ACE-U field notes
Practical secrets with OCI Vault: creation, rotation, and usage
Storing application credentials in Vault and rotating them without writing custom scripts everywhere.
Problem
A database password in an environment variable or a config file is a leak waiting for a screenshot, a log line or a copied image. The harder question is operational: who creates the secret, how does the app read it, and what happens when it changes?
I wanted one flow that answers all three, so rotation is a normal event instead of a project.
Options and trade-offs
- Secrets in files or environment variables: fast to start, and prone to leaks and drift.
- A non-OCI secret store: a good option if you already run one, with extra integration and policy work.
- OCI Vault secrets: IAM-governed, versioned, with rotation options. It needs deliberate policies and a read path.
My recommendation
Create the secret in a vault, with a master encryption key in the same vault, and let the application read the current version at runtime using an instance or resource principal. Rotate sensitive credentials on a schedule and watch the audit log for reads.
Worked example
Reading a secret from Java with an instance principal. Secret content comes back base64 encoded, so decode it and keep it in memory.
var provider = InstancePrincipalsAuthenticationDetailsProvider.builder().build();
try (var secrets = SecretsClient.builder().build(provider)) {
var req = GetSecretBundleRequest.builder()
.secretId(System.getenv("DB_SECRET_OCID"))
.stage(GetSecretBundleRequest.Stage.Current)
.build();
var content = (Base64SecretBundleContentDetails)
secrets.getSecretBundle(req).getSecretBundle().getSecretBundleContent();
byte[] password = java.util.Base64.getDecoder().decode(content.getContent());
// use the bytes, then discard them; do not log them
}
The policy that lets only the runtime read that one secret:
Allow dynamic-group app-runtimes to read secret-bundles in compartment apps
where target.secret.id = '<db_secret_ocid>'
Rotation can be configured on the secret with an interval, or driven through a function that updates the target system, such as an Autonomous Database user, and then writes a new secret version. Because every version has a stage such as current or previous, you can roll back by pointing readers at the earlier version while you investigate.
Checklist
- Create the secret with a key in the same vault.
- Authorize only the runtime principal to read secret bundles.
- Decode at runtime, hold the value in memory and never log it.
- Turn on rotation for credentials that matter.
- Alert on unusual GetSecretBundle activity in the audit log.
- Write down how to restore the previous version if a rotation fails.
Where this doesn't apply
One-time tokens that never need to be read again do not need a vault entry. Very large blobs may also exceed the secret size limit, so check the current limit before choosing Vault for them.
One honest limitation
Rotation and cross-region replication add moving parts. I rehearse a rotation in a test environment before the first production run.
Sources
- OCI Documentation: Vault, Creating a Secret
- OCI Documentation: Updating a Secret and Secret Rotation
- OCI Documentation: Retrieving a Secret Bundle (Java SDK)