Appearance
Issue a Cloud Credential
A Cloud Credential is a brokered secret owned by a Cloud. Issuing one writes the secret material into OpenBao KV-v2, records a broker row, and returns the credential's lifecycle metadata. The secret payload is accepted inbound only — no read surface ever returns it again, so keep your own copy if you need it elsewhere.
Prerequisites
- An authenticated session — see Log in with plexctl.
- A Cloud UUID. Issuing a credential needs the
managerelation on that Cloud — the Cloud is the residency pivot the issue gate authorises against. A caller withoutmanageis refused with403before the payload is ever read. - The secret bytes to store, in a file (or piped on stdin).
Steps
Write the provider's credentials document
The payload is the Crossplane provider's own credentials document. The provisioning broker copies it verbatim into the key credentials of the Secret the Cloud's ProviderConfig reads in each Project namespace, so write it in the format the provider expects. For provider-openstack it is a JSON object with the Keystone endpoint, the region and an application credential scoped to the one OpenStack project the machines land in:
json
{
"auth_url": "https://keystone.example.com/v3",
"region": "RegionOne",
"application_credential_id": "<application-credential-id>",
"application_credential_secret": "<application-credential-secret>"
}Keep the file out of version control and remove it once the credential is issued.
Issue with plexctl
shell
export PLEXSPHERE_URL="${PLEXSPHERE_URL:-https://localhost:8080}"
plexctl cloud credential create \
--server "${PLEXSPHERE_URL}" \
--cloud-id <cloud-uuid> \
--display-name "Acme AWS provisioner secret" \
--payload-file ./aws-provisioner.json \
--key-value role_arn=arn:aws:iam::123456789012:role/acme-provisionerThe command prints the metadata-only projection of the new credential (id, owning Cloud, display name, version 1, derived status active, and the lifecycle timestamps). Repeat --key-value for each key=value pair you want stored alongside the payload.
To avoid writing the secret to a file, pipe it on stdin with --payload-file -:
shell
printf '%s' "${SECRET_JSON}" | plexctl cloud credential create \
--server "${PLEXSPHERE_URL}" \
--cloud-id <cloud-uuid> \
--display-name "Acme AWS provisioner secret" \
--payload-file -Issue with the HTTP API
The payload field is base64-encoded secret bytes; key_values is an optional flat map. Both are accepted inbound only.
shell
curl --silent --show-error --fail-with-body -X POST \
-H "Authorization: Bearer ${TOKEN}" -H 'content-type: application/json' \
"${PLEXSPHERE_URL}/v1/clouds/<cloud-uuid>/cloud-credentials" -d '{
"display_name": "Acme AWS provisioner secret",
"payload": "'"$(base64 < ./aws-provisioner.json | tr -d '\n')"'",
"key_values": {"role_arn": "arn:aws:iam::123456789012:role/acme-provisioner"}
}'A 201 carries the new credential's metadata and a Location header holding its canonical read URL (/v1/cloud-credentials/<credential-uuid>).
Verify
Read the credential back — the projection is metadata-only and never includes the payload:
shell
plexctl cloud credential get <credential-uuid> --server "${PLEXSPHERE_URL}"Or list every credential the Cloud owns:
shell
plexctl cloud credential list --cloud-id <cloud-uuid> --server "${PLEXSPHERE_URL}"Troubleshooting
403— the caller lackscloud#manageon the parent Cloud, or the Cloud UUID is wrong. Issuing under an unknown Cloud fails the manage check first, so a missing Cloud also surfaces as403.400 invalid_display_name—display_namewas empty or whitespace-only.400 invalid_payload— the payload decoded to zero bytes (an empty file or empty stdin).413 request_body_too_large— the request exceeded the 8 KiB body ceiling. Large secrets should be referenced indirectly, not inlined.503 openbao_unavailable— OpenBao, where the credential is stored, is sealed or unreachable. Nothing was stored, so retry once OpenBao answers again; the API log carries the cause under the response'scorrelation_id.
Related
plexctl cloudreference — the fullcloud credentialcommand surface.- Cloud Credentials HTTP API — the issue, read, and revoke operations, the ReBAC gates, and the error taxonomy.
- Assign a Cloud Credential to a Project — bind an issued credential to a Project.