Tuesday, October 20, 2026

Configuring Oracle Key Vault with OCI/DB@ for Exadata Dedicated

This blog post will walk through how to configure OCI to use an existing Oracle Key Vault (OKV) with Exadata Database Service on Dedicated Infrastructure.

This topic has come up a lot lately with customers who need  a central TDE key manage system and I wanted to walk through the steps myself and document them for easy access.

 I am going to start at the point where OKV is already installed, the initial passwords have been set, and I can log into the OKV management console.

NOTE: For my testing, I used the marketplace image of OKV installed in an instance in OCI.

The next step is to give the OCI database automation the information it needs to connect to OKV. I will create an OCI vault if one is needed, create a key to encrypt a secret, store the OKV REST user password in that secret, and then create the Exadata Key Store.

There are a few similarly named objects involved, so I want to explain what each one does before going through the screens.

ObjectWhat I am using it for
Oracle Key Vault (OKV)The server(s) that will hold the database TDE master encryption keys when a database is configured to use OKV.  OKV is typically configured as a cluster for high availability.
OCI vaultThe OCI vault used for the key and secret in this walkthrough.
OCI encryption keyThe symmetric key used to encrypt the saved password.
OCI secretThe password for the OKV REST user.
Exadata Key StoreThe OCI resource containing the OKV connection IP address(es), REST username, and reference to the password secret for the REST user.

NOTE: The key I create in OCI below protects the password secret. The database TDE keys will be managed in OKV.

Before starting

My screenshots show OKV 21.15. OCI menu names can change, so I have included links to Oracle's documentation throughout the post.

Make sure the Exadata client network can reach OKV. Oracle lists ports 443, 5695, and 5696 for outbound access from the client network. Check the routes, security lists or network security groups, and any firewall on the path. 

I also need OCI permissions to create or use the vault, key, secret, and Key Store, plus an IAM administrator to configure the policies below. For this walkthrough, I will work in the Exadata deployment's region and select the appropriate compartment at each step.

Oracle's main reference is Managing Encryption Keys on External Devices for Exadata Dedicated. Start with the section titled Setting Up Your Oracle Exadata Database Service on Dedicated Infrastructure to Work With Oracle Key Vault.

Step #1 Enable REST access in OKV

First I am going to check that REST access is enabled. Log into OKV with a System Administrator account and go to System → Settings → RESTful Services.

In the screen below, REST access can be disabled, allowed from specific IP addresses, or allowed from all addresses. For a restricted configuration, select IP address(es) and include the actual client IP addresses used by all of the database VM hosts that will access OKV. Include every RAC node, and account for any source address translation in your network.  Save the change.



The supplied screenshot shows All selected. Use an explicit client IP list when restricting REST access.

Oracle documents these settings in Oracle Key Vault General System Administration, under Configuring RESTful Services Utility. Use the section appropriate to your standalone or multi-master cluster deployment.

Step #2a Create the OKV REST user

Next I am going to create a dedicated account for the integration. In OKV, go to Users → Manage Users and create a user such as okv_rest_user. Set its password and retain it securely. This is the password that I will put into the OCI secret.



Create the OKV user that OCI will use for the integration.

Open the user details, select the Create Endpoint privilege, and save the change. That is the REST user privilege specified for Exadata Dedicated in Oracle's integration prerequisites. The screenshot below shows it selected.



Grant Create Endpoint to the integration user.

NOTE: The OCI form calls this account the Administrator Username. I will enter the dedicated OKV REST username in that field.

Step #2b Reset the password for the REST user

Once you create the REST user, you need to reset the password before the first login.
This can be accomplished by logging into the OKV console as the okv_rest_user and you will be prompted to reset the password.




Step #3 Create or select an OCI vault

Now I am ready to move to the OCI Console. Open Identity & Security → Key Management and locate the vaults. Some Console layouts label this entry simply Vault.

If you already have an appropriate vault, select it and continue to the next step. Otherwise:

  1. Select the compartment where the vault will be created.
  2. Click Create Vault.
  3. Enter a descriptive name, such as okv-integration-vault.
  4. Select the vault type required by your organization. The virtual private vault option provides a dedicated HSM partition; it is not a requirement just to store this password.
  5. Create the vault and wait for it to become available.

See Creating a Vault for the options. Choose the vault type carefully because it cannot be changed after creation.

Step #4 Create the key that will encrypt the secret

Within the vault, open Master Encryption Keys and select Create Key. Below are the settings in my example.

FieldExample setting
CompartmentThe compartment chosen for the key
Namebsg-okv-secret
Protection ModeSoftware in this example; select HSM if required by your organization
Key Shape AlgorithmAES
Key Shape Length256 bits
Import External KeyOff, so OCI generates the key


This key will encrypt the OKV password secret.

Click Create Key and wait for it to become available. Use a symmetric AES key for this secret; an asymmetric key is not supported for secret creation.

Oracle explains the protection modes and creation options in Creating a Master Encryption Key. A key's protection mode cannot be changed after creation.

Step #5 Create the secret containing the OKV password

Next go to Identity & Security → Secret Management → Secrets. Select the compartment and vault, then click Create secret.

I am storing the password that already exists in OKV, so I will use Manual secret generation. Fill in the fields as follows.

FieldWhat to enter
Create in compartmentThe compartment where the secret should reside
Nameokv-rest-password
DescriptionPassword for the OKV REST integration user
Vault compartment and VaultThe vault selected or created in Step #3
Encryption key compartment and Encryption keyThe location and name of the AES key from Step #4
Secret generationManual secret generation
Secret type templatePlain-Text
Secret contentsOnly the exact password for okv_rest_user

The key must belong to the vault selected for the secret. The compartment selectors matter here: the secret, vault, and key can have different compartment locations.

NOTE: Do not include the username, a JSON document, surrounding quotes, or an extra newline in the password value. With Plain-Text selected, enter the password directly. The Console handles the required base64 encoding; base64 itself is not encryption. OCI encrypts the secret using the selected key.

Click Create secret. Once it is active, record its name, compartment, and OCID for reference. I will select this secret in the Key Store form rather than paste the password into that form.

See Creating a Secret. Oracle now documents secrets under the Secret Management Service, which explains why older Vault documentation may direct you to a different page.

Step #6 Configure IAM access

Before creating the Key Store, I need the OCI resources to have access to each other. This is separate from the permissions that let me log into the Console and create the resources.

The following follows the compartment-based dynamic-group approach in Oracle's Exadata Dedicated setup guide. Have your IAM administrator adapt it to your compartment structure and identity domain. Replace every value in angle brackets before using it.

Create the dynamic groups under Identity & Security → Domains → your domain → Dynamic groups.

For a group named OKV-KeyStores, use the OCID of the compartment where the Key Store will reside:

ALL {resource.compartment.id = '<KEYSTORE-COMPARTMENT-OCID>'}

For a group named OKV-Exadata, use the compartment identified for the Exadata infrastructure in Oracle's setup procedure:

ALL {resource.compartment.id = '<EXADATA-INFRASTRUCTURE-COMPARTMENT-OCID>'}

Create the policy in a parent compartment that covers the target compartments. These examples use dynamic groups in the Default identity domain; substitute your domain if different.

Allow dynamic-group 'Default'/'OKV-KeyStores' to use secret-family in compartment <SECRET-COMPARTMENT>
Allow dynamic-group 'Default'/'OKV-Exadata' to use keystores in compartment <KEYSTORE-COMPARTMENT>
Allow service database to read secret-family in compartment <SECRET-COMPARTMENT>

The first statement gives the Key Store group access to the secret. The second lets the Exadata group use the Key Store. The third lets the database service read the secret.

NOTE: These matching rules select resources by compartment; they are not filters for a particular resource type. Use appropriately scoped compartments and have your IAM administrator review the resulting access. If the Exadata infrastructure and VM clusters are in different compartments, verify the resource membership against your deployment before proceeding.

For the full procedure, use Steps 2 through 4 in Oracle's Exadata Dedicated OKV setup documentation.

Step #7 Create the Exadata Key Store

Now I have the OKV connection information and the password stored as an OCI secret. Open Oracle AI Database → Oracle Exadata Database Service on Dedicated Infrastructure, select the compartment for the new Key Store, and click Key Stores.



Open Key Stores from the Exadata Dedicated service page.

Click Create Key Store and enter the following.

FieldWhat to enter
Name Your Key StoreA descriptive name, such as bsg-okv-keystore
Connection IP AddressesThe OKV IP address(s) reachable from the Exadata client network. You can enter multiple addreess if this is an OKV cluster.
Administrator Usernameokv_rest_user, or the dedicated OKV username you created
Vault compartment and VaultThe vault associated with the password secret
Secret compartment and SecretThe compartment containing okv-rest-password, then that secret


The IP address and compartment names shown here belong to my example. Replace them with your own values.

For an OKV cluster, Oracle allows multiple comma-separated node IP addresses from the same OKV cluster. Enter addresses reachable from the database VMs. If you use a localhost tunnel to browse the OKV console, that localhost address does not belong in this field.

Review the settings, click Create Key Store, and wait for the resource to become active. Open its details and confirm the connection addresses, username, and password-secret reference.

If the secret does not appear in the selector, first check the selected region, vault, and secret compartment, followed by IAM access. If a later OKV operation cannot connect, check connectivity from every database VM, the REST access list, the Create Endpoint privilege, and whether the secret contains the current password.

What comes next

At this point I have created the OCI resources needed to reference OKV. Creating the Key Store does not migrate an existing database's TDE keys. An active Key Store also does not replace an end-to-end database operation when validating the integration.

For an existing database, the next operation is on the database details page under Encryption → Change → Oracle Key Vault, where the Key Store is selected. Oracle states that this migration restarts the database, so plan a maintenance window. Follow the Administer Transparent Data Encryption (TDE) Keys section of the Exadata Dedicated documentation for that separate procedure.

The setup covered here gives me the four OCI objects I need: the vault, the encryption key, the password secret, and the Exadata Key Store pointing to OKV.


What I see in OKV


Endpoint


Within OKV, I can see that the tooling enrolled both VM cluster nodes as endpoints



The endpoints are named with the following format.

EXA_<database-name>_<resource-ID>_<VM-hostname>_EP
``` :chatgpt-content-reference{index="0"}



| Component           | Meaning |
|---                  |---|
| `EXA`               | Exadata automation prefix |
| `OKV1BSG_PPX_PHX`   | Database name/unique-name portion |
| `E47CC2A7-4C1F-40B3-8861-36CD245FB741` | Automation’s database resource identifier   |
| `EXACS-PHX3-OSRPA1` | DB VM hostname |
| `EP` | Endpoint |

**An endpoint authenticates the database host to OKV; a virtual wallet holds keys and grants access to endpoints.** If you see this name under **Wallets**, check its endpoint association—it may be an endpoint-associated wallet.


Wallet and Keys


I can see that wallet was created to store the keys




NOTE: on the DB side the unique identifier is the "database resource ID" rather than the OCID.








Friday, October 2, 2026

A third recovery site: hybrid Data Guard and Autonomous Recovery Service

Until recently, most organizations I work with have been comfortable running their databases and applications across two regions. Sometimes that is an Active/Standby configuration, but more often I see some form of Active/Active. The big change I have seen recently is the addition of a third site, often described as a "cyber vault" or an IRE (Isolated Recovery Environment).

To provide that third site, many customers are looking at hosting a standby database in the cloud, either in OCI or through Oracle Database@ services in a multicloud environment. A practical way to limit traffic from the on-premises environment is to only send redo to the cloud database with Data Guard, then back up that cloud database to Autonomous Recovery Service. The backup workload stays on the cloud side.

Creating a cloud standby from your on-premises database is easier than you might think. In this post, I go through the standby build and the next step: configuring backups to Autonomous Recovery Service.

One thing to keep in mind is that a standby database and backups are only part of the picture. To use this as a cyber vault or IRE, you also need to control who can access it and which systems can connect to it. You need to protect the encryption keys and test that you can restore the database to a point before an attack or data corruption occurred. Plan for all of this as you build the standby and configure the backups..

Hybrid Data Guard from an on-premises primary to a cloud standby and Autonomous Recovery Service inside a multicloud Cyber Vault or Isolated Recovery Environment

The third-site pattern: send redo to a cloud standby, then back up the standby to Autonomous Recovery Service. The worked example below uses Oracle Exadata Database Service in OCI.

I recently went through the Oracle documentation for creating a hybrid Data Guard configuration. There is a lot of information to work through, especially when you are trying to figure out what needs to be ready before you start.

I am breaking this into four parts:

  1. Get the prerequisites in place.
  2. Run dbcactl to prepare the primary database.
  3. Run dbaascli to create the standby database in OCI.
  4. Configure backups from the cloud standby to Autonomous Recovery Service.

Once the preparation is done, the standby build comes down to two commands. I will go through their parameters and what dbcactl and  dbaascli are doing, then show where Recovery Service fits into the third-site design.

For this walkthrough, I am showing an on-premises Oracle RAC primary with a standby on Oracle Exadata Database Service in OCI. I have changed the database names and hostnames to use a generic sales example. My example build used a 19c Oracle Home and DBAAS CLI 26.3.1.0.0.

NOTE: The cloud VM cluster and Oracle Home need to exist before you start. configureStandby creates the database within that cluster. Refer to the full Oracle guide for platform requirements and configurations with additional standbys.

1) What needs to be ready before I start

First, let's go through the pieces that need to be in place before running either command.

  • Download dbcactl. My Oracle Support document 3099785.1, linked from the hybrid guide, has the download and installation instructions. I am using /home/oracle/dbcacl/dbcactl in the example. The folder is named dbcacl, and the executable is dbcactl.
  • Have the cloud Oracle Home ready. Match the primary release, RU, and one-off patches where possible. If you need a different RU, check the combinations allowed in the guide.
  • Check connectivity in both directions. The primary needs to reach the cloud, and the cloud needs to reach the primary. Check DNS, SSH, and Oracle Net for all RAC nodes and SCAN endpoints. The network also needs enough bandwidth for the initial copy and ongoing redo.
  • Existing standby database. If you already have an existing standby database you need to ensure that ALL databases can reach each other with DG broker. The existing standby needs to be able to resolve the scan listener on the new standby and connect. The new standby needs to be able to resolve the scan listener for the existing standby and connect.
  • Have a shared ACFS directory on the primary if possible. This is where the network files and wallet configuration can be shared between instances. For this example I am using /acfs01/sales on an existing mounted ACFS filesystem.  If you do not have a shared ACFS directory you need to validate the connectivity on all DB nodes after executing dbcactl.
  • Prepare the primary for Data Guard. This includes standby redo logs, logging, Flashback Database, Oracle Net encryption, and enough recovery-area space. Follow the MAA recommendations in the guide.

Make sure the encryption keys are there

One thing I want to call out is the TDE wallet. Even if the on-premises primary is not encrypted, it still needs a wallet with master encryption keys for this hybrid configuration. The cloud database needs those keys.

For this example I am using a file-based TDE keystore. Before starting, I would check that the wallet is usable and that the keys exist in the CDB root and each PDB other than the seed. The TDE with Data Guard documentation goes through the key handling.

For 19c at RU 19.16 or later, these are the settings I would look at:

ParameterExample or policyPurpose
WALLET_ROOT/acfs01/sales/walletRoot directory for wallet storage; the file-based
TDE wallet is under tde. Use your existing keystore location.
TDE_CONFIGURATIONKEYSTORE_CONFIGURATION=FILESelects the file-based keystore used in this example.
TABLESPACE_ENCRYPTIONChoose for each siteAUTO_ENABLE is the cloud policy. DECRYPT_ONLY
 is an on-premises option when encrypted tablespaces must be avoided. Do not apply it to the cloud standby.

NOTE: Setting the parameters does not create the wallet or set the master keys. Also, WALLET_ROOT is static, so changing it requires a restart.

If you still need to set up the wallet, follow the TDE configuration procedure. The TABLESPACE_ENCRYPTION reference explains the encryption policies. For earlier RUs, use the release-specific settings in the hybrid guide.

Here is a quick check I can run on the primary, connected through SQL*Plus as oracle:

SELECT name, db_unique_name, database_role, log_mode,
       force_logging, flashback_on
FROM v$database;

SHOW PARAMETER wallet_root
SHOW PARAMETER tde_configuration
SHOW PARAMETER tablespace_encryption

SELECT con_id, status, wallet_type, wrl_parameter
FROM v$encryption_wallet;

I want the primary in ARCHIVELOG mode, with force logging enabled and Flashback Database prepared before moving on. If archive logging still needs to be enabled, plan for the maintenance window that change may require.

I would also check V$DATABASE_KEY_INFO and V$ENCRYPTION_KEYS in the root and relevant PDBs. An open wallet is only part of the check; I need the master keys as well. If the wallet shows OPEN_NO_MASTER_KEY, that needs to be addressed before the build.

Use your existing key-management procedure and wallet location. There is no reason to replace an existing wallet just to match the path in my example.

Finally, have the primary SYS password, the TDE wallet password, and the password you will supply for AWR administration ready. These have different purposes and do not need to be the same.

Get Recovery Service ready as well

For the backup step, I also need the Recovery Service IAM policies, network connectivity, and a registered Recovery Service subnet. For 19c, the documented minimum is RU 19.18. Broker is mandatory for this backup destination in a Data Guard configuration with dbaascli 25.3.1.0.0 and later. I would also check regional availability, service limits, and the retention policy I need. The Exadata backup guide covers these prerequisites.

The names I am using in the example

ItemGeneric value
Database name on both sitessales
Primary database unique namesales_primary
Standby database unique namesales_stby
Primary SCANonprem-scan.example.com
Standby SCANcloud-scan.oraclevcn.com
Primary database servicesales_primary.example.com
SCAN listener port on both sites1521
Existing cloud Oracle Home/u02/app/oracle/product/19.0.0.0/dbhome_1

You can see that I am using sales as the database name on both sides. The unique names are different: sales_primary and sales_stby.

The other distinction to keep in mind is the SCAN name versus the database service. The SCAN gets me to the cluster, and the service identifies the database connection. Use the actual service registered with your primary listener when replacing sales_primary.example.com.

2) Run dbcactl on the primary

Primary RAC database, SCAN listener, preparation command, and generated standby bundle

Figure 1. Run the preparation command on the first primary node. The standby SCAN already belongs to the provisioned cloud cluster.

Now I can prepare the primary. The diagram above shows the database and its SCAN listener, along with the cloud SCAN I will pass to the command.

I run this as oracle on the first primary node, with ORACLE_HOME and the local ORACLE_SID set for the source database. The shared directory /acfs01/sales also needs to be writable by oracle.

Here is the command with the example names:

/home/oracle/dbcacl/dbcactl \
  -silent \
  -oui_internal \
  -configureDatabase \
  -prepareForStandby \
  -dgTNSNamesoraFilePath /acfs01/sales \
  -sourceDB sales_primary \
  -gdbName sales.example.com \
  -standbyDBUniqueName sales_stby \
  -standbyScanName cloud-scan.oraclevcn.com \
  -standbyScanPort 1521 \
  -primaryScanPort 1521 \
  -standbyDBDomain oraclevcn.com \
  -blobFileLocation /tmp

The command prompts for the primary SYS password. In my run, I could see it creating the Data Guard services, updating tnsnames.ora and the include-file entry, and then preparing the standby bundle.

If you do not have a shared location for the the new tnsnames.ora file, you need to make sure ALL DB nodes have access to the entries in the new tnsnames.ora. This may involve manually adding the entries to your database.

What the dbcactl parameters mean

ParameterValue in this exampleMeaning
-silentFlagRuns without the graphical assistant; password prompts still appear.
-oui_internalFlagWorkflow flag that allows for the use of prepareForStandby
 (which is a hidden parameter)
-configureDatabaseFlagSelects database configuration.
-prepareForStandbyFlagSelects primary preparation for a standby.
-dgTNSNamesoraFilePath/acfs01/salesDirectory for the Data Guard network configuration.  An "ifile" entry is created in the default tnsnames.ora file that points to a tnsnames.ora that is created in this directory which contains entries for both the primary database and the new standby database.
-sourceDBsales_primaryIdentifies the primary by its unique name.
-gdbNamesales.example.comGlobal database name passed to the workflow.
-standbyDBUniqueNamesales_stbyUnique name planned for the standby.
-standbyScanNamecloud-scan.oraclevcn.comSCAN hostname for the existing standby cluster.
-standbyScanPort1521Standby SCAN listener port.
-primaryScanPort1521Primary SCAN listener port.
-standbyDBDomainoraclevcn.comStandby database in OCI domain passed to the workflow.
-blobFileLocation/tmpOutput directory for the generated bundle.

These are the options from my successful command, with the environment names changed. If you are using a different utility version, check its supported options, especially -gdbName and -pdbServiceDomain.

At the end, the command tells me where it wrote the .tar file. The filename will look like this, with a generated timestamp and ID:

Successfully created blob file:
/tmp/sales_<generated_timestamp>_<generated_id>.tar

This file contains the preparation material, including network files and the TDE wallet. I need to copy it securely to the first cloud node before running the second command.

For example, I can use scp:

scp /tmp/sales_<generated_timestamp>_<generated_id>.tar opc@cloud-node1.example.com:/tmp/

Replace the timestamp and ID with the actual filename from your output. For the next command, I am using /tmp/sales_standby.tar as a simpler name for the transferred file. You can keep the generated name instead; just use the same path in --standbyBlobFromPrimary.

NOTE: The bundle contains wallet material. Keep access to it restricted during the transfer and on the destination.

Wednesday, September 16, 2026

Oracle 19c: Cloning Encrypted PDBs and Moving TDE Keys

Oracle TDE master key in a wallet or Oracle Key Vault protects keys for encrypted tablespaces and columns
Oracle TDE key hierarchy. This walkthrough uses file-based wallets in Oracle Database 19c.

When cloning or refreshing an encrypted pluggable database (PDB) in Oracle Database 19c, it is easy to focus on the datafiles. Restore the backup, recover the database, and plug the PDB into the destination container database (CDB).

But don't forget the keys. With Transparent Data Encryption (TDE), the destination also needs access to the master encryption keys stored in the source wallet.

In this post I will walk through two ways to bring the keys with an encrypted PDB, and then show where those steps fit when the PDB is restored from backup. I am using Oracle Database 19c, local file-based TDE wallets, and united mode. In united mode the PDBs use the CDB's wallet, while keeping their own master encryption keys.

This builds on my posts about encrypting an Oracle PDB with TDE and Oracle wallet files for TDE and authentication.

NOTE: These are command examples to adapt and validate on your 19c Release Update. Database names, paths, passwords, and the recovery SCN are placeholders. This is a walkthrough of the key handling, not output from a completed lab.

For unplug/plug, I can bring the keys with ENCRYPT USING and DECRYPT USING, or export and import them separately. A refresh from RMAN backups also needs the historical keys during recovery into the auxiliary CDB.

In this post: Check the wallet · Unplug/plug with keys · Export and import keys · Refresh from RMAN backups · Rekey and verify · Merge wallets

TDE wallet keys: what needs to move with a PDB?

TDE has two levels of keys. The tablespace key encrypts the data, and the TDE master encryption key protects that key. The master key is stored in the keystore. Copying encrypted datafiles does not, by itself, give a different CDB access to that master key. Oracle's TDE overview

Moving an encrypted PDB and its TDE wallet keysThe encrypted PDB datafiles move to the destination PDB. Master keys are transported or exported and imported into the destination wallet, retaining its existing PDB keys.An encrypted PDB has two things to carryOracle Database 19c • Local TDE wallet • United modeSource PDBEncrypted datafilesProtected tablespace keysDestination PDBCopied datafilesStill encryptedCopy / restore / plugSource CDB walletPDB master encryption keysCurrent + historical keysDestination CDB walletImported PDB keysRetain existing PDB keysTransport with the PDBOR export / importAfter import: rekey the new PDB, verify encrypted data, and back up the updated wallet.A new master key does not remove the need for keys used by older backups.Figure 1. Move both the encrypted PDB datafiles and the required master keys into the destination environment.

For these examples I am using the following names.

Name Purpose
PRODCDB / APPPDB Source CDB and encrypted PDB
AUXCDB / APPPDB Temporary CDB used for a restore from backup
TESTCDB / APP_REFRESH Existing destination CDB and the new refresh PDB
SourceWalletPassword Password for the source wallet
TargetWalletPassword Password for the destination wallet
TransportSecret Separate secret protecting keys during transport

The transport secret and the wallet passwords have different jobs. I do not need to make the source and destination wallet passwords match.

STEP #1 - Check the TDE wallet configuration

On each CDB, I first check the configuration and wallet status.

-- SQL*Plus, connected to the appropriate CDB root
SHOW CON_NAME
SHOW PARAMETER wallet_root
SHOW PARAMETER tde_configuration

SELECT con_id, status, wallet_type, keystore_mode,
       wrl_parameter
FROM   v$encryption_wallet
ORDER BY con_id;

The examples assume TDE_CONFIGURATION='KEYSTORE_CONFIGURATION=FILE', with the united wallet under WALLET_ROOT/tde. A PDB row should show UNITED; the root can show NONE. An OPEN wallet is a useful first check, but it does not prove that it contains every key needed for this refresh. Wallet status reference

For a password wallet that is closed, open it from the root. Use the password belonging to that CDB.

ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN
  IDENTIFIED BY "SourceWalletPassword"
  CONTAINER = ALL;

If auto-login already has the wallet open, check its state rather than blindly repeating the open. The key-management examples below use FORCE KEYSTORE where supported to allow access to the password wallet. Have the ewallet.p12 password available even when normal database startup uses cwallet.sso. Configuring TDE

I also record the source PDB's keys before the move.

ALTER SESSION SET CONTAINER = APPPDB;

SELECT key_id, creation_time, activation_time
FROM   v$encryption_keys
ORDER BY activation_time;

This gives me key identifiers to compare later. I am recording metadata here, not displaying the secret key material. Encryption key view

Run the key operations as an appropriately privileged key administrator (SYSKM or ADMINISTER KEY MANAGEMENT), and the PDB operations with the necessary database privileges. The examples assume both are available to the administrative session.

METHOD #1 - Unplug and plug an encrypted PDB with its TDE keys

For a planned unplug/plug, I can protect the PDB's keys with a transport secret as part of the unplug operation.

1) Unplug on the source

-- PRODCDB root; source wallet must be open
ALTER SESSION SET CONTAINER = CDB$ROOT;

ALTER PLUGGABLE DATABASE APPPDB CLOSE IMMEDIATE;

ALTER PLUGGABLE DATABASE APPPDB
  UNPLUG INTO '/secure_stage/apppdb.xml'
  ENCRYPT USING "TransportSecret";

ENCRYPT USING protects the transported keys. The XML file is a manifest; the PDB's datafiles still have to be made available on the destination host. A .pdb archive is an alternative packaging format. Unplugging PDBs

NOTE: Unplugging takes this source PDB out of service. For a refresh that must leave production running, use the backup/auxiliary workflow below and unplug the restored copy.

2) Check compatibility at the destination

For this example, the XML and datafiles are accessible at the paths recorded in the XML. If the files were staged at different paths, account for that with SOURCE_FILE_NAME_CONVERT; FILE_NAME_CONVERT controls the destination copies.

-- TESTCDB root
SET SERVEROUTPUT ON
DECLARE
  can_plug BOOLEAN;
BEGIN
  can_plug := DBMS_PDB.CHECK_PLUG_COMPATIBILITY(
    pdb_descr_file => '/secure_stage/apppdb.xml',
    pdb_name       => 'APP_REFRESH');
  IF can_plug THEN
    DBMS_OUTPUT.PUT_LINE('Compatible');
  ELSE
    RAISE_APPLICATION_ERROR(-20001,
      'Review PDB_PLUG_IN_VIOLATIONS before continuing');
  END IF;
END;
/

Resolve compatibility errors before creating the PDB, including applicable patch, component, and character-set issues. Plug compatibility check

3) Plug in the copy

The destination wallet must already exist and be open. APP_REFRESH must be a new PDB name in TESTCDB.

-- TESTCDB root; filesystem paths used for this example
CREATE PLUGGABLE DATABASE APP_REFRESH AS CLONE
  USING '/secure_stage/apppdb.xml'
  COPY
  FILE_NAME_CONVERT =
    ('/u02/oradata/PRODCDB/APPPDB/',
     '/u02/oradata/TESTCDB/APP_REFRESH/')
  KEYSTORE IDENTIFIED BY "TargetWalletPassword"
  DECRYPT USING "TransportSecret";

ALTER PLUGGABLE DATABASE APP_REFRESH OPEN;

Here, AS CLONE gives the plugged copy a new identity, and COPY creates its datafiles at the destination. DECRYPT USING supplies the transport secret, while KEYSTORE IDENTIFIED BY supplies the destination wallet password. Adapt file placement for OMF or ASM. CREATE PLUGGABLE DATABASE reference

Finish with the rekey and verification steps below. An initial restricted open is not the end of the process.

METHOD #2 - Export and import TDE keys for an Oracle 19c PDB

This is an alternative to Method #1. I use a separate export file when I want the key transfer to be an explicit step in the refresh process.

1) Export from inside the source PDB

-- PRODCDB, or AUXCDB after restoring the PDB
ALTER SESSION SET CONTAINER = APPPDB;

ADMINISTER KEY MANAGEMENT EXPORT ENCRYPTION KEYS
  WITH SECRET "TransportSecret"
  TO '/secure_stage/apppdb_keys.exp'
  FORCE KEYSTORE
  IDENTIFIED BY "SourceWalletPassword";

ALTER SESSION SET CONTAINER = CDB$ROOT;
ALTER PLUGGABLE DATABASE APPPDB CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE APPPDB
  UNPLUG INTO '/secure_stage/apppdb.xml';

Export inside the PDB. Do not add a WITH IDENTIFIER IN filter: a PDB export carries its keys and the metadata identifying the active key. Protect the export file and deliver its secret separately. Exporting keys leaves the source keys in place. Key export syntax

2) Import into the destination root before plugging, when required

If SYSTEM, SYSAUX, UNDO, or TEMP is encrypted, first import into TESTCDB's root. Then import again inside the new PDB to associate the keys with it. For a PDB without those encrypted system tablespaces, the pre-plug root import can be skipped. Oracle's united-mode PDB procedure

-- TESTCDB root: conditional pre-plug import
ALTER SESSION SET CONTAINER = CDB$ROOT;

ADMINISTER KEY MANAGEMENT IMPORT ENCRYPTION KEYS
  WITH SECRET "TransportSecret"
  FROM '/secure_stage/apppdb_keys.exp'
  FORCE KEYSTORE
  IDENTIFIED BY "TargetWalletPassword"
  WITH BACKUP USING 'before_refresh_root_import';

3) Plug in, open the PDB wallet, and import inside the PDB

Run the compatibility check from Method #1 first. This manifest was created without ENCRYPT USING, so this branch does not use DECRYPT USING.

-- TESTCDB root
CREATE PLUGGABLE DATABASE APP_REFRESH AS CLONE
  USING '/secure_stage/apppdb.xml'
  COPY
  FILE_NAME_CONVERT =
    ('/u02/oradata/PRODCDB/APPPDB/',
     '/u02/oradata/TESTCDB/APP_REFRESH/')
  KEYSTORE IDENTIFIED BY "TargetWalletPassword";

ALTER SESSION SET CONTAINER = APP_REFRESH;

-- If the PDB's password wallet is not already open:
ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN
  FORCE KEYSTORE
  IDENTIFIED BY "TargetWalletPassword";

ALTER SESSION SET CONTAINER = CDB$ROOT;
ALTER PLUGGABLE DATABASE APP_REFRESH OPEN;

ALTER SESSION SET CONTAINER = APP_REFRESH;

ADMINISTER KEY MANAGEMENT IMPORT ENCRYPTION KEYS
  WITH SECRET "TransportSecret"
  FROM '/secure_stage/apppdb_keys.exp'
  FORCE KEYSTORE
  IDENTIFIED BY "TargetWalletPassword"
  WITH BACKUP USING 'before_refresh_pdb_import';

The PDB may initially open restricted. Complete the PDB import, rekey, and reopen before releasing it to the application. The root import and PDB import serve different purposes; do not treat the root import as completion of both steps.

Refresh an encrypted PDB from RMAN backups

I separate this into two handoffs: backup to auxiliary CDB, followed by auxiliary PDB to the existing destination CDB.

Oracle 19c encrypted PDB refresh from RMAN backupsRestore the source backups into AUXCDB with the historical wallet keys. Then plug the restored PDB into TESTCDB and add its keys to the existing destination wallet.Refreshing from backup into an existing CDBRestore with the historical keys first. Then transfer the restored PDB and its keys.Source backup setRoot + seed + APPPDBControlfile + required redoChosen recovery SCNAUXCDB / APPPDBBackup-based duplicateRecover and openProduction keeps runningTESTCDBNew PDB: APP_REFRESHPlug in, rekey, and verifyCut over after validationSource wallet copyRequired root and PDB keysIncludes historical keysAuxiliary walletAvailable during recoveryUsed to export restored keysTESTCDB walletAdd APPPDB keysRetain other PDB keysRecoveryPlug-inTwo separate key handoffs1 Provision the recovery wallet to AUXCDB.2 Use ENCRYPT / DECRYPT, or a PDB key export / import, for TESTCDB.Figure 2. A backup refresh has two key handoffs: recovery into AUXCDB, then plug-in and key transfer into TESTCDB.

1) Make the historical keys available to the auxiliary

The auxiliary needs the keys required by the backup and recovery interval. Rotating the production master key does not eliminate the need for older keys. A wallet backup that predates a required rotation may be missing a key; a later wallet can contain the historical keys if they have been retained. TDE key history

For a newly prepared auxiliary, securely provision a copy of the source password wallet at its configured WALLET_ROOT/tde location. Use a wallet with the required CDB and PDB key history, not just a PDB key export. The duplicate also restores root and seed files. Keep the auxiliary's wallet separate from the live source and from TESTCDB's wallet. Preparing the auxiliary keystore

For example, the auxiliary initialization settings include:

db_name='AUXCDB'
db_unique_name='AUXCDB'
enable_pluggable_database=TRUE
wallet_root='/u01/app/oracle/admin/AUXCDB/wallet'
tde_configuration='KEYSTORE_CONFIGURATION=FILE'

This is only the relevant parameter excerpt. Prepare the auxiliary in NOMOUNT, with its own controlfile, datafile, redo, and recovery-area destinations, plus the password file and Oracle Net configuration required by your duplication method.

2) Restore the PDB into the temporary CDB

Here is a backup-based duplication example, with RMAN connected to PRODCDB as TARGET and AUXCDB as AUXILIARY. Both connections are to the root. The source backup pieces must be accessible to the auxiliary, including root, seed, PDB, controlfile, and the archived redo needed to reach the chosen SCN.

-- RMAN: connected to the two CDB roots
SET DECRYPTION WALLET OPEN
  IDENTIFIED BY 'SourceWalletPassword';

RUN {
  SET UNTIL SCN 123456789;
  SET NEWNAME FOR DATABASE TO '/u02/oradata/AUXCDB/%U';

  DUPLICATE TARGET DATABASE TO AUXCDB
    PLUGGABLE DATABASE APPPDB
    LOGFILE
      GROUP 1 ('/u02/oradata/AUXCDB/redo01.log') SIZE 200M,
      GROUP 2 ('/u02/oradata/AUXCDB/redo02.log') SIZE 200M,
      GROUP 3 ('/u02/oradata/AUXCDB/redo03.log') SIZE 200M;
}

Replace the SCN and file layout with values for your restore. This creates a new auxiliary CDB containing the selected PDB, not a PDB directly inside TESTCDB. Oracle 19c's DUPLICATE PLUGGABLE DATABASE ... TO existing_cdb form supports active duplication; it is not the backup-based command used here. RMAN DUPLICATE reference

SET DECRYPTION WALLET OPEN supplies the wallet password across auxiliary restarts during duplication. It does not transfer missing keys. If the backup pieces have a separate password-encryption layer, also supply the applicable backup password using SET DECRYPTION IDENTIFIED BY. That password does not replace the keys needed for the TDE-encrypted datafiles. RMAN SET reference

3) Transfer from AUXCDB into TESTCDB

After successful recovery and opening the restored PDB, use either Method #1 or Method #2, with AUXCDB as the source.

Create a fresh manifest from the restored PDB, and export its keys there if using Method #2. Update FILE_NAME_CONVERT to match the restored files' actual paths. In the RMAN example, %U generates filenames directly under /u02/oradata/AUXCDB/; inspect those filenames rather than assuming an APPPDB subdirectory exists.

I would create APP_REFRESH alongside the current test PDB, validate it, and then handle the application/service cutover. The destructive replacement of an existing PDB is a separate decision. This is a repeated refresh from backups, not a REFRESH MODE clone.

Rekey the cloned PDB, reopen, and verify

Once the imported keys are available, create and activate a destination master key inside APP_REFRESH.

-- TESTCDB, inside the new PDB only
ALTER SESSION SET CONTAINER = APP_REFRESH;

ADMINISTER KEY MANAGEMENT SET KEY
  FORCE KEYSTORE
  IDENTIFIED BY "TargetWalletPassword"
  WITH BACKUP USING 'app_refresh_rekey'
  CONTAINER = CURRENT;

ALTER SESSION SET CONTAINER = CDB$ROOT;
ALTER PLUGGABLE DATABASE APP_REFRESH CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE APP_REFRESH OPEN;

Use CONTAINER=CURRENT for this PDB; there is no reason for a refresh to rotate every PDB's key. Changing the wallet password is also a different operation from generating a new master key. Key-management operations

Rekeying gives the destination a new master key. It does not make historical backups independent of their original keys. Retain those keys for as long as the corresponding recovery requirements exist. TDE key architecture FAQ

Now I check the result.

-- TESTCDB root
SELECT name, open_mode, restricted
FROM   v$pdbs
WHERE  name = 'APP_REFRESH';

SELECT time, name, cause, type, message, status, action
FROM   pdb_plug_in_violations
WHERE  name = 'APP_REFRESH'
AND    status <> 'RESOLVED'
ORDER BY time;

ALTER SESSION SET CONTAINER = APP_REFRESH;

SELECT status, keystore_mode, fully_backed_up
FROM   v$encryption_wallet;

SELECT key_id, creation_time, activation_time
FROM   v$encryption_keys
ORDER BY activation_time;

SELECT tablespace_name, encrypted
FROM   dba_tablespaces
ORDER BY tablespace_name;

I want READ WRITE, RESTRICTED=NO, and all blocking plug-in violations resolved. I also read known application data from an encrypted tablespace and check the expected refresh timestamp or business totals. Opening the PDB alone is not my application validation. Completing a PDB plug-in

Finally, back up the updated destination wallet and the refreshed PDB. WITH BACKUP protects the wallet before a change; I also want a retained copy containing the newly created key.

-- TESTCDB root, after successful rekey
ALTER SESSION SET CONTAINER = CDB$ROOT;

ADMINISTER KEY MANAGEMENT BACKUP KEYSTORE
  USING 'after_app_refresh'
  FORCE KEYSTORE
  IDENTIFIED BY "TargetWalletPassword"
  TO '/secure_wallet_backups/TESTCDB';

Keep password-wallet backups and their passwords recoverable, with access controlled separately from the database backups. An auto-login wallet stored beside encrypted backups weakens that separation. RMAN encryption and wallet backup guidance

Migrate TDE wallet keys with MERGE KEYSTORE

For one PDB, I would normally use the PDB export/import above. A wallet merge has broader scope: it adds the source wallet's keys to another wallet.

Here is a merge example using staged wallet copies, outside the live wallet directories:

-- Optional wallet administration example; not a PDB refresh step
ADMINISTER KEY MANAGEMENT
  MERGE KEYSTORE '/secure_stage/source_wallet'
    IDENTIFIED BY "SourceWalletPassword"
  INTO EXISTING KEYSTORE '/secure_stage/target_wallet_copy'
    IDENTIFIED BY "TargetWalletPassword"
  WITH BACKUP USING 'before_wallet_merge';

This updates the staged destination password wallet and leaves the source unchanged. It does not switch the live database to that staged wallet. A planned wallet migration must also configure the final location, reopen the merged wallet, and update or recreate its auto-login companion as appropriate. Coordinate that change across all consumers of the wallet. Merging and relocating wallets

NOTE: Do not copy the source ewallet.p12 over the wallet of an existing destination CDB. That destination may need keys for other PDBs. Also, MOVE KEYS removes selected keys from the source keystore and is not a substitute for a clone's export/import. MIGRATE USING is for changing the keystore provider, such as migrating to Oracle Key Vault. Key-management SQL reference

The operational check I would add to every refresh job is simple: record which backup was restored, which keys were supplied, where the destination wallet was backed up, and whether encrypted application data was successfully read. Those four items make the next refresh, and the next recovery exercise, much easier to review.