OCI Vault and Secrets Management
Do NOT load this skill when
Do not load this skill for unrelated general programming, non-Oracle cloud work, or questions covered by a narrower sibling skill.
When the request is only asking to find or install skills, use find-skills instead.
When to Use
Load this skill for: the user asks to "store OCI secrets", "rotate Vault secrets", "debug secret retrieval 403", "use instance principals for Vault", "replicate secrets", or "Terraform state secret".
Prefer this skill only for its named domain. For broader OCI architecture triage, start with oci/best-practices as the router.
NEVER Do This
❌ NEVER set temp key file permissions AFTER writing content
# WRONG - world-readable during write (security window exists)
with open('/tmp/key.pem', 'w') as f:
f.write(private_key)
os.chmod('/tmp/key.pem', 0o600) # Too late — race condition!
# RIGHT - secure BEFORE writing
fd = os.open('/tmp/key.pem', os.O_CREAT | os.O_WRONLY, 0o600)
with os.fdopen(fd, 'w') as f:
f.write(private_key)
❌ NEVER use overly broad IAM secret policies
BAD: "Allow any-user to read secret-family in tenancy"
BAD: "Allow group Developers to manage secret-family in tenancy"
GOOD: "Allow dynamic-group app-prod to read secret-family in compartment AppSecrets
where target.secret.name = 'db-*'"
❌ NEVER retrieve secrets without a cache or refresh strategy
- OCI Secret Management is listed as free, so cache for latency, resilience, throttling, and blast-radius control rather than request-cost savings.
- Keep TTL shorter than the rotation detection window.
- Force refresh on authentication failures that may indicate rotated downstream credentials.
❌ NEVER confuse Console plaintext with API payload encoding — Console plaintext entry is encoded before submission; API/SDK automation should send BASE64 secret content explicitly.
❌ NEVER assume Vault prevents Terraform state leakage — Terraform can still store secret values, generated passwords, wallets, private keys, or sensitive outputs in state and plan files. For Terraform work, pass secret OCIDs and let workloads retrieve secrets at runtime unless state exposure is explicitly accepted and protected.
❌ NEVER hardcode Vault OCIDs in code — store in environment variables; OCIDs leak to repos and aren't portable across tenancies
❌ NEVER log secret contents — even in debug/error messages; logs are retained in aggregation systems for years
IAM Permission Gotcha (Critical)
Secret retrieval requires BOTH of these:
"Allow dynamic-group X to read secret-family in compartment Y"
"Allow dynamic-group X to use keys in compartment Y"
read secret-family→ list secrets and read metadatause keys→ decrypt secret content (all secrets are encrypted with a master key)
Without use keys: Confusing 403 — "User not authorized to perform this operation." Hours of debugging because the error message doesn't mention key permissions.
Vault Hierarchy (Often Confused)
Vault (container)
└─ Master Encryption Key (for encryption/decryption)
└─ Secret (encrypted data)
└─ Secret Versions (rotation over time)
Commands use different services — this trips everyone up:
- Vault operations:
oci kms management vault ... - Key operations:
oci kms management key ... --endpoint <vault-management-endpoint> - Secret operations:
oci vault secret ...(NOToci kms!)
Common mistake: oci vault-secret create (no such command) vs oci vault secret create (correct)
Secret Retrieval Error Decision Tree
Secret retrieval fails?
│
├─ 401 Unauthorized
│ ├─ On OCI compute? → Check dynamic group membership
│ ├─ Local dev? → Check ~/.oci/config, verify API key uploaded
│ └─ After rotation? → Cache has old credentials (wait for TTL)
│
├─ 403 Forbidden
│ ├─ Have "read secret-family"? → Add if missing
│ └─ Have "use keys"? → THIS IS USUALLY THE ISSUE
│
├─ 404 Not Found
│ ├─ Wrong OCID? → Verify env variable
│ ├─ Wrong compartment? → Secrets client must use secret's compartment
│ └─ Secret deleted? → Check vault for secret status
│
└─ 500 Internal Server Error
└─ Vault rate limit → Retry with exponential backoff
Secret Rotation (Zero-Downtime)
# WRONG - creates new OCID, breaks all running apps
oci vault secret delete --secret-id <secret-ocid>
oci vault secret create ...
# RIGHT - create new VERSION of existing secret (OCID unchanged)
oci vault secret update-base64 \
--secret-id <secret-ocid> \
--secret-content-content "$(echo -n 'new-value' | base64)"
Apps pick up new version on next cache refresh — no restart needed. Old version retained for rollback.
Cache TTL Selection
| Security Requirements | Cache TTL | Reasoning |
|---|---|---|
| High (rotate daily) | 5-15 min | 90%+ savings, frequent refresh |
| Standard (rotate monthly) | 30-60 min | Balance security and cost |
| Dev/Test | No cache | Always fresh |
Rule: Cache TTL must be less than secret rotation window.
OCI-Specific Gotchas
Vault management endpoint is required for key operations:
# Find vault's management endpoint
oci kms management vault get --vault-id <vault-ocid> \
--query 'data."management-endpoint"' --raw-output
# Required for all key commands
oci kms management key create ... \
--endpoint https://xxxxx-management.kms.us-ashburn-1.oraclecloud.com
Secret bundle requires explicit base64 decode:
secret_bundle = secrets_client.get_secret_bundle(secret_ocid)
encoded = secret_bundle.data.secret_bundle_content.content
decoded = base64.b64decode(encoded).decode('utf-8') # Both steps required
Secret Management is available in OCI commercial regions — still verify special realms, sovereign regions, and cross-region replication requirements before designing architecture.
Use managed lifecycle features where possible:
- Automatic secret generation can reduce password-handling code.
- Automatic rotation supports service-managed rotation for supported targets.
- Cross-region replication can copy a secret to up to three destination regions for DR and locality.
Instance Principal Auth (Production Pattern)
# 1. Create dynamic group
oci iam dynamic-group create \
--name "app-instances" \
--matching-rule "instance.compartment.id = '<compartment-ocid>'"
# 2. Grant Vault access (both policies required — see IAM gotcha above)
# "Allow dynamic-group app-instances to read secret-family in compartment Secrets"
# "Allow dynamic-group app-instances to use keys in compartment Secrets"
# 3. Application code — no credentials needed on instance
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
secrets_client = oci.secrets.SecretsClient(config={}, signer=signer)
Reference Files
Load references/oci-vault-reference.md only when you need current Oracle documentation anchors for Vault/KMS, BASE64 secret content, automatic generation, rotation, promotion, or cross-region replication. Use the links in the reference instead of loading broad external docs.
Load ../infrastructure-as-code/references/oci-terraform-secrets-state.md when Terraform may write passwords, wallets, private keys, Vault secret content, stack variables, or sensitive outputs to state.
Arguments
$ARGUMENTS: Optional user-provided target, path, environment, symptom, or constraint. When empty, infer the narrowest safe scope from the current repository context and ask only if multiple high-impact choices remain.