Introduction
The TDE database encryption is one of the main Oracle database feature usage. Once the TDE configured, the wallet must be backed up. If the wallet is lost nobody can help to recover the database. Also for security reasons is not a good idea to store the wallet with the database RMAN backups.
OKV was created to address these main points: store in a safe place the database encryption keys and avoid to keep the keys on the disk.
In this post I will show how to configure, from scratch, the TDE on the database, how to upload the wallet keys in the OKV and how to configure the database to use these keys.
I choose to make the full configuration using the OKV API, so it can be scripted and implemented on a new server.
The passwords are not hidden in order to easy find which password is used in which case.
So let’s start…
The steps
- Configure the TDE at the datababse level.
- Configure the OKV RESTfull API.
- Add the endpoint server to the OKV.
- Upload database keys to OKV.
- Migrate from local keys usage to OKV.
Main configuration
Oracle Key Vault ip | 172.168.0.41 |
Oracle Key Vault version | 21.7 |
Database Server ip | 172.168.1.128 |
Database name | CDB01 |
Database version | 21c |
Configure TDE at database level
Create the directories
First let’s create some directories to keep the database wallet.
[oracle@okvcli oracle]$ export WALLET_DIR=/u01/app/oracle/wallet
[oracle@okvcli oracle]$ mkdir -p ${WALLET_DIR}/tde
[oracle@okvcli oracle]$ mkdir -p ${WALLET_DIR}/tde_seps
[oracle@okvcli oracle]$ mkdir -vp ${WALLET_DIR}/okv
[oracle@okvcli oracle]$ echo "export WALLET_DIR=/u01/app/oracle/wallet" >> $HOME/.bashrc
Set the TDE parameters
[oracle@okvcli oracle]$ . oraenv
ORACLE_SID = [CDB01] ?
[oracle@okvcli oracle]$ sqlplus / as sysdba
SQL> alter system set wallet_root = '/u01/app/oracle/wallet' scope=spfile;
SQL> alter system set tablespace_encryption_default_algorithm = 'AES256';
SQL> alter system set encrypt_new_tablespaces='ALWAYS';
SQL> shutdown immediate;
SQL> startup;
SQL> alter system set tde_configuration = "KEYSTORE_CONFIGURATION=FILE"
Wallet creation
SQL> select a.con_id, b.name, a.wrl_type,
a.wrl_parameter, a.status,
a.wallet_type
from v$encryption_wallet a,
v$containers b
where a.con_id=b.con_id
order by a.con_id;
CON_ID NAME WRL_TYPE WRL_PARAMETER STATUS WALLET_TYPE
---------- ---------- ------------ ------------------------------------ ------------------------------ ------------
1 CDB$ROOT FILE /u01/app/oracle/wallet/tde/ NOT_AVAILABLE UNKNOWN
2 PDB$SEED FILE NOT_AVAILABLE UNKNOWN
3 PDB1 FILE NOT_AVAILABLE UNKNOWN
Create the keystore at CDB level
SQL> administer key management create keystore identified by "Hello123";
keystore altered.
SQL> administer key management add secret 'Hello123' for client 'TDE_WALLET' to local auto_login keystore '/u01/app/oracle/wallet/tde_seps';
keystore altered.
SQL> administer key management set keystore open identified by external store container=all;
keystore altered.
select a.con_id, b.name, a.wrl_type,
a.wrl_parameter, a.status,
a.wallet_type
from v$encryption_wallet a,
v$containers b
where a.con_id=b.con_id
order by a.con_id;
CON_ID NAME WRL_TYPE WRL_PARAMETER STATUS WALLET_TYPE
---------- ---------- ------------ ------------------------------------ --------------------- ------------
1 CDB$ROOT FILE /u01/app/oracle/wallet/tde/ OPEN_NO_MASTER_KEY PASSWORD
2 PDB$SEED FILE OPEN_NO_MASTER_KEY PASSWORD
3 PDB1 FILE OPEN_NO_MASTER_KEY PASSWORD
Create the master key password MEK at CDB and PDB level
SQL> administer key management set key using tag 'CDB1: Initial MEK' identified by external store with backup container=current;
Keystore altered.
SQL> select a.con_id,
b.name, a.wrl_type, a.wrl_parameter, a.status
from v$encryption_wallet a,
v$containers b
where a.con_id=b.con_id order by a.con_id;
CON_ID NAME WRL_TYPE WRL_PARAMETER STATUS
---------- ---------- ------------ ------------------------------ ------------------------------
1 CDB$ROOT FILE /u01/app/oracle/wallet/tde/ OPEN
2 PDB$SEED FILE OPEN
3 PDB1 FILE OPEN_NO_MASTER_KEY
SQL> alter session set container=pdb1;
Session altered
SQL> administer key management set key using tag 'PDB1: Initial MEK' identified by external store with backup container=current;
Keystore altered.
SQL> alter session set container=CDB$ROOT;
Session altered.
SQL> select a.con_id,
b.name, a.wrl_type, a.wrl_parameter, a.status
from v$encryption_wallet a,
v$containers b
where a.con_id=b.con_id order by a.con_id;
CON_ID NAME WRL_TYPE WRL_PARAMETER STATUS
---------- ---------- ------------ ------------------------------ ------------------------------
1 CDB$ROOT FILE /u01/app/oracle/wallet/tde/ OPEN
2 PDB$SEED FILE OPEN
3 PDB1 FILE OPEN
Create autologin wallet
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL> administer key management create local auto_login keystore from keystore '/u01/app/oracle/wallet/tde' identified by "Hello123";
keystore altered.
Configure OKV RESTfull service on oracle database server
[oracle@okvcli bin]$ export JAVA_HOME=/u01/app/oracle/product/21.0.0/dbhome_1/jdk
[oracle@okvcli bin]$ echo "export JAVA_HOME=/u01/app/oracle/product/21.0.0/dbhome_1/jdk" >> $HOME/.bashrc
[oracle@okvcli oracle]$ mkdir /u01/app/oracle/okvapi
[oracle@okvcli oracle]$ cd okvapi/
[oracle@okvcli okvapi]$ curl -O -k https://172.168.0.41:5695/okvrestclipackage.zip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3865k 100 3865k 0 0 107M 0 --:--:-- --:--:-- --:--:-- 107M
[oracle@okvcli okvapi]$ unzip okvrestclipackage.zip
Archive: okvrestclipackage.zip
creating: lib/
creating: bin/
inflating: bin/okv
inflating: bin/okv.bat
creating: conf/
inflating: conf/okvrestcli.ini
inflating: conf/okvrestcli_logging.properties
inflating: lib/okvrestcli.jar
[oracle@okvcli okvapi]$ rm okvrestclipackage.zip
oracle@okvcli ~]$ export OKV_HOME=/u01/app/oracle/okvapi
[oracle@okvcli ~]$ echo "export OKV_HOME=/u01/app/oracle/okvapi" >> $HOME/.bashrc
[oracle@okvcli ~]$ cat $OKV_HOME/conf/okvrestcli.ini
[Default]
log_property=$OKV_HOME/conf/okvrestcli_logging.properties
server=172.168.0.41
okv_client_config=$WALLET_DIR/okv/conf/okvclient.ora
user=admin
client_wallet=$OKV_HOME/wallet
Edit the $OKV_HOME/bin/okv
file and uncomment the line export OKV_RESTCLI_CONFIG=$OKV_RESTCLI_DIR/conf/okvrestcli.ini
Create the wallet for OKV RESTfull API
As for the okvrestcli.ini
file I used the admin user (see user=admin
from okvrestcli.ini
) to configure the wallet. The password is the one defined in OKV for the admin
user.
[oracle@okvcli okvapi]$ mkdir $OKV_HOME/wallet
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv admin client-wallet add --client-wallet $OKV_HOME/wallet --wallet-user admin
Password: ******
{
"result" : "Success"
}
Test the correct installation of OKV RESTfull API
[oracle@okvcli conf]$ $OKV_HOME/bin/okv
{
"restCLIVersion" : "21.7.0.0.0"
}
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv server info get
{
"result" : "Success",
"value" : {
"caCertificateExpirationDate" : "2026-10-19 09:52:32",
"cpuCores" : "4",
"deploymentType" : "Standalone",
"diskInGB" : "3652",
"fraInGB" : "20",
"memoryInKB" : "30504316",
"serverCertificateExpirationDate" : "2024-10-19 09:57:11",
"serverTime" : "2023-11-02 10:40:47",
"version" : "21.7.0.0.0"
}
}
At this moment the OKV RESTfull API is communicate with the OKV server. So we can use the API to add the endpoint to OKV.
Add the endpoint to OKV.
First we can create a wallet in the OKV for the endpoint. This step is optional. The name of the wallet is DBCDB01_WLT
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv manage-access wallet create --wallet DBCDB01_WLT
{
"result" : "Success"
}
Now create the endpoint in the OKV
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv admin endpoint create --endpoint okvcli_host --description "$HOSTNAME, $(hostname -i)" --type ORACLE_DB --platform LINUX64
{
"result" : "Success"
}
In the OKV the added endpoint is REGISTERED as is not enrolled yet:
As we create a wallet for this endpoint let’s define it as default wallet for it:
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv manage-access wallet set-default --wallet DBCDB01_WLT --endpoint okvcli_host
{
"result" : "Success"
}
Enroll the endpoint:
[oracle@okvcli okvapi]$ echo $ORACLE_HOME
/u01/app/oracle/product/21.0.0/dbhome_1
[oracle@okvcli okvapi]$ echo $ORACLE_BASE
/u01/app/oracle
[oracle@okvcli okvapi]$ $OKV_HOME/bin/okv admin endpoint provision --endpoint okvcli_host --location /u01/app/oracle/wallet/okv --auto-login FALSE
Enter Oracle Key Vault endpoint password: OKV_cli_123
{
"result" : "Success"
}
The --location
parameter must be wallet_root
parameter path from the database plus okv
. In this path OKV will download the okvutil
file needed by the database to communicate with OKV server:
[oracle@okvcli okvapi]$ ls /u01/app/oracle/wallet/okv
bin conf csdk jlib lib log ssl
The okvclient.ora
file from /u01/app/oracle/wallet/okv/con
f path can be added in the $OKV_HOME/conf/okvrestcli.ini
file: okv_client_config=/u01/app/oracle/wallet/okv/conf/okvclient.ora
to be able to use the RESTfull API for this database.
Notice that I put the password in the command to identified it in the next steps.
At the end execute the root.sh
script, which creates the directory tree /opt/oracle/extapi/64/hsm/oracle/1.0.0
, changes ownership and permissions, then copies the PKCS#11 library into this directory.
The library PKCS#11 library liborapkcs.so
is used by Oracle Database to communicate with OKV.
[opc@tstokvcli ~]$ sudo su -
[root@tstokvcli ~]# /u01/app/oracle/wallet/okv/bin/root.sh
At OKV server level the endpoint is enrolled now.
Let’s test if the endpoint okvutil is working:
oracle@okvcli ~]$ cd /u01/app/oracle/wallet/okv/bin
[oracle@okvcli bin]$ ./okvutil list
Enter Oracle Key Vault endpoint password: OKV_cli_123
Unique ID Type Identifier
3E32A151-D656-4E43-ADE8-629B11B8B4C9 Template Default template for OKVCLI_HOST
At this moment we have the database encrypted with TDE, and the database server is able to communicate with the OKV server, and is enrolled in the OKV client.
The next step is to upload the TDE keys in the OKV.
Upload TDE key to OKV.
The first password id the wallet password (Hello123
) the second password is the endpoint password (OKV_cli_123
)
[oracle@okvcli bin]$ ./okvutil upload -t WALLET -l /u01/app/oracle/wallet/tde -g DBCDB01_WLT -v 4
okvutil version 21.7.0.0.0
Endpoint type: Oracle Database
Configuration file: /u01/app/oracle/wallet/okv/conf/okvclient.ora
Server: 172.168.0.41:5696
Standby Servers:
Uploading from /u01/app/oracle/wallet/tde
Enter source wallet password: Hello123
No auto-login wallet found, password needed
Enter Oracle Key Vault endpoint password: OKV_cli_123
ORACLE.SECURITY.DB.ENCRYPTION.MASTERKEY
Trying to connect to 172.168.0.41:5696 ...
Connected to 172.168.0.41:5696.
ORACLE.SECURITY.DB.ENCRYPTION.AZXyYcD7Y0+Rv5tK3Y2lrT8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.KM.ENCRYPTION.AZXyYcD7Y0+Rv5tK3Y2lrT8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.KT.ENCRYPTION.AZXyYcD7Y0+Rv5tK3Y2lrT8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.KB.ENCRYPTION.
ORACLE.SECURITY.ID.ENCRYPTION.
ORACLE.SECURITY.KT.ENCRYPTION.AezKLH/ZbU8ev0KGkyVh9XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.KM.ENCRYPTION.AezKLH/ZbU8ev0KGkyVh9XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.DB.ENCRYPTION.AezKLH/ZbU8ev0KGkyVh9XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORACLE.SECURITY.DB.ENCRYPTION.MASTERKEY.0928CAFC93BBEE6CE0638001A8AC296F
Uploaded 2 TDE keys
Uploaded 0 SEPS entries
Uploaded 0 other secrets
Uploaded 4 opaque objects
Uploading private key
Uploading certificate request
Uploading trust points
Uploaded 1 private keys
Uploaded 1 certificate requests
Uploaded 0 user certificates
Uploaded 0 trust points
Upload succeeded
[oracle@okvcli bin]$ ./okvutil list
Enter Oracle Key Vault endpoint password: OKV_cli_123
Unique ID Type Identifier
F1C1537B-970E-4F09-BF41-6E5525D92E28 Opaque Object TDE Wallet Metadata
A2FE6566-A68E-5217-89B0-19370EF78066 Symmetric Key TDE Master Encryption Key: TAG CDB1: Initial MEK
F3C5C8F1-5DBA-4FF2-BF28-4EC3E8606772 Opaque Object TDE Wallet Metadata
3E77A59D-DB88-4F26-BF7C-5449137B46FE Opaque Object TDE Wallet Metadata
C910D912-0031-5776-AE3F-43967710B8DB Symmetric Key TDE Master Encryption Key: TAG PDB1: Initial MEK
0ABA58D9-7295-4F12-BFBF-F13382476355 Opaque Object TDE Wallet Metadata
492260F0-113C-4F07-BFCA-25360F0173BC Private Key Private Key
4F1FC5D9-2C87-4F56-BF4B-6B3A5D730C6E Opaque Object Certificate Request
3E32A151-D656-4E43-ADE8-629B11B8B4C9 Template Default template for OKVCLI_HOST
At database level we are still in the FILE
keystore mode (local on the server).
SQL> select wrl_type, status, con_id from v$encryption_wallet;
WRL_TYPE STATUS CON_ID
---------------- ------ ------
FILE OPEN 1
FILE OPEN 2
FILE OPEN 3
At OKV server level the wallet DBCDB01_WLT
contains our keys and the OKVCLI_HOST
endpoint has access to the wallet:
Migrate the FILE local wallet to OKV
SQL> show con_id
CON_ID
------------------------------
1
SQL> alter system set tde_configuration = "KEYSTORE_CONFIGURATION=OKV|FILE" ;
SQL> administer key management set encryption key identified BY "OKV_cli_123" migrate using "Hello123" WITH BACKUP;
keystore altered.
The parameter "KEYSTORE_CONFIGURATION=OKV|FILE"
means that the database will get the encryption key from OKV and the auto_login file cwallet.sso
from local disk (/u01/app/oracle/wallet/tde
)
Remove the auto_login file from the tde
, directory in order to create the new auto_login file:
[oracle@okvcli tde]$ cd /u01/app/oracle/wallet/tde
[oracle@okvcli tde]$ rm cwallet.sso
Create the auto_login file for OKV access:
SQL> administer key management add secret 'OKV_cli_123' for client 'OKV_PASSWORD' to local auto_login keystore '/u01/app/oracle/wallet/tde';
keystore altered.
SQL> select wrl_type, status, con_id from v$encryption_wallet;
WRL_TYPE STATUS CON_ID
----------- -------- --------
FILE OPEN 1
OKV OPEN 1
FILE OPEN 2
OKV OPEN 2
FILE OPEN 3
OKV OPEN 3
At this step the database use OKV for the encryption key and local file for auto_login. In the wallet directory /u01/app/oracle/wallet/tde
only the cwallet.sso
file should exist.
Final test
The final test consist in the creation of an encrypted tablespace with a table inside, then clean local wallet (ewallet.p12
file ) and finally restart the database.
If everything is correctly configured then no password should be asked, the CDB and PDB(s) must be opened, the encrypted tablespace and the table must be accessible.
Let’s clean the /u01/app/oracle/wallet/tde
directory (is a good practice to start by making a backup in another directory, just in case):
[oracle@okvcli tde]$ cd /u01/app/oracle/wallet/tde
[oracle@okvcli tde]$ mkdir bck
[oracle@okvcli tde]$ mv ewallet_* bck
[oracle@okvcli tde]$ ls
cwallet.sso
Create an encrypted (ENCR_TBS
) tablespace and add a table (ENCR_TABLE
):
SQL> alter session set container=pdb1;
Session altered.
SQL> create tablespace encr_tbs;
SQL> select tablespace_name, encrypted from dba_tablespaces where tablespace_name='ENCR_TBS';
TABLESPACE_NAME ENC
------------------------------ ---
ENCR_TBS YES
SQL> create table encr_table(c number) tablespace encr_tbs;
Table created.
SQL> insert into encr_table values(1);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from encr_table;
C
----------
1
SQL> alter session set container=CDB$ROOT;
Session altered
Finally restart the database and try to select the table:
SQL> shutdown immediate;
SQL> startup;
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ----------- ----------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
SQL> alter session set container=pdb1;
Session altered.
SQL> select * from encr_table;
C
----------
1
Conclusion
Using OKV to store TDE encryption keys is the preferred solution. The RESTfull API proposed by OKV is complete and easy to configure. It is a good practice to script all commands in order to add the endpoints, and configure the database, as a post script of vm creation for instance.
Nkec
22.11.2023Hi Alexandre,
Thank you for very usefull okv posts.
Have you executed root.sh after db endpoint enrollment (Copying PKCS library)?
(This step is missing in the post)
My understanding:
PKCS library is needed for 'tde online' encription . (KEYSTORE_CONFIGURATION=OKV|FILE)
PKCS library is not needed if okv is used only for 'long term wallet backup' . (KEYSTORE_CONFIGURATION=FILE; okv is used to upload/download wallet).
Best regards.
Alexandre Nestor
22.11.2023You are right. The step is missing. As I tried several time, and root.sh is to be executed only one time, I skipped the step. Thank's for the remark. I will add it.
The root-sh copy the liborapkcs.so library to /opt/oracle/extapi/64/hsm/oracle/1.0.0 (on unix like platform). This library is used by in the communication between Oracle Database and. If the KEYSTORE_CONFIGURATION=FILE then OKV is not used.
Besides, in my opinion OKV is a long term wallet backup solution. In case of rekey, OKV keep the trace of the old key. In case of KEYSTORE_CONFIGURATION=FILE you have to manage it by yourself, which can be tricky.