Sunday, October 4, 2026

How Autonomous AI Database Serverless on Oracle Database@AWS Uses Your AWS KMS Key for TDE

 

Valid as of October 4, 2026. Oracle Database@AWS is a relatively new service that's growing fast, with new features and improvements landing regularly. Some steps, screens, or limits may have been improved since this was written, so check the latest Oracle and AWS docs for the newest details.

Autonomous AI Database Serverless (ADB-S) on Oracle Database@AWS can protect its TDE master encryption key with an AWS KMS customer managed key in your own AWS account (ODB@AWS: Protect ADB-S).

In my previous post on Exadata, Exascale, and Autonomous Dedicated, the trick was OIDC federation: your own VM cluster proves who it is with a token from your OCI identity domain.

ADB-S works differently. You don't have a VM cluster. Oracle runs the infrastructure, so there's no resource of yours to carry an identity. ADB-S uses the classic AWS pattern for letting a SaaS vendor into your account instead: cross-account role assumption with an external ID.


The short version

  1. Oracle has an AWS role. Each ADB-S instance shows an "OCI trusted service account role ARN" in the AWS console. That role lives in an Oracle-owned AWS account.
  2. You create a role that trusts Oracle's account. It's an IAM role in your account whose trust policy allows Oracle's account to assume it, but only with the right external ID (your tenancy, compartment, or database OCID).
  3. Your KMS key policy lets your role use the key.
  4. At runtime, the service, acting as Oracle's role, calls STS AssumeRole on your role with the external ID, gets temporary credentials, and calls KMS to unwrap the master key.

No access keys are exchanged. You can revoke access at any time by changing your role's trust policy or the key policy.


Who trusts whom

PieceWhereWhat it does
OCI trusted service account roleOracle's AWS accountThe identity Oracle's service uses in AWS. You only need its ARN. Get it from ADB-S → Encryption → Edit → Customer managed key.
IAM policyYour AWS accountLets your role run kms:ListKeys and kms:ListAliases.
IAM roleYour AWS accountTrust policy: "Another AWS account" set to Oracle's account ID (taken from the role ARN), with Require external ID on. You can also restrict it to Oracle's exact role with aws:PrincipalArn.
KMS customer managed keyYour AWS accountSymmetric encrypt/decrypt key, backed by KMS or CloudHSM. Your role is added as a key user.
ODB network integrationsAWS AZSTS and AWS KMS service integrations must be turned on, the same as for Exadata.

The external ID: why it matters

Oracle's role serves many customers. Without an external ID, anyone who knew your role ARN could, in principle, configure their own ADB-S to point at it and have Oracle's role assume it for them. This is AWS's well-known confused deputy problem.

The external ID closes that gap. Your role only accepts the assume request when Oracle passes your OCID. You choose the scope in the console:

External ID typeWho can use your role
DATABASE_OCIDOnly that one ADB-S database. This is the tightest scope.
COMPARTMENT_OCIDAny ADB-S in that compartment
TENANCY_OCIDAny ADB-S in your tenancy. Oracle's walkthrough uses this one.

Pick the narrowest scope that fits how many databases share the role.


Setup, step by step

Following the ODB@AWS ADB-S page:

StepWhereWhat you do
1. NetworkAWS console → ODB networksTurn on STS and AWS KMS service integrations
2. Get Oracle's role ARNAWS console → ADB-S → Encryption → Edit → Customer managed keyCopy the OCI trusted service account role ARN. Also note your database, compartment, or tenancy OCID for the external ID.
3. IAM policyIAM → PoliciesAllow kms:ListKeys and kms:ListAliases
4. IAM roleIAM → Roles → Another AWS accountEnter Oracle's account ID, turn on Require external ID, and attach the policy from step 3. Optionally add an aws:PrincipalArn condition.
5. KMS keyKMS → Customer managed keysCreate a symmetric encrypt/decrypt key and add your role as a key user
6. Switch the databaseAWS console → ADB-S → Encryption → EditChoose Customer managed key, then enter the key ARN or ID, your role ARN, and the external ID type

After saving, the Key type changes to AWS KMS Key. Oracle notes that the change can take 30 minutes or more to show up in the AWS console.

What the role's trust policy looks like

This is a sketch based on the documented settings. Use the real ARN and OCID from your console:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::<oracle-account-id>:root" },
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": { "sts:ExternalId": "<tenancy-or-compartment-or-database-ocid>" },
      "ArnLike":      { "aws:PrincipalArn": "<oci-trusted-service-account-role-arn>" }
    }
  }]
}
  • Principal plus sts:ExternalId is what the console wizard builds when you choose "Another AWS account" with "Require external ID".
  • The ArnLike / aws:PrincipalArn condition is the optional extra step Oracle mentions. It narrows the trust from "Oracle's whole AWS account" to "Oracle's specific ADB-S role". I'd add it.

What happens at runtime

  1. The service calls sts:AssumeRole, acting as Oracle's trusted role. It passes your role ARN and the external ID.
  2. STS checks your role's trust policy: is the caller Oracle's account or role, and does the external ID match?
  3. STS returns temporary credentials for your role.
  4. The service calls kms:Decrypt with those credentials to unwrap the TDE master key.
  5. KMS checks the key policy and logs the call in CloudTrail under your role's assumed-role session.
  6. The unwrapped master key is used in memory to unlock the tablespace keys. Your data never goes to KMS.

Oracle doesn't document the internal call sequence or how the service gets credentials for its own role. The flow above is the standard AWS cross-account pattern that the documented setup implies.


How this differs from Exadata, Exascale, and ADB-D


ExaDB-D / ExaDB-XS / ADB-DADB-S
Who proves identity to AWSYour VM cluster, through your OCI identity domain (OIDC)Oracle's AWS role, on behalf of the service
AWS-side setupCloudFormation creates an OIDC provider and a WebIdentity roleYou create an IAM policy and a role that trusts Oracle's account
STS callAssumeRoleWithWebIdentityAssumeRole with sts:ExternalId
OCI-side setupIdentity connector, registered AWS key, OCI policyNone; it's all set from the AWS console
ScopingRole limited to one VM cluster OCID (optional)External ID = database, compartment, or tenancy OCID
Where you rotateOracle console → Rotate (new MKID context)AWS KMS → Rotate now (key material rotation), or switch to another key
Cross-region with AWS KMSDocumented with Multi-Region keysNot supported (see below)

Rotation

The ODB@AWS page rotates the key on the AWS side: KMS → your key → Key material and rotations → Rotate now.

  • That rotates the KMS key's backing material while the key ARN stays the same.
  • AWS limits on-demand rotation to 25 times per key.
  • You can also turn on KMS automatic rotation.

The other option is to switch the database to a different KMS key in Edit Encryption. The OCI ADB-S docs treat choosing a different key as rotating the TDE master key (ADB-S AWS KMS docs). On the same ODB@AWS page, the OCI Vault section says you can't switch to a different customer-managed key more than twice in 24 hours. I'd assume the same throttle applies to AWS KMS keys, but that isn't stated.


Limitations and gotchas (as of today)

  • No cross-region. AWS KMS isn't supported for cross-region Autonomous Data Guard standbys (ADB-S docs). The ODB@AWS page also says restoring to a different region isn't supported with AWS customer managed keys. If cross-region DR is a must, check this before you choose AWS KMS.
  • Enable after provisioning. The OCI ADB-S docs say AWS KMS can't be chosen during creation. You create the database with an Oracle-managed key, then switch.
  • Commercial regions only.
  • Keep the trust chain intact. If you delete or disable the key, remove your role from the key policy, change the role's trust policy, or change the external ID, the database loses access to its master key. Treat all four as a kill switch, deliberately or by accident.
  • Use the narrowest external ID you can. DATABASE_OCID means one role per database. TENANCY_OCID is simpler but lets any ADB-S in your tenancy use the role.
  • Watch CloudTrail. Calls show up as your role's assumed-role session, so you can alert on unexpected Decrypt failures or use.

Sources

Content from Oracle and AWS documentation was paraphrased for this post. The diagrams are my own and show my understanding of the documented setup. The runtime call order and the trust policy JSON are inferred, not taken from Oracle.

Valid as of October 4, 2026. Oracle Database@AWS is adding capabilities quickly, so check the latest documentation for what's new.

How Exadata, Exascale, and Autonomous Dedicated on Oracle Database@AWS Use Your AWS KMS Key for TDE (Without Storing Any AWS Keys)

Valid as of October 4, 2026. Oracle Database@AWS is a relatively new service that's growing fast, with new features and improvements landing regularly. Steps, screens, and limits may have changed since this was written. Check the current Oracle and AWS docs before you rely on it.

Three Oracle Database@AWS services can keep their TDE master encryption keys in AWS KMS, using a customer managed key you own:

ServiceAWS KMS integration GADocs
Exadata Database Service on Dedicated Infrastructure (ExaDB-D)November 18, 2025ExaDB-D AWS KMS
Autonomous AI Database on Dedicated Infrastructure (ADB-D)January 20, 2026ADB-D AWS KMS
Exadata Database Service on Exascale Infrastructure (ExaDB-XS)August 2026ExaDB-XS AWS KMS, ODB@AWS Protect Exascale Database

All three use the same mechanism. The only real difference is which VM cluster carries the identity: an Exadata VM cluster, an Exascale VM cluster, or an Autonomous VM cluster. I'll explain it with ExaDB-D, then cover what changes for the others in their own section.

That raises an obvious question. The VM cluster is an OCI resource: it's managed from the OCI console and has an OCI identity. AWS KMS only trusts AWS IAM principals. So how does a VM that AWS knows nothing about get permission to use your KMS key?

The answer is OIDC federation, the same idea behind GitHub Actions or EKS pods getting AWS access without access keys. This post goes through how it works, piece by piece.

Not covered here: Autonomous Serverless (ADB-S). ADB-S uses a different model. There's no OIDC provider or identity connector. Instead, you create an IAM role in your account that trusts an Oracle-owned AWS role (the "OCI trusted service account role ARN" shown in the console), usually protected with an external ID (database, compartment, or tenancy OCID). That role then gets key-user access to your KMS key (ADB-S AWS KMS). It deserves its own post.


The short version

  1. OCI vouches for the VM cluster. Your OCI identity domain acts as an identity provider and issues a signed token that says "this is VM cluster ocid1…".
  2. AWS trusts OCI's signature. An IAM OIDC identity provider in your AWS account trusts that identity domain. An IAM role trusts tokens from that provider.
  3. STS swaps the token for temporary AWS credentials for that role.
  4. KMS lets the role unwrap the database's master key, because your key policy allows it.

Nothing long-lived is stored on the VM. Every KMS call is checked against your key policy and logged in CloudTrail.


The pieces and who trusts whom

PieceWhereWhat it does
OCI identity domainOCIActs as the OIDC issuer. It authenticates the database so it can reach AWS KMS. Created automatically during ODB@AWS onboarding for accounts linked after GA.
IAM OIDC identity providerAWSTells AWS to trust tokens signed by that OCI identity domain URL. There's one per AWS account.
IAM role (WebIdentityRole)AWSWhat the VM cluster becomes in AWS. Its trust policy accepts tokens from the OIDC provider and can be limited to one VM cluster OCID.
KMS customer managed keyAWSSymmetric encrypt/decrypt key, backed by KMS or CloudHSM. Its key policy grants the role DescribeKey, Encrypt, and Decrypt.
Identity connectorOCILinks the VM cluster to the IAM role ARN. Created when you associate the role with the cluster.
Registered AWS keyOCIAn OCI resource (oracle-db-aws-keys) that points to your KMS key ARN, so OCI can show it in the database encryption settings.
OCI IAM policyOCIAllows the VM cluster's resource principal (type cloudvmcluster) to read registered AWS keys.
ODB network integrationsAWS AZSTS and KMS service integrations must be on so the VMs can reach those AWS endpoints privately.
PKCS#11 multicloud driverVM clusterInstalled automatically when you enable AWS key management. The database talks to it like a hardware security module (HSM), and it talks to STS and KMS.

A resource principal is OCI's way of giving a resource (here, the VM cluster) its own identity, so it can call services as itself instead of as a user. The policy that unlocks it looks like this:

Allow any-user to read oracle-db-aws-keys in compartment id <compartment-ocid>
  where all { request.principal.type = 'cloudvmcluster' }

If the registered key and the VM cluster are in different compartments, Oracle's docs say you need the policy in both compartments.


Setup, mapped to what each step creates

Following Oracle's step-by-step tutorial:

StepWhere you clickWhat it builds
1. Verify the OCI identity domainAWS console → Oracle Database@AWS → SettingsThe OIDC issuer on the OCI side
2. Turn on STS + KMS in the ODB networkAWS console → ODB networks → ModifyThe network path from the VMs to STS and KMS
3. Run the CloudFormation stackVM cluster → IAM service roles → CloudFormation linkIAM OIDC provider + IAM role. Leave OIDCProviderArn blank the first time and reuse it after that.
4. Associate the IAM roleVM cluster → IAM service roles → AssociateThe identity connector (status "Connected")
5. Create the KMS keyAWS KMS → Customer managed keysThe key and a key policy granting the role access
6. Register the key in OCIOCI → Database Multicloud Integrations → AWS Integration → AWS KeysA registered AWS key (Discover needs DescribeKey)
7. Enable AWS key managementOCI → VM cluster → EnableThe PKCS#11 driver on the VMs
8. Use itNew database, or "Change" on an existing oneA database whose master keys are protected by KMS

The CloudFormation stack, demystified

The stack creates two things:

  • The OIDC provider. It records the OCI identity domain URL as a trusted issuer.
  • The IAM role. It allows sts:AssumeRoleWithWebIdentity from that provider.

The ResourceOcid and RoleName parameters give you per-resource isolation: the role only accepts tokens for that one VM cluster. Leave them blank if you don't need that isolation.

A trust policy of that kind generally looks like this. It's illustrative only, so check the real one in your stack:

{
  "Effect": "Allow",
  "Principal": { "Federated": "arn:aws:iam::<account>:oidc-provider/<identity-domain-host>" },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": { "<identity-domain-host>:sub": "<vm-cluster-ocid>" }
  }
}

The KMS key policy from Oracle's docs grants the role these actions:

{ "Sid": "KMSKeyMetadata", "Effect": "Allow",
  "Principal": { "AWS": "<role-arn>" }, "Action": ["kms:DescribeKey"], "Resource": "*" },
{ "Sid": "KeyUsage", "Effect": "Allow",
  "Principal": { "AWS": "<role-arn>" }, "Action": ["kms:Encrypt", "kms:Decrypt"], "Resource": "*" }

What happens at runtime

When the database opens its keystore (at startup, when a PDB opens, or on key rotation), the flow is:

  1. The database asks the PKCS#11 driver for its master key. To the database, AWS KMS looks like an HSM keystore.
  2. The driver asks the OCI identity domain for a token as the VM cluster's resource principal.
  3. The identity domain returns a signed OIDC token (JWT) that identifies the VM cluster.
  4. The driver calls STS AssumeRoleWithWebIdentity with that token and the role ARN from the identity connector.
  5. STS checks the token against the OIDC provider (signature and issuer) and the role's trust policy (for example, the VM cluster OCID).
  6. STS returns temporary credentials. They expire on their own.
  7. The driver calls kms:Decrypt with an encryption context naming the master key ID (MKID = ORACLE.TDE.HSM.MK.…).
  8. KMS checks the key policy, including any Deny rules, and logs the call to CloudTrail.
  9. KMS returns the unwrapped master key to the driver.
  10. The database uses it in memory to unlock the tablespace keys.

Steps 2–6 are the standard OIDC web identity flow, and the documented parts (identity domain as issuer, OIDC provider, IAM role, STS integration) fit it. Oracle doesn't publish the driver's internal call sequence, so treat the exact ordering as my reading of the docs rather than an official spec.


Three layers of keys

TDE already uses two layers of keys. KMS adds a third on top:

  1. AWS KMS key. It never leaves KMS (or CloudHSM), and you control it.
  2. TDE master encryption keys. There's one per container (CDB$ROOT and each PDB), each with its own MKID. These are what go to KMS to be wrapped and unwrapped.
  3. Tablespace and column keys. They're stored encrypted in datafile headers and unlocked locally with the master key.

Your data, redo, and backups never go to AWS KMS. Only small key blobs do.

You can see the mapping on the VM:

dbaascli tde getHSMKeys --dbname <db>

The output lists each container's master_key_id next to the KMS key ARN. In SQL:

select key_id, con_id, creation_time, key_use from v$encryption_keys;

Controls you get

Kill switch for one PDB. Add a Deny to the key policy for that PDB's MKID. The other PDBs keep working. From Oracle's docs:

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": ["kms:Encrypt", "kms:Decrypt"],
  "Resource": "<kms-key-arn>",
  "Condition": { "StringEquals": { "kms:EncryptionContext:MKID": "ORACLE.TDE.HSM.MK.<mkid>" } }
}

Kill switch for everything. Disable the key or remove the role from the key policy. The databases won't be able to open their keystore the next time they need the master key.

Rotation. "Rotate" on a CDB or PDB generates a new encryption context for the same KMS key.

Audit. Every Encrypt/Decrypt call shows up in CloudTrail under the IAM role.

Isolation. With ResourceOcid set, a role only works for one VM cluster.


Same model for Exascale and Autonomous Dedicated

The ExaDB-XS and ADB-D AWS KMS pages follow the same steps as ExaDB-D:

  1. Verify the OCI identity domain.
  2. Turn on STS and KMS in the ODB network.
  3. Run the CloudFormation stack.
  4. Associate the IAM role.
  5. Create the key.
  6. Create the OCI policy.
  7. Register the key.
  8. Enable AWS KMS.

Everything in the diagrams above applies. Swap "Exadata VM cluster" for an Exascale VM cluster or an Autonomous VM cluster. For ADB-D, also swap the database for an Autonomous Container Database (ACD) and its Autonomous Databases.

What's different:


ExaDB-DExaDB-XS (Exascale)ADB-D
Resource that holds the identityExadata VM clusterExascale VM clusterAutonomous VM cluster
CloudFormation link and "Associate IAM role"Exadata VM cluster → IAM service rolesExascale VM cluster → IAM service roles (one stack per cluster)Autonomous VM cluster → IAM service roles
Resource principal type in the OCI policycloudvmclusterexadbvmclustercloudautonomousvmcluster
Where AWS KMS is enabledVM cluster → AWS Key Management → EnableVM cluster → AWS Customer Managed Encryption Key → EnableAutonomous Exadata VM cluster → Multicloud information → AWS KMS → Enable
Where you choose the keyNew database, or "Change" on an existing oneNew database, or "Change" on an existing oneWhen you create the ACD (Encryption key → AWS KMS)
RotationCDB or PDB → RotateCDB or PDB → RotateACD or Autonomous Database → Rotate encryption key
PKCS#11 driver on the VMsYes, you can update itYes, you can update itNot mentioned in the ADB-D docs (no customer OS access, so presumably Oracle-managed)
Cross-region DR with AWS KMSData Guard with a Multi-Region keyNot described on the Exascale page as of todayCross-region Autonomous Data Guard with a Multi-Region key

The OCI policy differs only in the principal type:

# ExaDB-D
Allow any-user to read oracle-db-aws-keys in compartment id <compartment-ocid>
  where all { request.principal.type = 'cloudvmcluster' }

# ExaDB-XS (Exascale)
Allow any-user to read oracle-db-aws-keys in compartment id <compartment-ocid>
  where all { request.principal.type = 'exadbvmcluster' }

# ADB-D
Allow any-user to read oracle-db-aws-keys in compartment id <compartment-ocid>
  where all { request.principal.type = 'cloudautonomousvmcluster' }

Using the wrong principal type is an easy mistake when you copy a policy from one service to another.

Exascale notes:

  • One stack per Exascale VM cluster. Oracle's Exascale page says to create a CloudFormation stack for each cluster. Reuse the account's existing OIDCProviderArn after the first run.
  • Same two-choice rule. After enabling, new databases on the cluster can use only Oracle Wallet or AWS KMS, and only keys registered in OCI are listed.
  • The ODB@AWS Exascale protect page is thin. As of today it lists AWS KMS as an option but doesn't show the steps. The detail is in the Exascale service docs linked above.

ADB-D notes:

  • Same two-choice rule. Once AWS KMS is enabled on the Autonomous VM cluster, new databases can use only Oracle Wallet or AWS KMS.
  • Plan for Multi-Region early. If cross-region Autonomous Data Guard is even a possibility, create the key as Multi-Region, because you can't change it later. For the standby, create a replica key in the standby region, give the standby Autonomous VM cluster's IAM role usage permission on it, and use Replicate AWS key in OCI. The standby region needs its own CloudFormation stack, role association, and OCI setup.
  • Cross-region restore is a separate question. Cross-region Data Guard is documented, but the ADB-D restore page says cross-region restore (cloning from S3 backups into another region) isn't supported for databases using AWS KMS.
  • One OIDC provider per AWS account. It's shared across ExaDB-D, ExaDB-XS, and ADB-D. After the first CloudFormation run, pass the existing OIDCProviderArn.

Operational notes and gotchas

  • Two choices only. Once AWS KMS is enabled on a VM cluster, new databases there can use only Oracle Wallet or AWS KMS. OCI Vault and Oracle Key Vault aren't offered.
  • Disabling breaks databases. Turning off AWS key management at the cluster level affects any database still using it, so move those databases off first.
  • One cloud driver per cluster. Only one PKCS#11 multicloud driver (AWS, Azure, or Google Cloud) can be active per VM cluster.
  • Driver updates need database restarts. Updates to the driver (dbaascli admin updateMCKMS) restart databases, either rolling one VM at a time or all at once.
  • Cross-region needs planning up front. Cross-region restore and Data Guard with AWS KMS depend on Multi-Region keys replicated to the target region, plus OCI-side key replication. You can't convert an existing single-Region key, so choose Multi-Region at creation if you might need it.
    • ExaDB-D: as of today, the ExaDB-D KMS page still has an older note saying cross-region restore isn't supported, next to a full cross-region restore procedure. I read that as a stale note, but confirm with Oracle.
    • ADB-D: cross-region Autonomous Data Guard is documented. Cross-region restore with AWS KMS is stated as unsupported.

Sources

Content from Oracle and AWS documentation was paraphrased for this post. The diagrams are my own and show my understanding of the documented components. The runtime call order is inferred, not taken from an Oracle diagram.

Valid as of October 4, 2026. Oracle Database@AWS changes frequently, so check the current documentation before you rely on these details.