Secure agentic workflows
Enterprise
Appropriate Vault Enterprise license or HCP Vault Dedicated cluster required.
Use Vault Enterprise and your ID provider to implement zero trust principles with narrowly scoped agent credentials.
Before you start
You must have a Vault Enterprise or HCP Vault Dedicated server deployed.
You must configure a supported identity or OAuth provider:
You must have admin permissions on Vault. You need a Vault token with sufficient ACL policies attached to configure and modify your Vault deployment.
Step 1: Create an OAuth resource server profile
Create an OAuth resource server configuration file called
verify-oauth.jsonusing the environment variables you saved during provider setup:$ cat > verify-oauth.json << EOF { "issuer_id": "${ISSUER}", "use_jwks": true, "user_claim": "sub", "supported_algorithms": ["RS256"], "jwks_uri": "${JWKS_URI}" } EOFCreate an OAuth resource server profile using the JSON file:
$ vault write sys/config/oauth-resource-server/verify @verify-oauth.json WARNING! The following warnings were returned from Vault: * algorithm "RS256" is functional but consider using PS256 (RSA-PSS) for better security * profile supports only one algorithm family - consider supporting multiple families for flexibilityRead the profile to check for correctness.
$ vault read sys/config/oauth-resource-server/verify Key Value --- ----- audiences [https://localhost:8200/v1] clock_skew_leeway 0 config_id de81dc66-e00d-23c6-7dfc-9cdbc5aaf97e enabled true issuer_id https://mydomain.verify.ibm.com/oauth2 jwks_uri https://mydomain.verify.ibm.com/oauth2/jwks jwt_type access_token no_default_policy false profile_name verify supported_algorithms [RS256] use_jwks true
Step 2: Map your external identity to a Vault entity
Create a Vault entity for the external user.
Create a new entity for the AI agent user:
$ vault write identity/entity name="obo-agent" external_id="${ACTOR_EXT_ID}" Key Value --- ----- aliases <nil> id ef897bd9-0060-1fa4-68ba-65ae5b0747ec name obo-agentSave the IDs created for the human and agent entities to environment variables:
$ export AGENT_CANONICAL_ID="ef897bd9-0060-1fa4-68ba-65ae5b0747ec"
Step 3: Create entity aliases
Create an alias for the newly created Vault entity.
Normally, creating an entity alias requires a mount_accessor value. If you
provide both an external ID and an issuer that matches your OAuth resource
server profile, Vault synthesizes the correct mount accessor for you when you
create aliases for agentic IAM.
Instead of associating the generated alias with an auth mount, the alias points to the issuer that grants access for the alias. Vault uses the following format for the mount accessor synthesis:
oauth-resource-server + _ + <namespace ID> + _ + <server profile config ID>
For example, a mount accessor in the root namespace would be:
oauth-resource-server_root_de81dc66-e00d-23c6-7dfc-9cdbc5aaf97e
Create an entity alias for the agent entity:
$ vault write identity/entity-alias \ name="jwt-binding-actor" \ canonical_id="${OBO_AGENT_CANONICAL_ID}" \ issuer="${ISSUER}" \ external_id="${ACTOR_EXT_ID}" Key Value --- ----- canonical_id ef897bd9-0060-1fa4-68ba-65ae5b0747ec id e929f437-f655-45c0-03e7-eb6212dba58dSave the alias ID to an environment variable. Do not use the canonical ID:
$ export ALIAS_ID="e929f437-f655-45c0-03e7-eb6212dba58d"
Step 4: Create a ceiling policy
Create a ceiling policy to encompass all the possible operations the agent might perform.
Create a policy configuration file called
ceiling-policy.hcl. For example, to restrict access on thekv,pki, andtransitplugins:$ cat > ceiling-policy.hcl << EOF # Allow KV2 read and write path "secret-v2/data/shared-secret/*" { capabilities = ["read", "list"] } path "secret-v2/metadata/shared-secret/*" { capabilities = ["list"] } # Allow PKI operations path "pki/issue/example-dot-com" { capabilities = ["create", "update"] } path "pki/cert/*" { capabilities = ["read"] } path "pki/certs" { capabilities = ["list"] } # Allow transit engine operations path "transit/encrypt/app-key" { capabilities = ["update", "create", "read"] } # Allow decrypt path "transit/decrypt/app-key" { capabilities = ["update", "create", "read"] } # Optional: allow key metadata read (safe) path "transit/keys/app-key" { capabilities = ["read"] } EOFWrite the ceiling policy to Vault:
$ vault policy write ceiling-all ceiling-policy.hcl Success! Uploaded policy: ceiling-all
Step 5: Register the agent with Vault
Create an entry in the Vault agent registry using the entity canonical ID and your ceiling policy:
$ vault write agent-registry/register \
display_name="<ai_agent>-iam" \
entity_id="${AGENT_CANONICAL_ID}" \
ceiling_policies='["ceiling-all"]'
For example:
$ vault write agent-registry/register \
display_name="claude-iam" \
entity_id="${AGENT_CANONICAL_ID}" \
ceiling_policies='["ceiling-all"]'
Key Value
--- -----
display_name claude-iam
id ef897bd9-0060-1fa4-68ba-65ae5b0747ec
Step 6: Validate the token flow
Use the new agent alias to mint and validate token creation in Vault.
Create an authorization request file for the
kvplugin calledkv-token.json:{ "type" : "vault:path_access", "path": "secret-v2/data/shared-secret/foo", "capabilities": ["create", "update", "read"] }Use
curlto request a token from Verify and save it to an environment variable:$ export AGENT_TOKEN=$(curl --request POST \ --variable authz_request=[@kv-token.json] \ --expand-data \ --data 'authorization_details=[{{authz_request}}]' \ ${ISSUER} | jq -r '.access_token)Use the minted token with
vault token lookupto verify your configuration. Vault validates the token against the OAuth resource server config profile, resolves the entity alias, and returns the default policy:$ VAULT_TOKEN=${AGENT_TOKEN} vault token lookup
Step 7: Validate Vault operations
You can use KV version 2 operations with the minted tokens to validate the ceiling policies.
Enable a KV version 2 secrets engine at the path
secret-v2.$ vault secrets enable -path=secret-v2 kv-v2 Success! Enabled the kv-v2 secrets engine at: secret-v2/ Create a policy to perform KV operations and link it to the subject entity.Write a secret to the
kvplugin as yourself:$ vault write \ secret-v2/data/shared-secret/test \ secret_author="I am human"Try to use the original minted token to write a
kvsecret:$ VAULT_TOKEN=${AGENT_TOKEN} vault write \ secret-v2/data/shared-secret/test \ secret_author="I am an AI agent" Error writing data to secret-v2/data/shared-secret/test: Error making API request. URL: PUT http://127.0.0.1:8200/v1/secret-v2/data/shared-secret/test Code: 403. Errors: * 2 errors occurred: * RAR_NO_MATCH: No valid authorization_details claim found matching this request. * permission deniedThe write fails because the ceiling policy does not allow writes to
kv.Use the original minted token to read the
kvsecret:$ VAULT_TOKEN=${AGENT_TOKEN} vault read secret-v2/data/shared-secret/test Key Value --- ----- data map[secret_author:I am human] metadata map[created_time:2026-06-11T08:04:13.817972Z custom_metadata:<nil> deletion_time: destroyed:false version:2]