BuildIdentity
Bind Workload Identity
Bind a capability to a SPIFFE workload: write the match policy, issue the token, and inspect the signed receipt.
You do not install SPIRE through Chio
Prerequisites
- A running chio kernel with a capability authority. See Installation.
- A workload whose SPIFFE ID you know, for example
spiffe://prod.chio/payments/worker. - One of the three delivery paths wired up (Envoy ext_authz, explicit attestation, or a verifier bridge). The policy and verification steps below are identical for all three.
Step 1: Write a WorkloadIdentityMatch Rule
Start from a rule that already enumerates the tools you want to gate, then add require_workload_identity. The match is additive: trust domain, path prefix, and credential kind all have to pass for admission.
rules:
payments_write:
enabled: true
default: block
allow:
- transfer_funds
- reconcile_ledger
require_workload_identity:
scheme: spiffe
trust_domain: prod.chio
path_prefixes:
- /payments/worker
- /payments/reconciler
credential_kinds:
- x509_svid
- jwt_svid
require_runtime_assurance_tier: attestedImportant field behavior:
- Omitting
credential_kindsaccepts any ofuri,x509_svid, andjwt_svid. Specify the accepted kinds to limit which credentials pass the rule. path_prefixesis a list of prefix strings, not globs. A workload at/payments/worker/shard-3matches/payments/worker.- Pairing
require_workload_identitywithrequire_runtime_assurance_tiergives you both "which workload" and "how strongly attested". The two requirements evaluate independently.
Soft match for gradual rollout
prefer_workload_identity instead of require_ during rollout. The kernel records a soft match on the receipt without denying the call, which lets you observe the identity population in your audit log before flipping to a hard requirement.Step 2: Issue an Identity-Bound Capability
Issuance can carry a runtimeAttestation block. The caller supplies the already-normalized assurance tier as part of that evidence; the authority does not derive it from the other fields. The trust policy (trusted_verifiers and the runtime_assurance tiers) is what later decides whether the asserted tier is honored, rebound, or rejected, stamping the capability with a minimum runtime-assurance constraint. Governed execution then re-checks that the presented evidence still clears the stamped tier.
Identity-bound issuance uses this endpoint: POST /v1/capabilities/issue on a trust-control cluster. The JSON body is an IssueCapabilityRequest carrying the subject public key, the scope, a TTL in seconds, and the runtimeAttestation evidence.
curl -X POST https://trust.example.com/v1/capabilities/issue \
-H "Authorization: Bearer $CHIO_TOKEN" \
-H "Content-Type: application/json" \
-d @issuance-request.json{
"subjectPublicKey": "7b0f6f63...",
"scope": {
"grants": [
{ "server_id": "payments", "tool_name": "transfer_funds", "operations": ["invoke"] }
]
},
"ttlSeconds": 300,
"runtimeAttestation": {
"schema": "chio.runtime-attestation.v1",
"verifier": "spire-agent",
"tier": "attested",
"issued_at": 1744537800,
"expires_at": 1744538100,
"evidence_sha256": "…",
"workload_identity": {
"scheme": "spiffe",
"credentialKind": "x509_svid",
"uri": "spiffe://prod.chio/payments/worker",
"trustDomain": "prod.chio",
"path": "/payments/worker"
}
}
}Fail-closed on conflict
workloadIdentity and a raw runtimeIdentity that do not agree, or if the SPIFFE URI is malformed, issuance fails. Do not wrap this in a retry. Fix the upstream and reissue.Step 3: Verify the Binding on the Receipt
Every governed admission that clears a workload-identity check records the accepted workloadIdentity object on the signed receipt. A reviewer can inspect the signed receipt to see which workload made the call.
chio --json receipt explain rct-01hxab...
# Prints the allow/deny reasoning and lineage for one receipt, including
# the recorded runtime_assurance block:
# {
# "receiptId": "rct-01hxab…",
# "verdict": "allow",
# "capabilityId": "cap-7b0f…",
# "runtime_assurance": {
# "schema": "chio.runtime-attestation.spiffe.x509-svid.v1",
# "tier": "attested",
# "verifier": "spire-agent",
# "evidenceSha256": "…",
# "workloadIdentity": {
# "scheme": "spiffe",
# "credentialKind": "x509_svid",
# "uri": "spiffe://prod.chio/payments/worker",
# "trustDomain": "prod.chio",
# "path": "/payments/worker"
# }
# },
# "signature": "ed25519:…"
# }If you run an auditor pipeline, filter receipts by runtime_assurance.workloadIdentity.uri to get the exact set of admissions a particular workload made. The receipt query API exposes this filter.
Runtime-Attestation Appraisal
Raw runtimeAttestation evidence rides on the governed and issuance requests. A separate, adapter-facing contract normalizes it into a runtime-attestation appraisal. It carries the verifier family, an evidence descriptor, normalized assertions, and reason codes for cross-organization verifiers and auditors.
Export an appraisal locally from an evidence payload, optionally passing a HushSpec policy to evaluate its policy-visible outcomes:
chio trust appraisal export \
--input runtime-attestation.json \
--policy-file policy.yamlRemote deployments produce the same report over HTTP at POST /v1/reports/runtime-attestation-appraisal. A signed appraisal result can be exported for a partner (chio trust appraisal export-result or POST /v1/reports/runtime-attestation-appraisal-result) and evaluated on import against local policy (chio trust appraisal import or POST /v1/reports/runtime-attestation-appraisal/import). Imported results are defended by signature and freshness today; there is no replay registry for them yet.
Rebinding to verified via Trusted Verifiers
Raw attestation evidence lands at the attested tier by default. To let a rule require verified, add an explicit trusted_verifiers entry that binds a {schema, verifier} pair to an effective tier. This keeps verifier trust in a policy extension instead of individual rules.
extensions:
runtime_assurance:
tiers:
verified:
minimum_attestation_tier: verified
max_scope:
operations: ["invoke"]
ttl_seconds: 300
trusted_verifiers:
spire_prod:
schema: chio.runtime-attestation.spiffe.x509-svid.v1
verifier: https://spire.prod.internal
verifier_family: spiffe
effective_tier: verified
max_evidence_age_seconds: 120
allowed_attestation_types: [x509_svid]With this in place, a rule that sets require_runtime_assurance_tier: verified admits only calls whose attestation matches a trusted-verifier rule and satisfies its freshness and claim constraints.
Fail-Closed Conditions
The kernel denies admission, not warns, when any of the following hold. Matching operator recovery guidance lives in WORKLOAD_IDENTITY_RUNBOOK in the reference tree.
| Condition | What to do |
|---|---|
| Explicit workloadIdentity conflicts with raw runtimeIdentity | Fix the upstream so both agree; do not mask the conflict at the kernel. |
| SPIFFE URI is malformed (missing trust domain, empty path) | Regenerate the SVID from SPIRE or your attestation source; inspect the exact string. |
Presented identity fails require_workload_identity | Either add the workload to the allowed prefixes, or accept the deny. Do not relax the match to get past one call. |
Evidence older than max_evidence_age_seconds | Refresh the upstream attestation and resend. Do not extend the age ceiling to bypass freshness. |
| Verifier bridge projects a non-SPIFFE identifier | Fix the projection rule on the bridge. Chio will not invent a typed identity from an opaque string. |
Summary
- Write the rule. Add
require_workload_identitywith an explicit trust domain, path prefix set, and credential kind set. - Issue with attestation. Pass
runtimeAttestationon issuance so the capability is stamped with the minimum runtime-assurance tier. - Verify on the receipt. The accepted
workloadIdentityappears under the kernel signature; audit pipelines query on it directly. - Rebind to verified when needed. Use
trusted_verifiersto promote raw attestation into theverifiedtier under explicit operator policy.
Next Steps
- Workload Identity (concept) · the normalized shape and why SPIFFE is canonical
- Envoy ext_authz · the mesh delivery path for SPIFFE principals
- Policy Schema · the full
WorkloadIdentityMatchcontract - Rotate Keys & Revoke · what to do when a workload's identity material changes