Skip to content

plexctl domain-idp

plexctl domain-idp is the CLI surface over Domain IdP bindings. It groups seven operations against /v1/admin/idp and /v1/admin/idp/{id}/status:

  • plexctl domain-idp create — POST a new IdPBindingRequest.
  • plexctl domain-idp list — GET the optionally domain-filtered list of bindings.
  • plexctl domain-idp get — GET a single binding by id.
  • plexctl domain-idp update — PATCH a partial update of a binding's non-status fields.
  • plexctl domain-idp delete — DELETE a binding by id.
  • plexctl domain-idp enable — PATCH binding status to active.
  • plexctl domain-idp disable — PATCH binding status to deactivated.

Two safety contracts surface here:

  • Secret masking on output. Response fields whose JSON key matches (?i)secret|key|token are rewritten to *** in create, list, get, update, enable, and disable output. Pass --reveal-secrets to opt out; in that case a one-line warning is written to stderr and the invocation is audit-logged. The masking rule is the same one applied to config-redacted.json inside the support bundle so the two surfaces stay consistent.
  • File-only client secret on create. --client-secret MUST be passed as @<path> to a file holding the secret; an inline literal is rejected at parse time. The file content is read once and trimmed of trailing whitespace before being marshalled into the IdPBindingRequest.client_secret_ref field. This keeps the secret out of shell history, audit logs, and process listings.

update performs a partial PATCH: only the flags explicitly set on the command line are forwarded in the request body, and an invocation that sets none of the mutable flags is rejected client-side as exit 2 rather than issuing an empty round-trip. Status transitions are intentionally absent from update — they go through the dedicated enable and disable subcommands which hit /v1/admin/idp/{id}/status.

Synopsis

shell
plexctl domain-idp create  --domain-id <UUID> --client-id <ID> --client-secret @<PATH> \
                           --discovery-url <URL> --issuer <URL> --jit-policy allow|deny \
                           [--required-acr <VALUE>]... [--required-amr <VALUE>]... \
                           [--claim-mapping plexsphere_claim=idp_claim]...
plexctl domain-idp list    [--domain-id <UUID>] [--reveal-secrets]
plexctl domain-idp get     --id <UUID> [--reveal-secrets]
plexctl domain-idp update  --id <UUID> [--jit-policy allow|deny] [--discovery-url <URL>] \
                           [--required-acr <VALUE>]... [--required-amr <VALUE>]... \
                           [--claim-mapping plexsphere_claim=idp_claim]... [--reveal-secrets]
plexctl domain-idp delete  --id <UUID>
plexctl domain-idp enable  --id <UUID>
plexctl domain-idp disable --id <UUID>

Invocation

plexctl domain-idp create

POSTs an IdPBindingRequest to /v1/admin/idp. The CLI validates --jit-policy, parses --claim-mapping plexsphere_claim=idp_claim pairs, and rejects an inline literal --client-secret.

Flags

FlagTypeRequiredDefaultDescription
--domain-idUUIDyesOwning Domain UUID.
--client-idstringyesOIDC client identifier.
--client-secretstring (@<path>)yesFile spec; inline literals rejected. The file's trimmed contents become client_secret_ref.
--discovery-urlURLyesOIDC discovery document URL.
--issuerURLyesOIDC issuer URL.
--jit-policyenumyesJust-in-time provisioning policy: allow or deny.
--required-acrstring (repeatable)noRequired OIDC ACR value. May be passed multiple times.
--required-amrstring (repeatable)noRequired OIDC AMR value. May be passed multiple times.
--claim-mappingkey=value (repeatable)noMap a plexsphere claim to an IdP claim, e.g. email=preferred_email.

Persistent flags inherited from root: see plexctl.md. The root-level --reveal-secrets is honoured by create for masking fields on the IdPBindingResponse echoed back to stdout.

plexctl domain-idp list

GETs /v1/admin/idp. An optional --domain-id filter narrows the result set to a single Domain. The response masks (?i)secret|key|token fields unless --reveal-secrets is passed.

Flags

FlagTypeRequiredDefaultDescription
--domain-idUUIDnoOptional Domain filter.

Persistent flags inherited from root: see plexctl.md. The root-level --reveal-secrets controls whether secret-shaped fields are unmasked.

plexctl domain-idp get

GETs a single binding from /v1/admin/idp/{id}. The --id flag is parsed as a UUID before the wire call. The response masks (?i)secret|key|token fields unless --reveal-secrets is passed — the same masking applied by list and create.

Flags

FlagTypeRequiredDefaultDescription
--idUUIDyesBinding UUID.

Persistent flags inherited from root: see plexctl.md. The root-level --reveal-secrets controls whether secret-shaped fields are unmasked.

plexctl domain-idp update

PATCHes a partial mutation of a binding's non-status fields against /v1/admin/idp/{id}. Only the flags explicitly set on the command line are forwarded in the IdPBindingPatchRequest body; an invocation that sets none of --jit-policy, --discovery-url, --required-acr, --required-amr, or --claim-mapping is rejected client-side as exit 2 rather than issuing an empty PATCH. Status is not a settable field — use enable and disable for status transitions. The echoed IdPBindingResponse masks secret-shaped fields unless --reveal-secrets is passed.

Flags

FlagTypeRequiredDefaultDescription
--idUUIDyesBinding UUID.
--jit-policyenumnoJust-in-time provisioning policy: allow or deny.
--discovery-urlURLnoOIDC discovery document URL (absolute http/https).
--required-acrstring (repeatable)noRequired OIDC ACR value. Pass with no value to clear the list.
--required-amrstring (repeatable)noRequired OIDC AMR value. Pass with no value to clear the list.
--claim-mappingkey=value (repeatable)noMap a plexsphere claim to an IdP claim, e.g. email=preferred_email.

At least one of the five mutable flags must be set; an empty patch surfaces locally as exit 2 rather than a 400 empty-patch round-trip.

Persistent flags inherited from root: see plexctl.md. The root-level --reveal-secrets controls whether secret-shaped fields are unmasked.

plexctl domain-idp delete

DELETE /v1/admin/idp/{id}. The server returns 204 No Content on success.

Flags

FlagTypeRequiredDefaultDescription
--idUUIDyesBinding UUID.

Persistent flags inherited from root: see plexctl.md.

plexctl domain-idp enable

PATCH /v1/admin/idp/{id}/status with { "status": "active" }.

Flags

FlagTypeRequiredDefaultDescription
--idUUIDyesBinding UUID.

Persistent flags inherited from root: see plexctl.md.

plexctl domain-idp disable

PATCH /v1/admin/idp/{id}/status with { "status": "deactivated" }.

Flags

FlagTypeRequiredDefaultDescription
--idUUIDyesBinding UUID.

Persistent flags inherited from root: see plexctl.md.

Exit codes

CodeReachable fromMeaning
0every subcommandSuccess.
1every subcommandRuntime / API error (non-2xx response, body parse error).
2every subcommandFlag-parse / misconfiguration (missing required flag, malformed UUID, inline --client-secret without @ prefix, unknown --jit-policy, malformed --claim-mapping, empty update patch).
3every subcommandMissing or insecure credentials.
4every subcommandPermission denied (HTTP 403 from the server).

No domain-idp subcommand produces exit 64; the whole family is wired against the typed OpenAPI client.

Examples

Create a Domain IdP binding (file-only client secret)

shell
echo -n 'super-secret-from-okta' > /run/secrets/okta-client.secret
chmod 0400 /run/secrets/okta-client.secret

plexctl domain-idp create \
  --server "${PLEXSPHERE_URL}" \
  --domain-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1 \
  --client-id plexsphere-staging \
  --client-secret @/run/secrets/okta-client.secret \
  --discovery-url https://idp.example.com/.well-known/openid-configuration \
  --issuer       https://idp.example.com/ \
  --jit-policy   allow \
  --required-acr urn:mace:incommon:iap:silver \
  --required-amr mfa \
  --claim-mapping email=preferred_email \
  --claim-mapping groups=memberOf

The CLI rewrites client_secret_ref (and any other secret-shaped field) to *** on output. Pass --reveal-secrets to opt out.

List bindings for a Domain (default masked output)

shell
plexctl domain-idp list \
  --server "${PLEXSPHERE_URL}" \
  --domain-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1 \
  --output json
json
[
  {
    "id": "0190a8c1-...-a0a4",
    "domain_id": "0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1",
    "client_id": "plexsphere-staging",
    "client_secret_ref": "***",
    "discovery_url": "https://idp.example.com/.well-known/openid-configuration",
    "issuer": "https://idp.example.com/",
    "jit_policy": "allow",
    "status": "active"
  }
]

List bindings with secrets revealed (audit-logged)

shell
plexctl domain-idp list --reveal-secrets --domain-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1
# stderr: WARNING: --reveal-secrets is set; sensitive fields will be printed verbatim. This invocation is audit-logged.

Refusal: inline --client-secret (exit 2)

shell
plexctl domain-idp create \
  --domain-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1 \
  --client-id plexsphere-staging \
  --client-secret hunter2 \
  --discovery-url https://idp.example.com/.well-known/openid-configuration \
  --issuer https://idp.example.com/ \
  --jit-policy allow
# stderr: plexctl: --client-secret must be @<path>; reading secrets from argv is forbidden
echo "exit=$?"   # exit=2

Get a single binding (default masked output)

shell
plexctl domain-idp get \
  --server "${PLEXSPHERE_URL}" \
  --id 0190a8c1-1234-7a0a-8a0a-a0a0a0a0a0a4 \
  --output json
json
{
  "id": "0190a8c1-1234-7a0a-8a0a-a0a0a0a0a0a4",
  "domain_id": "0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0a1",
  "client_id": "plexsphere-staging",
  "client_secret_ref": "***",
  "discovery_url": "https://idp.example.com/.well-known/openid-configuration",
  "issuer": "https://idp.example.com/",
  "jit_policy": "allow",
  "status": "active"
}

Update a binding's JIT policy (partial PATCH)

shell
plexctl domain-idp update \
  --server "${PLEXSPHERE_URL}" \
  --id 0190a8c1-1234-7a0a-8a0a-a0a0a0a0a0a4 \
  --jit-policy deny

Only jit_policy is forwarded in the PATCH body; every other field is untouched. An invocation that sets none of the mutable flags exits 2:

shell
plexctl domain-idp update --id 0190a8c1-1234-7a0a-8a0a-a0a0a0a0a0a4
# stderr: plexctl: domain-idp update: at least one of --jit-policy, --discovery-url, --required-acr, --required-amr, --claim-mapping must be set
echo "exit=$?"   # exit=2

Cross-references

  • ../../../api/openapi/plexsphere-v1.yaml — OpenAPI 3.1 source of truth for /v1/admin/idp and /v1/admin/idp/{id}/status, plus the IdPBindingRequest, IdPBindingResponse, and IdPBindingStatusRequest schemas.
  • ../../contexts/identity/idp.md — bounded-context reference: claim-mapping rules, ACR/AMR step-up examples, JIT policy semantics, IdPBinding lifecycle.
  • ../../../cmd/plexctl/commands/domain_idp.go — source of truth for the masking regex ((?i)secret|key|token), the file-only --client-secret reader, the --reveal-secrets warning banner, and the partial-PATCH empty-patch guard on update.
  • plexctl.md — root command reference (persistent flags, profile resolution, shared exit-code taxonomy).