Home / OCI

OCIHow-toIntermediate

Moving application passwords into OCI Vault secrets

Store database passwords and API keys as OCI Vault secrets, let instances read them with instance principals, and rotate them without redeploying.

Deepak Bhardwaj2 min read

Applies toOCI Vault (KMS) and Secrets, OCI CLI 3.x, Python SDK

When a customer's config file holds a plaintext database password, move it into OCI Vault. The application then fetches it at start-up with its instance identity, so no keys sit on disk.

1. Create the vault, key and secret

oci kms management vault create --compartment-id $C --display-name prod-vault --vault-type DEFAULT
# use the vault's management endpoint for key operations
oci kms management key create --compartment-id $C --display-name app-secrets-key \
  --key-shape '{"algorithm":"AES","length":32}' --endpoint <management-endpoint>

oci vault secret create-base64 --compartment-id $C --vault-id $VAULT --key-id $KEY \
  --secret-name orders-db-password \
  --secret-content-content "$(printf '%s' 'S3cure-Pass!' | base64)"

2. Let the application read it

Create a dynamic group for the app's instances:

ALL {instance.compartment.id = 'ocid1.compartment.oc1..apps'}

Then a policy that grants read access to only that secret:

Allow dynamic-group OrdersApp to read secret-bundles in compartment Apps where target.secret.name = 'orders-db-password'

3. Fetch it at runtime

oci secrets secret-bundle get --secret-id $SECRET --auth instance_principal \
  --query 'data."secret-bundle-content".content' --raw-output | base64 -d
import base64, oci

signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
client = oci.secrets.SecretsClient(config={}, signer=signer)
bundle = client.get_secret_bundle(secret_id="ocid1.vaultsecret.oc1..xxxx").data
password = base64.b64decode(bundle.secret_bundle_content.content).decode()

On OKE, use workload identity instead of instance principals so each pod gets only its own permissions.

4. Rotate without redeploying

oci vault secret update-base64 --secret-id $SECRET \
  --secret-content-content "$(printf '%s' 'N3w-Pass!' | base64)"

A new version becomes current. Applications that fetch the secret at start-up (or cache it briefly) pick it up on their next restart or cache refresh. Change the database password and the secret together in one runbook step.

Common errors

Error Cause
NotAuthorizedOrNotFound The dynamic group rule doesn't match the instance, or the policy is in the wrong compartment
Authorization failed or requested resource not found on the key The secret's key is disabled or deleted. Secrets need their key.
Empty or garbled value The content wasn't base64-decoded, or was double-encoded when created

Warning

Never put secret values on the command line in shared shells or in CI logs. Use --secret-content-content from a file or environment variable, and clear your shell history afterwards.