DEMO/Infrastructure

← Back to dashboard

What the Password Safe public API can and cannot do

Audience: operator · Profile: both · Read this when: you need to know what the dashboard can do through Password Safe's public API, and what it has to leave to the console.

Part of BeyondTrust Password Safe.

Researched against BeyondTrust's own endpoint tables — the BeyondInsight APIs and Password Safe APIs references — while scoping the POV readiness panel. Recorded here so nobody has to establish it twice, and so a plan that assumes "we can automate the console" gets corrected before it is written.

Creatable:

Object Call
User groups, their permissions and memberships POST UserGroups, POST UserGroups/{id}/Permissions, .../Users
Workgroups POST Workgroups
Assets POST Workgroups/{workgroupID}/Assets
Address groups and their addresses POST AddressGroups
API registrations POST
Users POST Users
Functional accounts POST FunctionalAccounts — already used by pov_functional_account
Directory managed systems POST Workgroups/{id}/Directories
Managed accounts POST ManagedSystems/{systemID}/ManagedAccounts
Attributes and attribute types POST
Smart Rules — one shape only POST SmartRules/FilterAssetAttribute

Actionable:

Action Call
Re-process a Smart Rule POST SmartRules/{id}/Process — used by pov_ps_config.process
Rotate a managed account's credential POST ManagedAccounts/{id}/Credentials/Change
Test an access policy POST AccessPolicies/Test

Not creatable — read-only, or no endpoint at all:

Object State
Resource zones, resource brokers no endpoint of any kind. Independently confirms why ps_application_host_id was never the broker handle — see docs/profiles/pov/design/resource-broker.md §6
Discovery credentials no endpoint
Discovery scans no endpoint; run from the console
Directory queries no endpoint
Password policies read-only
Access policies read, plus the Test above
Applications read-only
Smart Rules, generally read, delete and process; create is the one narrow shape above

The practical consequence: the engine of a Password Safe POC — an authenticated discovery scan and the Smart Rules that act on its results — cannot be built by this dashboard. What it can do is verify the work and re-run a rule, which is what pov_ps_config does.

Absence from the documentation is not proof of absence from the product, and most of the table above was not checked against a live tenant. The _probe helper in ps_api_service is built for that uncertainty: a 404 is reported as "this Password Safe version does not serve that endpoint" rather than as a failure, so a tenant that does serve one of these shows up as readable instead of broken.

Assets and attributes — verified live, 2026-09-23

This is contributor-level API evidence. For using attributes, see Inventory — Password Safe attributes.

Building the /inventory attributes column settled four of these against a real tenant. All four were guesses before, and two of them were wrong:

Call Result Note
GET Assets 404 There is no flat asset collection.
GET Workgroups/{id}/Assets 200 Assets are workgroup-scoped on read, matching the POST. Reading them all means one call per workgroup.
GET AttributeTypes 200 The vocabulary — Criticality, Business Unit, Geography, Status, Operating System, Retire Date, Workgroup, Manufacturer.
GET Attributes 404 No flat attribute collection either.
GET Assets/{id}/Attributes 200 Per object, which is why the read is capped and only matched objects are fetched.
GET ManagedSystems/{id}/Attributes 200 Exists, and is commonly empty.
POST/DELETE ManagedSystems/{id}/Attributes/{attributeID} unverified Documented by BeyondTrust; not yet exercised against a tenant from here. See the write note below for what the dashboard does about that. The SPIRE lab's Prepare probe is the first caller that will. It also calls POST AttributeTypes and POST AttributeTypes/{id}/Attributes when the tenant lacks SpiffeTrustDomain, and its job log records every call's status, so its first live run settles all three rows.

An attribute's shape is easy to read backwards, and doing so produces chips that look broken. A row is:

{"AttributeID": 10000, "AttributeTypeID": 10000, "ShortName": "Online",
 "LongName": "Online", "ValueInt": 0, "ChildAttributes": []}

ShortName is the value; the type is the category it was chosen from. So AttributeTypeID 10000 + ShortName "Online" renders as Status = Online — not Online = "". The type is also the half SmartRules/FilterAssetAttribute keys on, so losing it loses the point. ps_attribute_catalog.to_chips takes the AttributeTypes map for exactly this.

Writing an attribute — verified live the same day. POST and DELETE on Assets/{assetID}/Attributes/{attributeID} both work; a DELETE of an attribute the asset does not carry answers 404, which the dashboard treats as success (the caller asked for it gone and it is gone, so a retry after a partial apply does not report errors for the targets that already succeeded).

Managed systems take attributes too, and that is the path that matters here. ManagedSystems/{managedSystemID}/Attributes/{attributeID} is the same POST/DELETE shape in a different collection. It is the one most of /inventory needs: everything this dashboard onboards lands as a managed system, so while the write path was asset-only, most matched rows could have their attributes read and never changed.

One asymmetry follows from the table above: the managed-system read is verified and the write is not. So the 404-is-success rule cannot simply be reused — an appliance that does not serve the endpoint at all answers 404 to exactly the same DELETE. Before accepting a 404 as "already gone", ps_api_service._set_object_attribute issues one GET {collection}/{id}/Attributes: a 200 proves the endpoint family exists and the attribute is genuinely absent, anything else is reported as a failure. Reporting a removal that never happened is the worse of the two errors by a wide margin.

A resource matched to both an asset and a managed system gets the change written to both records. They are separate rows in Password Safe and can disagree; the inventory page's chips flatten them into one, so writing to only half means a removal leaves the chip on screen and reads as a failed write.

An attribute is assigned, not typed: a type owns a fixed set of values, each with its own AttributeID, so GET AttributeTypes/{id}/Attributes is the picker and there is no free text anywhere in the write path. Some types are IsReadOnly: true — Criticality is, in the tenant checked — and the dashboard refuses those by name rather than letting Password Safe refuse them once per target in a bulk apply.

An asset's address is not guaranteed usable. In the tenant checked, 33 of 35 assets carried a routable IPAddress; the other two carried an IPv6 link-local (fe80::…), which cannot identify a host. Separately, every managed system this dashboard onboards through a cloud-native plugin carries the 127.0.0.1 placeholder with a packed locator in DnsName — so it has no usable address at all, and is matched by the ps_managed_system_id recorded on its deploy job instead. See ps_attribute_catalog.