Appearance
plexctl credential
Synopsis
plexctl credential is the operator surface for the OpenBao Credential Broker pool and the per-Project Credential Assignment lifecycle. It spans two /v1 surfaces under a single cobra parent:
/v1/projects/{project_id}/credentials(list) and/v1/credentials/{id}(get, revoke, rotate) — the per-Project credential pool./v1/projects/{project_id}/credential-assignments(list, request) and/v1/credential-assignments/{id}/revoke— the assignment lifecycle under the nestedplexctl credential assignmentsubgroup. Approving and rejecting a request belongs toplexctl approval, not here.
text
plexctl credential <subcommand> [flags]
plexctl credential assignment <subcommand> [flags]Subcommands
plexctl credential list
GETs /v1/projects/{project_id}/credentials (the --project-id flag is required). Returns metadata only.
plexctl credential get <id>
GETs /v1/credentials/{id}. Returns metadata only.
plexctl credential revoke <id>
POSTs /v1/credentials/{id}/revoke. Requires --yes and a --reason audit-rationale string.
plexctl credential rotate <id>
POSTs /v1/credentials/{id}/rotate. The caller passes the new material payload via --material-file or --material-base64 (mutually exclusive). --expected-version carries the broker-row version the caller observed; a mismatch surfaces as 409 conflict. --ttl-seconds declares the lifetime budget for the refreshed credential. Optional --key-value flags carry flat provider-specific key/value pairs (repeatable).
plexctl credential assignment request
POSTs /v1/projects/{project_id}/credential-assignments. --project-id is required. The Cloud Credential to bind is named either directly by --cloud-credential-id, or indirectly by --cloud-id — in which case the server auto-selects the most recently issued eligible credential bound to that Cloud and runs the standard approval flow. Either form requires the Cloud the credential belongs to to already be usable in the Project — an approved Cloud Assignment — otherwise the request fails with 422 cloud_not_usable_in_project. A credential is only usable where both assignments are in place, so a request opened without the Cloud Assignment would be approved and still refused at deploy time. The --cloud-id form is checked twice: against the Cloud you named, and against the Cloud the auto-selected credential actually belongs to, which the credential-to-Cloud usage join may make a different one. The two flags are mutually exclusive: setting both, or neither, fails locally with a clear exit-2 error before the request is sent.
plexctl credential assignment grant
POSTs /v1/cloud-credentials/{id}/credential-assignments — the holder's push, and the counterpart to request. Both --cloud-credential-id and --project-id are required, and the server gates the call on cloudcredential#assign over the named credential: its owner, or a principal granted assigner on it.
Unlike a request, the assignment lands already approved and materialised, so the credential is usable in the Project the moment the command returns — there is no second party to wait for. That is deliberate rather than a shortcut: requesting and then approving one's own request is refused by the self-approval guard, so without this route a credential's owner could not place it in a Project at all.
The push carries the same Cloud Assignment prerequisite the request direction does: the receiving Project must already be able to use the Cloud the credential belongs to, otherwise the grant fails with 422 cloud_not_usable_in_project. Holding the credential lets you decide who spends it; it does not let you put a Project onto a Cloud its own assigner never approved. A --cloud-credential-id naming no credential fails with 422 credential_not_assignable.
There is no --cloud-id form here. The auto-select that resolves a Cloud to its newest eligible credential exists to spare the asking side a lookup it cannot make; a holder pushing a credential already knows which one. A second live assignment for the same (Project, Credential) pair fails with 409 duplicate_live_assignment.
plexctl credential assignment list
GETs /v1/projects/{project_id}/credential-assignments (the --project-id flag is required). Pagination is keyset-based via --cursor / --limit.
plexctl credential assignment revoke <id>
POSTs /v1/credential-assignments/{id}/revoke. Requires --yes and a --reason audit-rationale string. Either party may revoke: the server first checks assign on the Cloud Credential the assignment spends, and on that denial falls back to deploy on the consuming Project, so a Project deployer can hand the credential back without holding it. The call is refused only when both checks deny. Whichever party revoked, the same cloudcredential#uses tuple is removed and the audit row records which relation granted.
Deciding a request
plexctl credential assignment has no approve or reject subcommand. Approving and rejecting a Credential Assignment happens on the dual-control queue: plexctl approval list --kind credential_assignment shows the rows the caller may decide, and plexctl approval approve or plexctl approval reject takes the assignment id directly. See approval.md.
Flags
plexctl credential list
| Flag | Type | Required | Description |
|---|---|---|---|
--project-id | UUID | yes | Owning Project UUID. |
--limit | int | no | Maximum items per page (server default when zero). |
--cursor | string | no | Continuation token from a previous call. |
plexctl credential revoke <id>
| Flag | Type | Required | Description |
|---|---|---|---|
--reason | string | yes | Audit-recorded revocation rationale. |
--yes (persistent) | bool | yes | Required confirmation for the destructive operation. |
plexctl credential rotate <id>
| Flag | Type | Required | Description |
|---|---|---|---|
--expected-version | int64 | yes | Broker-row version the caller observed. |
--ttl-seconds | int64 | yes | Lifetime budget for the refreshed credential, in seconds. |
--material-file | path | conditional | Path to the new secret payload. Mutually exclusive with --material-base64. |
--material-base64 | string | conditional | New secret payload encoded as base64. Mutually exclusive with --material-file. |
--key-value | string slice | no | Optional flat KV pair in key=value form, repeatable. |
plexctl credential assignment request
| Flag | Type | Required | Description |
|---|---|---|---|
--project-id | UUID | yes | Owning Project UUID. |
--cloud-credential-id | UUID | conditional | Cloud Credential UUID to bind directly. Mutually exclusive with --cloud-id. |
--cloud-id | UUID | conditional | Cloud UUID whose newest eligible credential the server auto-selects. Mutually exclusive with --cloud-credential-id. |
plexctl credential assignment list
| Flag | Type | Required | Description |
|---|---|---|---|
--project-id | UUID | yes | Owning Project UUID. |
--limit | int | no | Maximum items per page (server default when zero). |
--cursor | string | no | Continuation token from a previous call. |
plexctl credential assignment revoke <id>
| Flag | Type | Required | Description |
|---|---|---|---|
--reason | string | yes | Audit-recorded revocation rationale. |
--yes (persistent) | bool | yes | Required confirmation for the destructive operation. |
Destructive subcommands
plexctl credential revoke and plexctl credential assignment revoke consume the persistent --yes flag — both reject the call without explicit confirmation.
Persistent flags inherited from root
--server, --profile, --token-file, --output, --yes, --reveal-secrets. See ../plexctl.md.
Exit codes
See ../plexctl.md#exit-code-taxonomy.
Examples
Rotate a Cloud Credential
shell
plexctl credential rotate 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1 \
--server "${PLEXSPHERE_URL}" \
--expected-version 3 \
--ttl-seconds 86400 \
--material-file /var/secrets/aws-key-2026-05.jsonRequest a Credential Assignment
The Project must already hold an approved Cloud Assignment for the Cloud this credential belongs to, otherwise the request fails with 422 cloud_not_usable_in_project:
shell
plexctl credential assignment request \
--server "${PLEXSPHERE_URL}" \
--project-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0c0 \
--cloud-credential-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1Request a Credential Assignment by Cloud ID
Name the Cloud instead of resolving a specific credential; the server auto-selects the newest eligible credential bound to it. The Cloud Assignment prerequisite applies here too, and is checked against both the Cloud you name and the Cloud the selected credential belongs to:
shell
plexctl credential assignment request \
--server "${PLEXSPHERE_URL}" \
--project-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0c0 \
--cloud-id 0190a8b8-a0c0-7a0a-8a0a-b0b0b0b0b0b0