Access Control
KeyPolicy, principals, OIDC roles, attestation profiles, and live human approvals for Enclave Vaults.
Every key in Enclave Vaults carries a KeyPolicy that controls who can do what, under which attestation conditions, and with which approvals. The policy is part of the sealed state of the vault and is enforced inside the enclave on every call. There is no admin override.
Principals
The vault recognises three kinds of principal.
| Principal | Authentication | Typical role |
|---|---|---|
| OIDC subject | Bearer JWT validated against the configured issuer and audience via JWKS | Owner, manager, auditor (humans or service accounts). |
| Attested enclave | Mutual RA-TLS; the caller's SGX or TDX quote, MRENCLAVE, and config Merkle root are extracted from the peer X.509 certificate | A CI runner, a confidential VM, another enclave. |
| FIDO2 wallet credential | Signed IssueApprovalToken request from a registered Privasys Wallet | Live human approval for sensitive operations. |
A single call may need to satisfy several principals at once (for example, a calling enclave with the right MRENCLAVE, a manager OIDC token, and a fresh wallet approval).
OIDC roles
The default OIDC roles checked by the vault. Custom roles can be added per deployment.
| Role | Operations |
|---|---|
vault:owner | Create and delete keys, update KeyPolicy, list keys, run any operation on owned keys, drive the pending-profile lifecycle (StagePendingProfile, PromotePendingProfile). |
vault:manager | Issue ApprovalTokens for operations that require live approval. Cannot read, create, or modify keys. |
vault:auditor | Read the audit log. Cannot perform any operation on keys. |
The split between owner and manager is intentional. It keeps a defence-in-depth boundary even if the owner identity is compromised, because sensitive operations still require a separate manager approval.
KeyPolicy
The policy attached to each key is organised into three independent surfaces.
principals
Who is recognised at all for this key: the owner, optional managers, optional auditors, plus optional TEE, FIDO2, and mTLS principals. A principal that is not listed here cannot influence the key in any way.
operations
Per-operation rules of the form "operation X is allowed for principal P when condition C holds". Conditions are composable:
| Condition | Meaning |
|---|---|
AttestationMatches(profile) | The caller presented an RA-TLS certificate whose quote matches profile. |
ManagerApproval { manager, fresh_for } | A ManagerApproval token from manager, signed within fresh_for, accompanies the request. |
TimeWindow { from, until } | The current time is inside the window. |
CallerHoldsRole(role) | The caller's OIDC token includes role. |
All(...), Any(...), Not(...) | Boolean combinators. |
The same operation can have several rules, and all matching rules must succeed for the operation to be allowed.
mutability
Which fields of the policy can change, and under what conditions. The schema separates fields the owner can edit unilaterally, fields the owner can edit only with a quorum of manager approvals, and fields that are immutable for the life of the key. For example, on a platform-managed key, the platform's manager identity is allowed to add a new MRENCLAVE to the attestation profile but cannot change the owner or change auto_migrate_to_next_attestation_profile.
Attestation profiles
An attestation profile describes what a calling enclave must look like.
| Field | Purpose |
|---|---|
mrenclave | Required SGX MRENCLAVE (hex). |
mrsigner | Optional SGX MRSIGNER (hex). Useful for accepting any release signed by a known build pipeline. |
mrtd | TDX measurement, for confidential VM callers. |
config_merkle_root | Optional commitment to the caller's runtime configuration. Lets the policy require not just the right code, but the right configuration of that code. |
required_oids | List of (oid, expected_value) claims that must appear in the caller's RA-TLS certificate. |
A KeyPolicy typically lists more than one profile (for example, "the production CI enclave plus the on-call recovery enclave") so that operations can continue across deploys without policy churn.
Approval tokens
For operations that require a live human approval, the manager issues an ApprovalToken against a specific key handle and operation:
IssueApprovalToken {
key_handle: "k-7f3...",
operation: "Sign",
not_before: 2026-04-29T10:00:00Z,
not_after: 2026-04-29T10:05:00Z,
nonce: <random>,
signed_by: <wallet FIDO2 credential>
}The token is signed by the manager's FIDO2 credential through the Privasys Wallet and carries a short TTL. The wallet performs a fresh user-presence ceremony for each token. The vault verifies the signature, the nonce, the TTL, the key handle, and the operation name before counting the token towards the policy's ManagerApproval requirement.
A manager compromised on its own cannot use a stolen token outside its TTL. A calling enclave compromised on its own cannot mint a token. Both must cooperate, and the audit log records every issued and consumed token.
How a typical call is evaluated
For a sensitive Sign call by a CI enclave:
- The CI enclave opens a mutual RA-TLS channel to a vault. The vault verifies that the CI enclave's MRENCLAVE matches at least one
attestation_profileon the key. - The CI enclave's request envelope carries an OIDC bearer token. The vault verifies the token via JWKS and reads
subandroles. The owner check passes. - The request includes one or more
ApprovalTokens from the manager. The vault verifies each (signature, TTL, key handle, operation, nonce). The count must reach the policy's manager-approval threshold. - The vault performs the
Signoperation inside the enclave. The signature is returned to the caller. The raw key never leaves the enclave. - Every step is appended to the audit log.
If any check fails, the operation is refused and the failure is logged.
Auditability
Read access to the audit log requires the vault:auditor role and a mutual RA-TLS channel. Each entry is hash-chained to the previous one, so an auditor can detect tampering with the log itself. Streaming export of the log to an external append-only store is on the roadmap; today the log is pulled on demand.
Why this is more than RBAC plus attestation
Classical RBAC says "this user can do this thing". The vault adds two orthogonal axes:
- The calling code's identity must match. Not just the user, but the exact enclave binary that is acting on the user's behalf. This is what eliminates "secret leaked from a CI runner" as a threat.
- A fresh act of human consent can be required. Not a long-lived token, but a per-operation FIDO2 ceremony on a phone. This is what eliminates "compromised long-lived credential" as a threat for the operations you care most about.
Combined with the per-vault sealed storage and (for RawShare keys) the Shamir distribution that prevents any single vault from leaking a secret on its own, these properties produce a system where the cost of misuse is high enough to actually deter it, even against a determined insider.