by Alexandre Nestor
Introduction
This post is to describe the process of cloning an Oracle Database which is configured to store the TDE (encryption keys) in the Oracle Key Vault (OKV)
If the source database is configured with Oracle key Vault, than we can clone the database withouth having to transport the key files on the destination server.
In this exemple the clone will be made on the same host.
To install the RESTFul API and add a database as endpoint to OKV check my previous BLOG Add Oracle database server to Oracle Key vault (OKV) from scratch, only with RESTfull API.
The initial configuration is :
- The source database name is
CDB01
- The target database name will be
CDB02
- The
wallet_root
database parameter on source database,CDB01
, is set to/opt/oracle/admin/CDB01/wallet
- The
tde_configuration
parameter on source database,CDB01
, is set toKEYSTORE_CONFIGURATION=OKV|FILE
. That means that the keystore is in OKV server and the auto login file is on local filesystem in/opt/oracle/admin/CDB01/wallet/tde
path. - The source database is enrolled as an endpoint. A wallet was defined for the
CDB01
endpoint, and the TDE keys are uploaded in this wallet. - On
CDB01
the SYS password is tagged as sys_pwd - The endpoint password is tagged as endpoint_pwd
- The RESTFul API is installed on the server in the path
$HOME/okv
- Finally, the name of the wallet defined in OKV which contains the TDE keys for
CDB01
database isORA_DB
The schema is something like this:

The CDB01
database store his keys in ORA_DB
wallet. Normally it has the rights to read/write in this wallet. At enrol time, we are going to give the rights ro read the ORA_DB
wallet to CDB02
endpoint (database).
I also use a simple sql script to check the wallet status at the database level:
[oracle@db ~]$ cat $HOME/tde.sql
set pages 200
set line 300
col WRL_PARAMETER format a50
col status forma a10
col pdb_name format a20
select pdb_id, pdb_name, guid from dba_pdbs;
select * from v$encryption_wallet where con_id != 2;
Declare and enrol the endpoint for CDB02
The first step is the enrolment of the destination database, CDB02, and grant the rights to read the keys from OKV server.
Create the destination directory structure for CDB02.
[oracle@db ~]$ cat $HOME/okv/set_okv_rest_env.sh
export OKV_RESTCLI_CONFIG=$HOME/okv/conf
export JAVA_HOME=/usr/java/jdk-11.0.10
export OKV_HOME=$HOME/okv
# source the RESFul API environnement file
[oracle@db ~]$ source $HOME/okv/set_okv_rest_env.sh
Create the database endpoint, for CDB02
, using a JSON parameter file:
# create the JSON file for endpoint creation
[oracle@db ~]$ cat 01.create_endpoint_CDB02.json
{
"service" : {
"category" : "admin",
"resource" : "endpoint",
"action" : "create",
"options" : {
"endpoint" : "DB_CDB02",
"description" : "DB server CDB02",
"platform" : "LINUX64",
"type" : "ORACLE_DB",
"strictIpCheck" : "FALSE"
}
}
}
# create the endpoint on OKV
[oracle@db ~]$ $OKV_HOME/bin/okv admin endpoint create --from-json 01.create_endpoint_CDB02.json
{
"result" : "Success"
}
Enrol the CDB02 endpoint.
# create the enroll endpoint JSON file
[oracle@db ~]$ cat 02.provision_endpoint_CDB02.json
{
"service" : {
"category" : "admin",
"resource" : "endpoint",
"action" : "provision",
"options" : {
"endpoint" : "DB_CDB02",
"location" : "/opt/oracle/admin/CDB02/wallet/okv",
"autoLogin" : "FALSE"
}
}
}
# enroll the endopoint
[oracle@db ~]$ $OKV_HOME/bin/okv admin endpoint provision --from-json 02.provision_endpoint_CDB02.json
Enter Oracle Key Vault endpoint password: endpoint_pwd
{
"result" : "Success"
}
Grant the access to the new CDB02
endpoint to read the wallet ORA_DB
which keep the CDB01
TDE keys.
# create the grant access file to the wallet Keeping the source CDB01 Keys.
[oracle@db ~]$ cat 04_grant_access_wallet_CDB02.json
{
"service" : {
"category" : "manage-access",
"resource" : "wallet",
"action" : "add-access",
"options" : {
"wallet" : "ORA_DB",
"endpoint" : "DB_CDB02",
"access" : "RM_MW"
}
}
}
# grant the access to the ORA_DB wallet for the endpoint.
[oracle@db ~]$ $OKV_HOME/bin/okv manage-access wallet add-access --from-json 04_grant_access_wallet_CDB02.json
{
"result" : "Success"
}
Check that CDB02
endpoint can read the keys from CDB01
wallet.
# Test
[oracle@db ~]$ /opt/oracle/admin/CDB02/wallet/okv/bin/okvutil list
Enter Oracle Key Vault endpoint password: endpoint_pwd
Enter Oracle Key Vault endpoint password:
Unique ID Type Identifier
600D0743-01D9-4F2F-BF6F-C9E8AC74FF2A Symmetric Key TDE Master Encryption Key: TAG CDB:CDB01 MEK first
6A752388-F93D-4F14-BF35-39E674CAAFED Symmetric Key TDE Master Encryption Key: TAG REKEY CDB01
AB294686-1FC4-4FE8-BFAD-F56BAD0A124B Symmetric Key TDE Master Encryption Key: TAG REKEY CDB01
BB0CC77A-10AD-4F55-BF0A-9F5A4C7F98C1 Symmetric Key TDE Master Encryption Key: TAG CDB:DBTDEOKV:PDB1 MEK first
At this level okvutil list
for CDB02
endpoint, command return the keys available for CDB01
source database.
Clone the CDB01 to CDB02
Create an temporary init file with the TDE OKV parameters.
[oracle@db ~]$ cat /tmp/init.ora
db_name='CDB02'
wallet_root='/opt/oracle/admin/CDB02/wallet'
tde_configuration='KEYSTORE_CONFIGURATION=OKV|FILE';
enable_pluggable_database=true
Copy the Oracle password file /opt/oracle/product/19c/dbhome_1/dbs/orapwdCDB01
to /opt/oracle/product/19c/dbhome_1/dbs/orapdwCDB02
.
Add the CDB02
as static identifier to the listener.
[oracle@db ~]$ cat $ORACLE_HOME/network/admin/listener.ora
LISTENER = (ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=db.sub05191447261.vcn01.oraclevcn.com)(PORT=1521)))
SID_LIST_LISTENER=
(SID_LIST=
.....
(SID_DESC=
(GLOBAL_DBNAME=CDB02)
(SID_NAME=CDB02)
(ORACLE_HOME=/opt/oracle/product/19c/dbhome_1)
)
)
# restart the listener
[oracle@db ~]$ lsnrctl start listener
.....
Services Summary...
Service "CDB01" has 1 instance(s).
Instance "CDB01", status UNKNOWN, has 1 handler(s) for this service...
Service "CDB02" has 1 instance(s).
Instance "CDB02", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
Set the CDB02
environnement and start the database using the temporary init file.
[oracle@db ~]$ . oraenv <<< CDB02
[oracle@db ~]$ sqlplus / as sysdba
SQL> startup nomount pfile='/tmp/init.ora'
SQL> exit;
[oracle@db ~]$ rman target sys/sys_pwd@CDB01 auxiliary sys/sys_pwd@CDB02
connected to target database: CDB01 (DBID=1690718290)
connected to auxiliary database: CDB02 (not mounted)
RMAN> run {
allocate auxiliary channel aux1 device type disk;
allocate auxiliary channel aux2 device type disk;
duplicate target database to CDB02 from active database
SPFILE
PARAMETER_VALUE_CONVERT 'CDB01' 'CDB02'
NOFILENAMECHECK;
}
using target database control file instead of recovery catalog
allocated channel: aux1
channel aux1: SID=180 device type=DISK
allocated channel: aux2
channel aux2: SID=21 device type=DISK
Starting Duplicate Db at 26-MAR-24
current log archived
contents of Memory Script:
{
restore clone from service 'CDB01' spfile to
'/opt/oracle/product/19c/dbhome_1/dbs/spfileCDB02.ora';
sql clone "alter system set spfile= ''/opt/oracle/product/19c/dbhome_1/dbs/spfileCDB02.ora''";
}
.....
contents of Memory Script:
{
Alter clone database open resetlogs;
}
executing Memory Script
database opened
contents of Memory Script:
{
sql clone "alter pluggable database all open";
}
executing Memory Script
sql statement: alter pluggable database all open
Finished Duplicate Db at 26-MAR-24
The clone is finished. Test the WALLET configuration
[oracle@db ~]$ . oraenv <<< CDB02
[oracle@db ~]$ sqlplus / as sysdba
SQL> @$HOME/tde
PDB_ID PDB_NAME GUID
---------- -------------------- --------------------------------
3 PDB01 0AE3AEC4EE5ACDB1E063A001A8ACB8BB
2 PDB$SEED 0AE38C7FF01EC651E063A001A8AC821E
WRL_TYPE WRL_PARAMETER STATUS WALLET_TYPE WALLET_OR KEYSTORE FULLY_BAC CON_ID
--------- ------------------------------------- -------------- ------------ --------- -------- --------- ----------
FILE /opt/oracle/admin/CDB02/wallet/tde/ NOT_AVAILABLE UNKNOWN SINGLE NONE UNDEFINED 1
OKV CLOSED UNKNOWN SINGLE NONE UNDEFINED 1
FILE NOT_AVAILABLE UNKNOWN SINGLE UNITED UNDEFINED 3
OKV CLOSED UNKNOWN SINGLE UNITED UNDEFINED 3
-- the wallet is closed. Open it:
SQL> administer key management set keystore open identified by "endpoint_pwd" container=all;
keystore altered.
SQL> @$HOME/tde
PDB_ID PDB_NAME GUID
---------- -------------------- --------------------------------
3 PDB01 0AE3AEC4EE5ACDB1E063A001A8ACB8BB
2 PDB$SEED 0AE38C7FF01EC651E063A001A8AC821E
WRL_TYPE WRL_PARAMETER STATUS WALLET_TYPE WALLET_OR KEYSTORE FULLY_BAC CON_ID
--------- ------------------------------------ ---------- -------------- --------- -------- --------- ----------
FILE /opt/oracle/admin/CDB02/wallet/tde/ OPEN_NO_MA AUTOLOGIN SINGLE NONE UNDEFINED 1
STER_KEY
OKV OPEN OKV SINGLE NONE UNDEFINED 1
FILE OPEN_NO_MA AUTOLOGIN SINGLE UNITED UNDEFINED 3
STER_KEY
OKV OPEN OKV SINGLE UNITED UNDEFINED 3
Finally create the auto login wallet, and restart the cloned database to validate the configuration.
[oracle@db ~]$ . oraenv <<< CDB02
[oracle@db ~]$ sqlplus / as sysdba
-- "OKV_PASSWORD" is used to open the wallet.
-- "HSM_PASSWORD" is used to access the OKV server(s).
SQL> ADMINISTER KEY MANAGEMENT ADD SECRET 'endpoint_pwd' FOR CLIENT 'HSM_PASSWORD' TO AUTO_LOGIN KEYSTORE '/opt/oracle/admin/CDB02/wallet/tde';
-- check that the autologin wallet was created
SQL> !ls /opt/oracle/admin/CDB02/wallet/tde
cwallet.sso
SQL> startup force
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB01 MOUNTED
SQL> alter pluggable database PDB01 open;
Pluggable database altered.
SQL> @$HOME/tde
PDB_ID PDB_NAME GUID
---------- -------------------- --------------------------------
3 PDB01 0AE3AEC4EE5ACDB1E063A001A8ACB8BB
2 PDB$SEED 0AE38C7FF01EC651E063A001A8AC821E
WRL_TYPE WRL_PARAMETER STATUS WALLET_TYPE WALLET_OR KEYSTORE FULLY_BAC CON_ID
--------- ------------------------------------ ---------- -------------- --------- -------- --------- ----------
FILE /opt/oracle/admin/CDB02/wallet/tde/ OPEN_NO_MA AUTOLOGIN SINGLE NONE UNDEFINED 1
STER_KEY
OKV OPEN OKV SINGLE NONE UNDEFINED 1
FILE OPEN_NO_MA AUTOLOGIN SINGLE UNITED UNDEFINED 3
STER_KEY
OKV OPEN OKV SINGLE UNITED UNDEFINED 3
All PDB are correctly opened and the wallet are opened too.
Conclusion
The clone process can be fully automatised, and no wallet file must be transfered between the source and the destination server. With the keys in OKV the clone process is identically as withouth OKV. Keeping the keys in OKV is more secure as the principle “Zero touch keys” is respected, and DBA do not manipulate the keys.
Finally if we want to configure the database CDB02
to use another keys as the keys from CDB01
, we can execute a REKEY operation.
Catdba107
12.07.2024Thanks for the document. It is very helpful. Just one comment, it might be better to create a new virtual wallet for the clone target DB (CDB02), shared the key from source DB wallet to this new wallet in OKV, grant read/write access of the new virtual wallet to CDB02 endpoint. Then start the RMAN clone. Once finished, rekey to the CDB02 virtual wallet as needed. In your example, you only grant read access of the source wallet to target DB, so both DBs are sharing one wallet, when you rekey, it affects both DBs, you want them to be separate and independent. Everything else is great.
Alexandre Nestor
17.07.2024Hello, thank for the feedback. It is exactly whai I did, finally, in production ;). It is just to keep more simple the post...