Trust domains¶
A person and a workload must never be confusable. A workload that could present as a person, or inherit a person's grants, would turn a leaked service credential into an operator's access. port49 makes the difference structural rather than checking a name.
The rule¶
A principal's trust domain is whichever verifier validated its credential. Configuration declares
the verifiers in two lists, broker.identity.humans and broker.identity.machines
(port49d reference), and nothing else classifies. A claim inside a
token, a naming convention or a group never decides.
broker:
identity:
issuance: {} # an OIDC person's ID token is taken to issue a certificate
humans:
- type: x509
trust_anchor_file: <people-ca.pem>
- type: oidc
issuer: https://login.example.com
client_id: <client_id>
principal_claim: email
principal_domains: [example.com]
machines:
- type: x509
trust_anchor_file: <workload-ca.pem>
spiffe_trust_domains: [example.org]
- type: k8s
issuer: https://kube.example.com
cluster: us_east
jwks: https://kube.example.com/openid/v1/jwks
audience: port49
namespaces: [netops]
The values are placeholders; the full key list is in the reference.
issuance: {} turns on certificate issuance with its defaults. The broker refuses an OIDC human verifier
without it. The one exception is an OIDC verifier that sits beside an x509 human verifier and serves only as
a per-login MFA proof.
What follows from the rule¶
- A credential no verifier accepts is refused at mint. The reason is
trust_domain_unresolved. The same reason covers a certificate whose revocation status cannot be established whenbroker.certificate_status.on_unavailableisrefuse. See Reason codes for the full meaning. - A credential two verifiers accept is refused. There is no tie-break. A person's delegated token is never a machine's, and two issuers never give one principal.
principal_domainsbounds who a provider may name. An OIDC human verifier lists the domains whose people it may name (user:<name>@<domain>), and has no default. Another provider cannot name someone in your domains, even with a claim that looks right.principal_claimlikewise has no default: set it to a claim only your provider's administrators can write.- The same issuer may serve both lists with a different audience. An identity provider that issues
tokens to people and to applications uses one issuer for both.
client_idnames the public client whose ID token a person presents;audiencenames the API in the access token a service obtains. Both are checks onaud, and the list the token matched decides the domain. - Certificate anchors may not overlap. The handshake verifies against both anchors, and the one the
chain ends at is the domain. A chain that ends at both is refused at the TLS handshake. That leaves a
line in the broker's log and a count of
identity_refusedhandshake failures, not a decision record. Put the two anchors in unrelated hierarchies. The broker refuses to start if one anchor directly signs the other, and refuses at a request whose chain shows a deeper overlap. - A workload never authenticates with a directory password. The password sign-in refuses a workload's
entry, and the verifier's
filterkeeps a person-shaped service account out. - Directory groups reach a workload only as a machine group. A workload can be mapped to a directory
entry for membership, opt in per verifier, and the membership reaches only a
machine_group:subject, never a person's. So a workload cannot inherit a person's grants by any route.
What is trusted, and what is not¶
| Inside the domain | Outside it |
|---|---|
| the verifier's trust anchor, or the provider's published keys | any other CA or provider, even if it names the same user |
| the principal that verifier derived (a certificate's mapped entry, an OIDC principal claim, a SPIFFE ID, a service account name) | a group or role asserted by the credential |
| a directory entry the principal maps to exactly once | a name that matches more than one entry, which denies |
Policy identity strings carry the domain in their form, so a policy test can check the distinction in CI without any credential in hand. See Policy.
Your own trust domain¶
port49 is a relying party, not a certificate authority, with one exception: the short-lived certificate it issues a person after an OIDC or directory-password sign-in. That is port49's own trust domain. Only the broker that issued it reads it, no device ever sees it, and its CA lives in the broker's state directory and rotates with overlap.