Encryption Wallet Location
My encryption wallet location is set to the following (sqlnet.ora):
ENCRYPTION_WALLET_LOCATION= (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /u01/app/oracle/admin/$ORACLE_SID/wallet/tde) ) )Create a non-CDB database
Let's start by creating a non-CDB database. I will call this database db1 and it will later be converted to a pluggable database called pdb1:
dbca -silent \ -createDatabase \ -templateName New_Database.dbt \ -gdbName db1 \ -createAsContainerDatabase false \ -sysPassword oracle \ -systemPassword oracle \ -emConfiguration none \ -datafileDestination /u02/oradata \ -redoLogFileSize 128 \ -recoveryAreaDestination /u02/fra \ -storageType FS \ -characterSet al32utf8 \ -nationalCharacterSet al16utf16 \ -automaticMemoryManagement false \ -initParams filesystemio_options=setall \ -initParams session_cached_cursors=100 \ -totalMemory 1024 Creating and starting Oracle instance 1% complete ... 100% completeSince I have PSU2 applied I need to run datapatch once the database has been created:
[oracle@ora12cr1 ~]$ . oraenv ORACLE_SID = [oracle] ? db1 The Oracle base remains unchanged with value /u01/app/oracle [oracle@ora12cr1 ~]$ $ORACLE_HOME/OPatch/datapatch -verboseCreate the wallet and encrypted table
We're now ready to setup the wallet and create a user with an encrypted table:
[oracle@ora12cr1 ~]$ mkdir -p /u01/app/oracle/admin/db1/wallet/tde [oracle@ora12cr1 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Sat Mar 7 15:51:21 2015 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> alter system set encryption key identified by "db1"; System altered. SQL> alter system set db_create_file_dest='/u02/oradata'; System altered. SQL> create tablespace encrypted datafile size 64m encryption using 'AES256' default storage (encrypt); Tablespace created. SQL> create user encrypt_user identified by "encrypt_user" default tablespace encrypted; User created. SQL> alter user encrypt_user quota unlimited on encrypted; User altered. SQL> create table encrypt_user.z_encrypted as select dbms_random.string('x', 100) s from dual connect by level <= 100; 2 3 4 Table created.Note that I did not use the new administer key management syntax on purpose and instead created the wallet the old style way as I expect most of the existing environments to be the same. We will explore the significance of this in a moment.
Create a CDB
Before our non-CDB database can be converted to a PDB and plugged into a CDB we need to create the container database first:
[oracle@ora12cr1 ~]$ dbca -silent \ > -createDatabase \ > -templateName New_Database.dbt \ > -gdbName cdb12cr1 \ > -createAsContainerDatabase true \ > -sysPassword oracle \ > -systemPassword oracle \ > -emConfiguration none \ > -datafileDestination /u02/oradata \ > -redoLogFileSize 128 \ > -recoveryAreaDestination /u02/fra \ > -storageType FS \ > -characterSet al32utf8 \ > -nationalCharacterSet al16utf16 \ > -automaticMemoryManagement false \ > -initParams filesystemio_options=setall \ > -initParams session_cached_cursors=100 \ > -totalMemory 1024 Creating and starting Oracle instance 1% complete ... 100% completeAs before I need to run the datapatch utility:
[oracle@ora12cr1 ~]$ . oraenv ORACLE_SID = [oracle] ? cdb12cr1 The Oracle base remains unchanged with value /u01/app/oracle [oracle@ora12cr1 ~]$ $ORACLE_HOME/OPatch/datapatch -verbose
Setup CDB with a wallet
Our newly created CDB needs to be setup with a wallet before we proceed with plugging a PDB which utilizes TDE. Let's do it now:
[oracle@ora12cr1 ~]$ mkdir -p /u01/app/oracle/admin/cdb12cr1/wallet/tde [oracle@ora12cr1 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Sat Mar 7 17:23:58 2015 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> administer key management create keystore '/u01/app/oracle/admin/cdb12cr1/wallet/tde' identified by "cdb12cr1"; 2 3 keystore altered. SQL> administer key management set keystore open identified by "cdb12cr1"; 2 3 keystore altered. SQL> administer key management set key identified by "cdb12cr1" with backup; 2 3 keystore altered.
Here I have setup the wallet and the master encryption key using the new syntax.
Wallets
Before we move forward let's explore the differences between db1 (created using the old syntax) and cdb12cr1 (created using the new syntax) wallets:
[oracle@ora12cr1 ~]$ orapki wallet display -wallet /u01/app/oracle/admin/db1/wallet/tde Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter wallet password: Requested Certificates: Subject: CN=oracle User Certificates: Oracle Secret Store entries: ORACLE.SECURITY.DB.ENCRYPTION.AY/sdMkWZk/4v3YgBKzZtcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.DB.ENCRYPTION.MASTERKEY ORACLE.SECURITY.ID.ENCRYPTION. ORACLE.SECURITY.KB.ENCRYPTION. Trusted Certificates: [oracle@ora12cr1 ~]$ orapki wallet display -wallet /u01/app/oracle/admin/cdb12cr1/wallet/tde Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter wallet password: Requested Certificates: Subject: CN=oracle User Certificates: Oracle Secret Store entries: ORACLE.SECURITY.DB.ENCRYPTION.Ad+A607CLU+Ivx4f4E7KUYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.DB.ENCRYPTION.MASTERKEY ORACLE.SECURITY.ID.ENCRYPTION. ORACLE.SECURITY.KB.ENCRYPTION. ORACLE.SECURITY.KM.ENCRYPTION.Ad+A607CLU+Ivx4f4E7KUYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Trusted Certificates:Notice how db1 has the encryption key listed under ORACLE.SECURITY.DB.ENCRYPTION while cdb12cr1 in addition has the encryption key listed under the new ORACLE.SECURITY.KM.ENCRYPTION as well.
In practice what I found is unless your encryption key is listed under ORACLE.SECURITY.KM.ENCRYPTION it will not be exported when doing administer key management export keys. As a result when you import the export file the master key required to decrypt the data will not be there potentially leaving you in a peculiar situation especially if you have used an in-place conversion. Even if you specifically export the key using the with identifier in syntax you will not be able to import the key because specific key exports are not permitted to be imported into the PDBs.
Add ORACLE.SECURITY.KM.ENCRYPTION to db1's wallet
This step is only required if you created the wallet without using the new administer key management syntax. Re-keying the wallet will generate a new master key preserving the old master key necessary to decrypt the data while adding missing ORACLE.SECURITY.KM.ENCRYPTION entries at the same time. Execute while connected to db1:
SQL> administer key management set key identified by "db1" with backup; 2 3 keystore altered.If we look at the wallet we can see that it now contains the necessary entires:
[oracle@ora12cr1 ~]$ orapki wallet display -wallet /u01/app/oracle/admin/db1/wallet/tde Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter wallet password: Requested Certificates: Subject: CN=oracle User Certificates: Oracle Secret Store entries: ORACLE.SECURITY.DB.ENCRYPTION.AXZlzWtP/U/xv+vihPzeaGkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.DB.ENCRYPTION.AY/sdMkWZk/4v3YgBKzZtcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.DB.ENCRYPTION.MASTERKEY ORACLE.SECURITY.ID.ENCRYPTION. ORACLE.SECURITY.KB.ENCRYPTION. ORACLE.SECURITY.KM.ENCRYPTION.AXZlzWtP/U/xv+vihPzeaGkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.KM.ENCRYPTION.AY/sdMkWZk/4v3YgBKzZtcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ORACLE.SECURITY.KM.ENCRYPTION.MASTERKEY Trusted Certificates:Prepare db1 to be converted into a PDB
Before db1 can be plugged into a container database it needs to be converted to a PDB and it's encryption keys exported. Shutdown db1 and open it in read only:
SQL> show parameter db_name NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_name string db1 SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SQL> startup mount restrict ORACLE instance started. Total System Global Area 1241513984 bytes Fixed Size 2923872 bytes Variable Size 452985504 bytes Database Buffers 771751936 bytes Redo Buffers 13852672 bytes Database mounted. SQL> alter database open read only; Database altered.We can now export the encryption keys:
SQL> administer key management set keystore open identified by "db1"; 2 3 keystore altered. SQL> administer key management export keys with secret "db1" to '/u01/app/oracle/admin/cdb12cr1/wallet/tde/db1.exp' identified by "db1"; 2 3 4 keystore altered.Note that in order for the export operation to work the wallet needs to be explicitly opened with a password otherwise you will receive an error. In case of an auto login (local) wallet you will have to close the wallet and reopen it with a password.
The next step is to generate metadata necessary for PDB conversion and shutdown db1 database:
SQL> exec dbms_pdb.describe(pdb_descr_file => '/u01/app/oracle/db1.xml'); PL/SQL procedure successfully completed. SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down.Convert and plug db1 into a CDB
We can now login into cdb12cr1 and perform in-place conversion of db1 which does not requires any datafiles to be copied. Of course if something were to go wrong with the conversion process you might end up in a situation where you need to restore your original database from a backup so use this approach with care.
SQL> show parameter db_name NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_name string cdb12cr1 SQL> create pluggable database pdb1 using '/u01/app/oracle/db1.xml' nocopy tempfile reuse; 2 3 Pluggable database created.Before pdb1 can be opened we need to run the script which will convert pdb1's data dictionary:
SQL> alter session set container=pdb1; Session altered. SQL> @?/rdbms/admin/noncdb_to_pdb.sqlOnce the script completes we can open pdb1:
SQL> alter pluggable database pdb1 open; Warning: PDB altered with errors.The error while opening the PDB tells us that the encryption key is missing (can be seen in pdb_plug_in_violations view). Let's go and import the key now:
[oracle@ora12cr1 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Sat Mar 7 18:22:23 2015 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> alter session set container=pdb1; Session altered. SQL> administer key management set keystore open identified by "cdb12cr1"; 2 3 keystore altered. SQL> administer key management import keys with secret "db1" from '/u01/app/oracle/admin/cdb12cr1/wallet/tde/db1.exp' identified by "cdb12cr1" with backup; 2 3 4 5 keystore altered. SQL> alter pluggable database pdb1 close; Pluggable database altered. SQL> alter pluggable database pdb1 open; Pluggable database altered.The encryption keys are now imported and we no longer get an error. Note that as with the export in order to import the keys the wallet must be explicitly opened with a password. We can verify that everything is in order by querying the encrypted table:
SQL> administer key management set keystore open identified by "cdb12cr1"; 2 3 keystore altered. SQL> select count(*) from encrypt_user.z_encrypted; COUNT(*) ---------- 100