Friday, August 29, 2025

Oracle Master Encryption Key Management: Wallets, OKV, and OCI KMS Explained

Data Encryption Keys (DEK) are used by encryption algorithms (typically AES256) to protect data at rest in tablespaces, backups and even datapump exports. Since DEKs are stored with the data, they need to be protected.  Master Encryption Keys (MEK) are stored outside the database in local wallets or in an external keystore, and MEKs are used to encrypt the DEK which provides a separation between the data that is encrypted and an external key.

DEKs are not only found on Tablespaces (TDE), but they are also found in RMAN encrypted backups, Space Efficient Encrypted backups to ZDLRA/Recovery Service and encrypted datapump exports.

The diagram below shows that relationship between MEKs and DEKs.




You can see in the diagram that MEKs are not only used to encrypt Tablespace Encryption Keys to support TDE, they are also used to encrypt RMAN backups to disk, Tape or ZDLRA/Recovery Service, along with Datapump encryption keys.  

NOTE: When implementing encryption you should make sure you meet ASO licensing restrictions
  • Creating encrypted tablespaces or encrypted columns in tables requires ASO, unless you are leveraging an OCI Cloud Database environment (including multicloud).
  • Creating RMAN encrypted disk backups requires licensing.
  • Creating RMAN encrypted tape backups is license included and only supported when writing to Oracle products.
    • OSB - Oracle Secure Backup is license included for creating encrypted backups.
    • OCI Object Storage - The OCI cloud library requires encryption and can only be leveraged for writing backups directly to OCI object storage in OCI, or writing backups from a ZDLRA to OCI object storage in cloud or on ZFSSA
    • ZDLRA - Creating Space Efficient Encrypted backups is license included on ZDLRA and will create encrypted backups on ZDLRA.
  • Creating Datapump Encrypted backups requires licensing. 


MEKs are commonly called "TDE keys", but they are much more, and I will refer to them as MEKs throughout this post.

MEK with a Wallet File

In this first section I am going to talk about how the Oracle Database manages an MEK when using a Wallet file.

Wallet settings

With wallet-based MEKs, the database stores and reads keys from a wallet file on disk (or +ASM or Exascale).

There are 2 parameters in the database (spfile) that help guide the database to the wallet file.

WALLET_ROOT - This replace the "ENCRYPTION_WALLET_LOCATION" parameter that was previous set in the sqlnet.ora file.  Having it set at the database level allows multiple databases to independently share the same $ORACLE_HOME. It even allows PDBs to have individual wallet files. When using a wallet file, the WALLET_ROOT points to top directory where the encryption keys will be kept.

TDE_CONFIGURATION - This tells the database what kind of MEK will be used. For wallets you would specify "TDE_CONFIGURATION=FILE".  This tells the database to use find the encryption keys in an encryption wallet.

Encryption key location

Within the WALLET_ROOT directory the encryption wallet containing the MEKs, the wallet must be stored in a subdirectory named "tde".

Within that directory you will find 2 wallet files

  • ewallet.p12 - The password-protected wallet (contains keys; required for updates).
  • ewallet.sso — the auto-login wallet (allowing no password prompt on open); The auto-login wallet can also be created as a “local” autologin wallet bound to a single host.

On startup (or when you open the keystore), the database retrieves the CDB/PDB MEKs from the wallet file and caches them in memory.

Database interaction with MEK

When using a wallet file, the auto-login wallet file is opened when the database is opened, and the database constantly interacts with this file.  If no auto-login wallet file is created, you must open the wallet manually providing the password.

Viewing V$ENCRYPTION_WALLET 

What you’ll typically see for FILE based wallets:

PDB_NAME        WALLET_TYPE  STATUS  WRL_PARAMETER                KEYSTORE
--------------  -----------  ------  ----------------------------  --------
CDB$ROOT        AUTOLOGIN    OPEN    {WALLET_ROOT}/tde             NONE
DB23AI_PDB      AUTOLOGIN    OPEN                                  UNITED

MEK with OKV/OCI KMS

When using an external keystore, the database communicates with the OKV/OCI KMS client libraries installed on the host in order to retrieve the MEKs.

OKV/OCI KMS settings

There are 2 parameters in the database (spfile) that help guide the database to the OKV/OCI KMS installation.

WALLET_ROOT -  When using OKV/OCI KMS, the WALLET_ROOT points to top directory of the client install of the OKV/OCI KMS software.

TDE_CONFIGURATION - For OKV/OCI KMS  specify "TDE_CONFIGURATION=OKV" or "TDE_CONFIGURATION=HSM".  It is possible to combine both wallets and  OKV/OCI KMS if there are older keys that are still stored a wallet file. In that case you would see "TDE_CONFIGURATION=OKV|FILE" for example, and the database would read older encryption keys from a wallet file along with reading the keys from OKV/OCI MKS.

Encryption key location

Within the WALLET_ROOT directory, the software to communicate with the HSM is typically installed in the "okv" or "hsm" subdirectory.  The keys themselves are stored externally, and could be securely cached locally depending on your configuration.

The credential used to access OKV/OCI KMS is typically stored under the /tde directory in an auto-login wallet. This allows the database to connect to OKV/OCI KMS at startup. The external password store entries (if used) live under /tde_seps which allows up to manage keys without entering a password.

Database interaction with MEK

The MEK is always permanently stored externally.  The database interacts with the external keystore through a library.  This library is named liborapkcs.so.  The library itself is vendor specific and is used by the database to interact with different vendors keystore,. Because there is a single library, you cannot use multiple external key store types on the same DB host.
When the database starts up, it reads the password for the external keystore out of the wallet, opens up a connection to the keystore (after authentication and encryption handshake) and caches the MEK.  The database periodically will communicate with the external keystore through that library.


OKV/OCI MKS in Practice: What You’ll See

When both FILE and OKV configurations exist (e.g., during migration), you may observe dual rows in V$ENCRYPTION_WALLET showing the FILE wallet (no active master key) and the active OKV keystore:

PDB_NAME        TYPE  STATUS             WALLET_TYPE  WRL_PARAMETER
--------------  ----  -----------------  -----------  ---------------------------
CDB$ROOT        FILE  OPEN_NO_MASTERKEY  AUTOLOGIN    {WALLET_ROOT}/tde
CDB$ROOT        OKV   OPEN               OKV
DB23AI_PDB      FILE  OPEN_NO_MASTERKEY  AUTOLOGIN
DB23AI_PDB      OKV   OPEN               OKV


Best Practices & Notes

  • Back up only the passworded wallet when using a wallet file. (ewallet.p12) and store it securely, separate from database backups.
  • Use local autologin wallets if you require host binding for additional security.
  • When migrating to OKV/OCI KMS, consider a staged approach (OKV|FILE) so you can fall back if needed.
  • Always test wallet/keystore open/close operations and RMAN/Data Pump encryption workflows in lower environments before production.
  • Keep client libraries (liborapkcs.so and OKV client) patched and consistent across RAC nodes.

Last updated: August 29, 2025

Monday, August 25, 2025

ZDLRA - How to manually register databases

Steps to Manually Register a Database and Backup to ZDLRA

Table of Contents


Section 1: User and Policy Setup

Step 1.1 – Create the VPC User Account

racli add db_user --user_name=USER_NAME --user_type=vpc [--insecure]

Notes:

  • If created with --insecure, the VPC password will expire, but can be reused. Password rollover is not supported in this mode.
  • Without --insecure, enable password rollover with the enable_stig option on alter db_user.

Step 1.2 – Create the DB Admin User Account

racli add db_user --user_name=USER_NAME --user_type=admin

Step 1.3 – Create a New Protection Policy (optional)

You can use the default protection policies provided with ZDLRA, but you may want to create custom policies for more control over the protection window and other attributes.  Creating a new policy also allows you the name the protection appropriately to ensure you chose the correct policy.

racli create protection_policy --protection_policy_name=VALUE --storage_location_name=VALUE \
 [--recovery_window_goal=VALUE] [--description=VALUE] [--polling_policy_name=VALUE] \
 [--max_retention_window=VALUE] [--recovery_window_sbt=VALUE] [--unprotected_window=VALUE] \
 [--guaranteed_copy=VALUE] [--allow_backup_deletion=VALUE] [--store_and_forward=VALUE] \
 [--log_compression_algorithm=VALUE] [--autotune_reserved_space=VALUE] \
 [--recovery_window_compliance=VALUE] [--keep_compliance=VALUE] [--comments=VALUE]

Example:

racli create protection_policy --protection_policy_name='test' --storage_location='delta' \
 --recovery_window_goal=10days --unprotected_window=30minutes --autotune_reserved_space=yes \
 --log_compression=low --recovery_window_compliance=1days --allow_backup_deletion=no



Section 2: Database Registration in ZDLRA

Step 2.1 – Add the Database to ZDLRA Metadata

racli add protected_db --db_unique_name={DB_NAME} --protection_policy_name={PROTECTION_POLICY} --reserved_space={VALUE}

Recommended reserved space = ~2x database size.

Step 2.2 – Grant VPC Users Access

racli grant db_access --db_unique_name={DB_NAME} --username={VPCUSER}



Section 3: Wallet and Network Configuration

Step 3.1 – Determine the Wallet Location

  • Check for existing wallets in $ORACLE_BASE/admin/<dbname>/wallet and sqlnet.ora.
  • Use WALLET_ROOT/server_seps (typically under $ORACLE_BASE/admin/{db_name}/wallet).
You should always store the SEPS wallet used by ZDLRA under the WALLET_ROOT location for your database. This will allow the wallet configuration for the ZDLRA to coincide with any other wallets.

NOTES:
  • Setting WALLET_ROOT requires a bounce of the database if it is not already set.  Setting WALLET_ROOT will better prepare the database for managing wallets for real-time redo, TLS, and any encryption keys in the future.
  • Having individual SEPS wallet files for each database, stored outside of $ORACLE_HOME will allow you to have different VPC users, and certificates, providing more flexibility. It also allows you to perform out-of-place upgrades without changing wallet locations.
  • Yes, you can store TDE wallets on ASM/ExaScale and customers sometimes set WALLET_ROOT to ASM/Exascale.  I don't recommend this because many of the additional wallets (SEPS, TLS, OKV) cannot be read from ASM/ExaScale.  I recommend ACFS as a shared file system.

Step 3.2 – Create or Update the Wallet

  • Create the wallet file (if It doesn't exist, or update the existing wallet file):
orapki wallet create -wallet $ORACLE_BASE/{DB_NAME}/wallet/server_seps
mkstore -wrl $ORACLE_BASE/{DB_NAME}/wallet/server_seps -createCredential {connect string} {VPC user} {password}

NOTE: Creating the wallet file with orapki allows you later add TLS certificates
  • Add any Certificates if TLS is configured on the ZDLRA (optional)
orapki wallet add -wallet $ORACLE_BASE/{DB_NAME}/wallet/server_seps -trusted_cert -cert {trusted cert PEM file}
  • Create the auto-login wallet from the passworded wallet:
orapki wallet create -wallet $ORACLE_BASE/{DB_NAME}/wallet/server_seps -auto_login


Copy wallet to all RAC nodes, or ensure it is on a shared mount point.

Step 3.3.A –Create a new sqlnet.ora for your database (Option A).

It is highly recommended to create a separate TNS_ADMIN directory for each database when multiple databases share the same host. This allows you to leverage different wallets for VPC users and TLS certificates.
This also ensures that setting WALLET_LOCATION does not affect any configurations that also use WALLET_LOCATION (i.e. TLS).

I would recommend storing the sqlnet.ora under $ORACLE_BASE/admin/{dbname}/tnsadmin and using TNS_ADMIN within your RMAN session to point to this location.
Within the sqlnet.ora make the following changes.  
SQLNET.WALLET_OVERRIDE=TRUE
WALLET_LOCATION=
 (SOURCE=
   (METHOD=FILE)
   (METHOD_DATA=
     (DIRECTORY={Wallet Location})
   )
 )

Create this directory on each RAC node (if it isn't shared) and copy the sqlnet.ora to all RAC nodes

Step 3.3.B –Update the general sqlnet.ora for your database (Option B).

If this is the only database on your host, you can update the general sqlnet.ora file within $ORACLE_HOME.  Be careful that other DB features, like TLS which may also use WALLET_LOCATION are not affected.

Within the sqlnet.ora make the following changes.  
SQLNET.WALLET_OVERRIDE=TRUE
WALLET_LOCATION=
 (SOURCE=
   (METHOD=FILE)
   (METHOD_DATA=
     (DIRECTORY={Wallet Location})
   )
 )

Copy this file to all nodes if implementing on a RAC cluster.

Step 3.4 – Test SEPS Connection

If using TNS_ADMIN, set it to appropriate location.

Execute the command below using the entry you created in the wallet with mkstore. This will ensure SEPS security is working correctly before continuing.
Check all nodes in a RAC environment.
sqlplus /@<db SCAN listener:PORT/Service:dedicated>




Section 4: Database Registration with RMAN

Step 4.1 – Register the Protected Database

Connect to the local database, and connect to the RMAN catalog using the entry in the SEPS wallet.
Once connect you need to register the database.
RMAN> CONNECT TARGET /  CATALOG /@<db_SCAN:PORT/Service:dedicated>
RMAN> REGISTER DATABASE;



Section 5: Real-Time Redo (Optional)


Step 5.1 – Update Database Parameters

ALTER SYSTEM SET REMOTE_LOGIN_PASSWORDFILE=shared;
ALTER SYSTEM SET LOG_ARCHIVE_FORMAT='log_%d_%t_%s_%r.arc';

Step 5.2 – Set LOG_ARCHIVE_CONFIG 

ALTER SYSTEM SET LOG_ARCHIVE_CONFIG='DG_CONFIG=(<ZDLRA DB>,<DB_UNIQUE_NAME>)' SCOPE=BOTH;

Step 5.3 – Update the WALLET_ROOT in the database (if not set)

ALTER SYSTEM SET WALLET_ROOT='{Oracle home}/admin/{DB name}/wallet' scope=spfile;

It is highly recommended to allow real-time redo use the default wallet located in WALLET_ROOT/server_seps.
If there is no wallet in WALLET_ROOT/server_seps, then the database will use the setting from WALLET_LOCATION in the sqlnet.ora file. The sqlnet.ora can only point to a single WALLET_LOCATION and this can cause confclits.

NOTE: This requires a bounce of the instance to take affect.

Step 5.5 – Create the Redo Transport user  (when using DG)

If you are using Dataguard, you need to ensure you add the VPC user in the database and grant it SYSOPER priveleges.
You also need to ensure that you standby database(s) have a current copy of the Password file.

For multi-tenant environments you need to execute "alter session set "_oracle_script"=true;" prior to creating the users.

Verify that the user exists in the wallet on all systems by querying against the v$password_users view. 

Step 5.6 – Change the Redo Transport User to the VPC user

Change the redo transport user on all environments (primary and standby).
ALTER SYSTEM SET redo_transport_user={VPCUSER};

Step 5.7 – Add ZDLRA as an Archive Log Destination

ALTER SYSTEM SET LOG_ARCHIVE_DEST_<n>=
 'SERVICE=<string from wallet>', 
 VALID_FOR=(ALL_LOGFILES,ALL_ROLES) ASYNC, 
 DB_UNIQUE_NAME='<ZDLRA DB>' SCOPE=BOTH;
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_<n>=ENABLE SCOPE=BOTH;

NOTE: You can also configure DG broker to manage the ZDLRA using the "ADD RECOVERY_APPLIANCE " command.

Step 5.8 – Test Archive Log Configuration

SELECT status, error FROM v$archive_dest WHERE dest_id=<destination>;

Section 6: RMAN Channel and Backup Configuration

Step 6.1 – Add Default Channel Configuration

CONFIGURE CHANNEL DEVICE TYPE 'SBT_TAPE' FORMAT '%d_%U'
 PARMS 'SBT_LIBRARY=libra.so, ENV=(_RA_NO_SSL=TRUE,RA_WALLET="location=file:<ORACLE_BASE>/admin/<db_name>/wallet/server_seps credential_alias=<string from wallet>",RA_FORMAT=TRUE)';
CONFIGURE DEVICE TYPE 'SBT_TAPE' PARALLELISM <n> BACKUP TYPE TO BACKUPSET;
CONFIGURE CONTROLFILE AUTOBACKUP ON;
CONFIGURE BACKUP OPTIMIZATION ON;
CONFIGURE ARCHIVELOG DELETION POLICY TO SHIPPED TO ALL STANDBY;
CONFIGURE DEFAULT DEVICE TYPE TO SBT_TAPE;
NOTE:
  1. Set _RA_NO_SSL to disable sending backups encrypted unless you are implementing TLS already.
  2. Set RA_FORMAT=TRUE to enable space efficient encrypted backups

Step 6.2 – Perform an Explicit Level 0 Backup

RMAN> CONNECT TARGET /
RMAN> CONNECT CATALOG <string from wallet>
RUN {
 BACKUP INCREMENTAL LEVEL 0 DATABASE FILESPERSET 1 SECTION SIZE 64g PLUS ARCHIVELOG NOT BACKED UP;
 FILESPERSET 32}

Step 6.3 – Schedule Regular Incremental Backups

RMAN> CONNECT TARGET /
RMAN> CONNECT CATALOG <string from wallet>
RUN {
 BACKUP INCREMENTAL LEVEL 1 DATABASE FILESPERSET 1 SECTION SIZE 64G PLUS ARCHIVELOG NOT BACKED UP;
 FILESPERSET 32}

Monday, May 12, 2025

Configuring TLS security on ZDLRA

 TLS security is becoming more and more necessary to protect data, and the ZDLRA supports configuring TLS security for both communicating with the RMAN catalog, and for send/receiving backup pieces. In this blog post I will go through the steps to configure TLS security.


These steps are well documented and you can find the documentation below

Configuring Certificate Management 


As a DBA, some of the concepts were new to me, and I wanted to go through the steps in detail so even a DBA (like me) could understand the process.

  1. Determine the DNS entries 

In order to create the certificate request I first need to gather DNS network information about the ZDLRA.

This can be done by utilizing the "racli list san" command.

racli list san

Below is the example output from the documentation showing the DNS entries.


    Created log /opt/oracle.RecoveryAppliance/log/racli_list_san.log
    Thu May  6 16:18:33 2021: Start: List SAN
    CN = zdlra09ingest-scan1.yourdomain.com
    DNS.1 = zdlra09adm01.yourdomain.com
    DNS.2 = zdlra09adm02.yourdomain.com
    DNS.3 = zdlra09ingest-scan1.yourdomain.com
    DNS.4 = zdlra09ingest01-vip.yourdomain.com
    DNS.5 = zdlra09ingest01.yourdomain.com
    DNS.6 = zdlra09ingest02-vip.yourdomain.com
    DNS.7 = zdlra09ingest02.yourdomain.com
    Thu May  6 16:18:39 2021: End: List SAN

This returns the two pieces of information necessary to create the request.

CN (Common Name)

The common name is the name associated with the certificate.  For the ZDLRA this will be the scan listener's fully qualified DNS name.  You will request a certificate registered to this name.



Alternate Names

As you probably know the Protected Database client connects to the ZDLRA using DNS entries other than the Scan Listener.  The scan listener is used to balance traffic and the connection itself is handed to a DNS/IP address assigned to one of the hosts.
Because of this you can see in the example that there are 7 additional DNS entries that are associated with this certificate as alternate names.

 zdlra09adm01.yourdomain.com,zdlra09adm02.yourdomain.com,zdlra09ingest-scan1.yourdomain.com,zdlra09ingest01-vip.yourdomain.com,zdlra09ingest01.yourdomain.com,zdlra09ingest02-vip.yourdomain.com,zdlra09ingest02.yourdomain.com




2. Prepare Certificate Details

The next step is to create the signed certificate and add it to the ZDLRA
There are 2 methods you can use to create the signed certificate, and they are outlined in the documentation

NOTE: You need a signed certificate in order to implement TLS on the ZDLRA. If you are not familiar with the process of requesting a signed certificate you should contact someone from your security team, or talk to someone in your organization who has gone through the process of requesting a server certificate.

A) Certificate Creation Using Third Party Software.

Request Certificate


With this method you request a signed certificate from your company's certificate authority.
Along with the signed certificate the private key is generated by the certificate authority and provided to you.
I used this method because my companies certificate authority process pre-filled in most of the fields required for the request.


In order acquire the certificate I created a request (following my companies process) and entered the two items determined above in the request details along with the company specific information provided to me by the security team.
  • CN name
  • Alternate DNS names
From this, my company's certificate request process (once approved) returned to me a .ZIP file containing two files
  • {CN name}.crt
  • {CN name}.key
I was also given a link to download the Trusted Certificate associated with the certificate authority used by my company.
I stored the Trusted Certificate in a .pem file.
  • {CN name}.pem

NOTE: The PKCS12 command (used in the next step) requires a "Trusted Certificate" as input. When signing my certificate, I was also given a link to the CA Chain certificates, including ROOT and intermediate CA.  As a DBA, I did not immediately understand this concept.  The "Trusted Certificate" contains the ROOT certificate and any intermediate certificates for the 3rd part Certificate Authority that will validate the signed certificate and ensure the certificate is valid and belongs to DNS names provided with the certificate request.
Examples of Trusted Certificate Authorities are DigiCert, Entrust, GlobalSign, Symantec, etc.
You can find more detail on this concept here.

Once completed you can continue to Step #3 with the 3 files

  • {CN Name}.crt - Signed certificate request
  • {CN Name}.key - Private key
  • {CN name}.pem - Trusted Certificate (may be named differently)

B) Create the request and send the request to be signed

With this method, you create the request and generate the key on the ZDLRA.  The request is sent to the Certificate Authority, and signed. You are responsible for creating and storing the private key.

Manually create the certificate request


You begin by creating a ".crt" file with your company's certificate information.
You can see an example in the documentation. 

You need to replace the information in the request file with your companies detail that was provided to you. 

With your company specific detail, you also need to ensure that the request contains the proper
  • CN name from the first step
  • Alternate names from the first step

Upload your certificate request using your company's process

Upload your certificate request to get it signed.
Once signed you will be returned your certificate and you will be given a copy of (or a link to) your company's Trusted Certificate. (see explanation from the first method if this is a new concept).

You should have 2 files
  • {CN name}.crt
  • {CN name}.pem
NOTE: The .pem file for the trusted certificate might be named differently as it is associated with Certificate Authority rather than the Common Name.

Generate a private key

You need to generate a private key to be associated with your signed certificate.  Using the first method, the key was provided to me. With this method you will generate the key yourself. 

The command to generate this key is below, and you may assign a password to the private key.

openssl genrsa -passout pass:<your password> --out /dir/{CN name>.key 2048

Once completed you will have 3 files
  • {CN Name}.crt - Signed certificate request
  • {CN Name}.key - Private key
  • {CN name}.pem - Trusted Certificate

3. Add Certificate to ZDLRA

Sign the user Certificate with the Trusted Certificate

The next step is create a signed user certificate. This step will create a {CN name}.p12 file that can be added to the wallet on the ZDLRA.

NOTE: A PKCS12 file, often also called a PFDX file, is a standard format for storing digital certificates and private keys within a single, encrypted file. It's commonly used to bundle all the necessary cryptographic components for secure communicate, especially for SSL/TLS certificates and code signing. This file combines the signed certificate, the private encryption key, and the Certificate Authority (Trusted Certificate) information into a single file. 

The PKCS12 file is created by executing "openssl pkcs12 -export" and passing in all three files  from above.

openssl pkcs12 -export --in /<DIR>/<NAME>.crt 
--inkey /<DIR>/<NAME2>.key --certfile  /<DIR>/<NAME3>.pem 
--passin pass:<YOURPASSWORD> --passout pass:<YOURPASSWORD>  
--out /<DIR>/<NAME4>.p12

NOTE: The command includes a password. The --passin password is the password for the .key file and the --passout password will be used adding to the .p12 file when created.

Import the user Certificate with the Trusted Certificate

The next step is to take the .PKCS12 file (contained the signed certificate, the private key, and the Certificate Authority) along with the trusted certificate and add them to the wallet on the ZDLRA.

In this step you execute the command below to add both files to the wallet.
 Ensure you give a fully qualified location for the files.

racli add certificate --signed_cert /dir/{CN name}.p12 --trusted_cert=/dir/{CN name}.pem

NOTE: If this is the first time executing this command you will be asked to provide a password for the wallet. The password will be stored on the ZDLRA and you will not be asked for it again. You will also be asked for the password used to create the PKCS12 files in the previous step

Validate both the user Certificate and Trusted Certificate were added

Execute the "racli list certificate command".

This command should return BOTH the "trusted_cert" and "signed_cert" similar to the example in the documentation.

4. Enable the certificate

Once both the trusted_cert and signed_cert have been added to the wallet on the ZDLRA we can configure the ZDLRA to utilize TLS encryption for BOTH TNS (TCPS SQL*net) and backup (HTTPS) traffic.


NOTE: 
  • The ZDLRA will bounce when implementing this step

  • TLS will be the default for sending and receiving backups. ALL channel configurations should contain "_RA_NO_SSL=TRUEin order to ensure they continue sending backups until they are configured with a client wallet.

  • Configuring TLS with "ONLY" will disable non-TLS connections and traffic. Ensure all of your clients are configured for TLS prior to enabling ONLY.

The command to enable TLS is specified in the documentation with the default settings.
When enabling TLS you need to decide if you want TLS to be mandatory, or optional.

You can use the simple command (without any defaults), or you can change the default ports.
If you want to use all of the defaults you can execute the command below

racli alter network --service=ra_server --encrypt=enable | only




4. Validate the TLS configuration

You can validate the configuration in a couple of different ways.

  • Check the health of TLS with "racli run check --check_name=tls_health". This should give you a PASS status
  • As Oracle execute a listener status "lsnrctl status". Below is the output and I can see that TPCS traffic is configured to go over port 2484 and HTTP will go over port 8005 has a certificate configured to ensure it is encrypted.


5. Configuring the Protected DB Client wallet

When using TLS there are 2 wallet entries that need to be referenced when communicating with the ZDLRA
  • Trusted Certificate - This is a new wallet entry and needs to be present so that the client can validate the certificate.
  • VPC credentials (SEPS) - These are the login credentials for the VPC user. If you are using an EZ connect entry, then you would need to change the entry format to use EZConnect Plus (see below) or a TNS alias. If you are currently using a TNS alias you would need to update the tnsnames.ora entry.
These two entries are independent and do not have to be in the same wallet file.

Update current wallet file to include the Trusted Certificate

In order to add certificates to the wallet file, the wallet file must have been created using the orapki command (rather than mkstore).
If the your wallet file was created with mkstore, you will need to recreate it with the orapki command

You will be loading the Trusted Cert into the wallet file used by the ZDLRA to authenticate the VPC user.
More discussion on where the wallet should be located, and how to set the wallet location is covered in my last blog post you can find here.

Assuming the Trusted Certificate is stored in a file names {CN name).pem you would execute the command below also providing the location of the wallet you want to add the certificate to.
Remember it needs to be added to all nodes in a RAC cluster.

orapki wallet add --wallet <WRL> --trusted_cert --cert <dir>/{CN name}.pem

 

Update the SEPS wallet

If you have been using the EZConnect string in your SEPS wallet vs a tnsnames alias you are at a decision point. 

EZConnect - {host}:{port}/{service}

When using TCPS to encrypt communication, you need to indicate that you are using TCPS, and you need to tell EZConnect where to find the wallet file containing the Trusted Certificate for the communication.
Because EZConnect does not support TCPS you need to use EZConnect Plus. EZConnect Plus was introduced with 18g, and is supported with release 19g and above.

EZConnect Plus [Protocol]://{host}:{port}/{service}?wallet_location={wallet location on disk}

When adding the SEPS credential for the VPC user  you need to use the EZConnect Plus format in your wallet for the connection to succeed.

TNSNAMES Alias - As an alternate to using EZConnect, you can use a tnsnames.ora alias. If using an alias, you would add the entry to the tnsnames.ora file that points to the correct port and uses TPCS, and you would ensure the WALLET_LOCATION set in the associated sqlnet.ora file contains the Trusted Certificate.


EZConnect Plus example :

TCPS://ra1-scan1.mycorp.com:2484/radb1?/u1/app/oracle/mydb/wallet/server_seps


6. Configuring the Client to utilize TLS

There are three places where you would change the settings to use TLS

  • RMAN catalog connections (/@)
  • RMAN channel configuration
  • Protected DB real-time redo destination

RMAN catalog connections

In order to connect to the RMAN securely with TLS you need to ensure that your connection is using the correct encrypted port using the TPCS protocol, and you need to ensure that the WALLET_LOCATION in the sqlnet.ora file points to a wallet containing the Trusted Certificate.  You can connect to the catalog using a few different methods
  • Connect directly using the password and using a tnsnames.ora alias.
  • Connect directly using the password and using the EZConnect Plus format specifying TCPS and the location of the Trusted Certificate wallet.
  • Connect using a SEPS entry pointing to a tnsnames alias or the EZConnect Plus formatted string.

RMAN channel configuration

There are a couple of changes to the channel configuration.  The channel configuration will use the two different wallet entries.
  • ra_wallet - This points to the SEPS wallet location and you specify the credential you want to utilize which is in this SEPS wallet.
  • Trusted Certificate location - If you are using the EZConnect Plus format, you would specify the wallet_location which points to a wallet containing the Trusted Certificate. If you are using a tnsnames alias, the WALLET_LOCATION in the sqlnet.ora points to a wallet containing the Trusted Certificate.
NOTE: If your entry is in the EZConnect Plus format, you might have to enclose the credential on double quotes.

Real-time redo configuration


The real-time redo connection will use the two different wallet entries.
  • SEPS wallet - Real-time redo will determine if the parameter WALLET_ROOT is set and if there is a server_seps directory within the WALLET_ROOT. If so, that wallet is used to look up the SEPS connection. If WALLET_ROOT is not set, the connection will use the WALLET_LOCATION set in the sqlnet.ora file pointed to during DB startup.
  • Trusted Certificate location - Real-time redo will always use the WALLET_LOCATION from the sqlnet.ora file to locate the Trusted Certificate.
NOTE: If your entry is in the EZConnect Plus format, you might have to enclose the credential on double quotes.

7. Cloud Control (OEM) considerations

If you are using Cloud Control (OEM) to onboard databases, please follow MOS note

 

Thursday, March 13, 2025

Oracle database wallets for TDE, ZDLRA and External Authentication

 One topic that I spend a lot of time on is "wallets" and the Oracle database. When working with multiple features in the database, there are multiple wallets that are used for different purposes. Along with multiple wallets, there are 2 ways to manage wallets (mkstore and orapki), and there a multiple types of wallets, passworded, auto-login and local.


Wallet Use Cases

Below is a subset of all the places where wallets are used.  

Encryption Wallet : This wallet contains the encryption keys used by DBMS_CRYPTO, TDE and/or RMAN encrypted backups

Strong authentication: Often when external authentication is configured in the database, each database has unique certificates that are stored in a wallet.  In this blog I will refer to this as Strong Authentication. This covers all of DB authentication terms. EUS, OUD, Kerberos, RADIUS, etc.

Certificate authorities and Self-signed certificates : These are used by the database to establish external calls to websites using SSL (HTTPS).  The database can validate the certificate with an external certificate authority, or the self-signed certificate can be stored directly in the wallet.

SEPS authentication : SEPS authentication is used by Oracle clients (including the ZDLRA) to allow scripts to authenticate with a username and password that is stored in an auto-login wallet.  The connection string to the DB is used as the key to retrieve the encrypted connection information.

Real-time redo and TLS certificates for ZDLRA : When the ZDLRA is configured to utilize HTTPS for send/receiving backups, a self-signed certificate is stored in a wallet. This is the same wallet that is used for SEPS authentication of the VPC user.

You can imagine the confusion when you try to combine multiple products that use a wallet, and you want to manage those wallets separately.


Encryption Wallet 

The encryption wallet is the easiest wallet to manage because it is typically isolated from the other wallets that are in use.

The hierarchy Oracle uses to find the location of an encryption wallet is below.  It follows this hierarchy and it will use the first wallet it finds.

WALLET_ROOT : This the recommended location for the encryption wallet as of 19c. The WALLET_ROOT is a spfile/pfile setting that allows you to specify a different location for each database.  It is recommended that the wallet is stored under $ORACLE_BASE/admin/{DB name}/wallet on each node to allow for out of place upgrades.

ENCRYPTION_WALLET_LOCATION in the sqlnet.ora : This was the recommended location prior to 19c.  When multiple databases were sharing the same $ORACLE_HOME (and thus the same sqlnet.ora file), this became confusing. The workaround was to set the location using a variable representation of the DB_NAME.  

$ORACLE_BASE/admin/{DB name}/wallet : This location is the recommended location, But you should set the WALLET_ROOT, or in on an old release (less than 19c)  set the ENCRYPTION_WALLET_LOCATION.  Depending on this location to be the "default" location can cause issues when you start using a wallet for other purposes.  This same location is the default location for any Strong authentication implementations.

Since you should be on 19c, you should be using WALLET_ROOT for encryption wallet location.

NOTE: If you running databases in OCI, it is mandatory to be using WALLET_ROOT in order to utilize the recovery service.

Recommendation :

My recommendation is to always use OKV to manage TDE encryption keys, but I understand that it is a licensable product and it isn't feasible to expect that all customers are using it.

When working in a RAC environment (non-OKV) it becomes critical to have a shared TDE wallet. You may be tempted to store the wallet on ASM, or Exascale. I recommend that you DO NOT.  This makes it much more difficult to backup the wallet, and it makes it more difficult to have a shared SEPS wallet if backing up to a ZDLRA.

Store the TDE encryption wallet on ACFS, and point the WALLET_ROOT to the ACFS location mounted on each node.  When backing up the encryption wallet, copy ONLY the passworded wallet ewallet.p12 to another location to be backed up outside of the DB backups.

Strong authentication wallets

This wallet typically causes the most headaches for users.  The hierarchy Oracle uses to find the location of a Strong authentication wallet is below.  Like the encryption wallet, it follows this hierarchy and it will use the first wallet it finds.

WALLET_LOCATION in the sqlnet.ora : When multiple databases are sharing the same $ORACLE_HOME (and thus the same sqlnet.ora file), this becomes confusing. The workaround was to set the location using a variable representation of the DB_NAME as part of location string.  

$ORACLE_BASE/admin/{DB name}/wallet : This is the location that most customers place their Strong authentication wallets in since it is isolated to the Database associated with the wallet

NOTE: The issue arises when customers use a product/feature that updates the WALLET_LOCATION in the sqlnet.ora, which breaks authentication since the WALLET_LOCATION is checked first.

Use separate wallets, and leverage the TNS_ADMIN variable to point to different sqlnet.ora files and sharing the same $ORACLE_HOME.


Certificate authorities and Self-signed certificates 

The most common use case for certificate authorities is when  utilizing the DBMS_CLOUD family of products.  Products such as DBMS_CLOUD call out object storage and require a secure (HTTPS) connection. In order to open a secure connection the client needs to authenticate the certificate as  valid certificate, or use a self-signed certificate that is stored in the wallet.
This same issue is true when using DBMS_CLOUD_AI and DBMS_VECTOR_CHAIN which makes calls to external LLMs that often require a secure connection.

This wallet is controlled by setting the database property "SSL_WALLET". 
For simplicity I would recommend creating a central wallet that can be used by ALL databases on the host and is stored within $ORACLE_BASE. My favorite location is $ORACLE_BASE/cert_wallet which identifies it as containing certificate authorities.

I do not recommend adding certificates to the Strong authentication wallet, or the SEPS wallet (discussed next) as it becomes more difficult to mange multiple wallets to make updates.

SEPS authentication 

The next wallet I want to discuss is the SEPS authentication wallet. This wallet is used by Oracle clients (sqlplus, RMAN, and ZDLRA) to store the credentials for a database.

The connection string (either an ezconnect string or a tnsnames.ora entry) is added to the wallet, along with the username and password that will be used when connecting using this entry.  

The location of the wallet is stored in the sqlnet.ora file, and there are 2 parameters associated with this setting.

SQLNET.WALLET_OVERRIDE=true

WALLET_LOCATION={location on disk}

NOTE: Setting the WALLET_OVERRIDE to true disables any OPS$ usage and allows the usage of SEPS wallets for authentication. 

Setting the WALLET_LOCATION on a host that supports databases utilizing Strong authentication often causes issues if it does not specify a separate location each database using variable.  The sqlnet.ora file is only read at startup, so changes to the WALLET_LOCATION might not become apparent to after a database bounce.

Recommendation :

If you are using multiple products that use a wallet AND share the same Oracle Home, I recommend using the TNS_ADMIN variable to mange which wallet to use in scripts. 

As wallets become more common for security, separating out the use cases, if possible, will make it easier to manage and rotate authentication information.  With TNS_ADMIN you can point to a directory containing a sqlnet.ora file specific to the database, and leave the original sqlnet.ora file without a WALLET_LOCATION entry. 

Real-time redo and TLS certificates for ZDLRA 

Prior to the 19.18 DB release, configuring real-time redo for databases sending backups to the ZDLRA required a bounce of the database (to refresh the DBs copy of the sqlnet.ora), and it required the WALLET_LOCATION to be set in the sqlnet.ora.

This changed with 19.18, and I recommend you use the new location.

   The hierarchy Oracle uses to find the location of the wallet real-time wallet is below.  Like the encryption wallet, it follows this hierarchy and it will use the first wallet it finds.

WALLET_ROOT/server_seps : If the variable WALLET_ROOT is set, and a wallet exists in the server_seps subdirectory, that wallet is used by the real-time redo.  This is a HUGE improvement as it doesn't require a bounce, and it makes it much easier to avoid issues with Strong authentication, and databases that share the same $ORACLE_HOME.

NOTE: WALLET_ROOT was added in 18c. If you are still using 12.x, you need to use the sqlnet.ora.

WALLET_LOCATION in the sqlnet.ora : When multiple databases are sharing the same $ORACLE_HOME (and thus the same sqlnet.ora file), this becomes confusing. The workaround was to set the location using a variable representation of the DB_NAME.  This is what I mentioned for Strong authentication.

Recommendation :

When backing up to a ZDLRA, especially with real-time redo you should be using a SEPS wallet that is stored under WALLET_ROOT.  
Since the ZDLRA supports encrypted backups, even if you don't own ASO, I recommend creating an encryption wallet with keys to encrypt your backups.  This is much more secure, and this ability is included in the ZDLRA license.
The steps I would recommend for any customer using the ZDLRA are
  • If you don't have an encryption wallet (because you don't own ASO), create one and set the  encryption keys for both the CDB and PDB (if it is multi-tenant). This does require a DB bounce to set the WALLET_ROOT, but this will allow you to have RMAN encrypted backups.
  • In a RAC environment store the encryption wallet on ACFS and point WALLET_ROOT to the ACFS location.
  • Store the SEPS wallet containing the VPC user credentials for the ZDLRA in the WALLET_ROOT/server_seps directory.  This will automatically be used by real-time redo starting with 19.18.
  • Ensure your channel configuration for RMAN points to the WALLET_ROOT/server_seps directory on ACFS for the wallet.
  • In your RMAN scripts ensure that you are pointing to a TNS_ADMIN location that has a sqlnet.ora file pointing to the WALLET_ROOT/server_seps location for WALLET_LOCATION or ensure that OEM has the correct SEPS wallet location set. 

MKSTORE vs ORAPKI

orapki 

The orapki utility manages public key infrastructure (PKI) elements, such as wallets and certificate revocation lists, from the command line.  This is the recommended method of managing wallet files.

You can use the orapki command-line utility to perform the following tasks:

  • Creating and viewing signed certificates for testing purposes

  • Manage Oracle wallets (except for Transparent Data Encryption keystores):

    • Create and display Oracle wallets

    • Add and remove certificate requests

    • Add and remove certificates

    • Add and remove trusted certificates

  • Manage certificate revocation lists (CRLs):

    • Renaming CRLs with a hash value for certificate validation

    • Uploading, listing, viewing, and deleting CRLs in Oracle Internet Directory

NOTE: The above is directly from the 19c documentation.  You can see that orapki is used to manage certificates with no mention of managing SEPS credentials.

mkstore

The first thing you will notice with mkstore, is that the mkstore command should be considered deprecated.  Upon digging into this some more, I found a comment from Russ Lowenthal (VP of Database Security products) who mentions that the SEPS credential wallet management will not be added to orapki until AFTER 23c.

NOTE: Even though it is considered deprecated, mkstore is the only way to manage SEPS credentials from the command line, and should only be used to manage SEPS credentials.

Administer key management

I added the "Administer Key Management" command to this section because it can also be used to manage both secrets and SEPS credentials.
The following options are available and can be found in the documentation.
  • add/update/delete Secret '{secret name}' for client '{client identifier}' --> secret
  • add/update/delete secret '{secret name}' for client '{client identifier}' to {local optionally} auto_login keystore {keystore location}  --> SEPS

How to manage wallets


Wallet Type How to manage contents
Encryption Keys Utilize the "ADMINISTER KEY MANAGEMENT" statement from the database
External user authentication Use orapki to manage certificates, or the OWM tool which uses orapki
Certificate authorities and Self-signed certificate Use orapki to manage certificates
SEPS authentication Use mkstore for now, as orapki does not support SEPS
Real-time redo for ZDLRA Use mkstore for now, as orapki does not support SEPS
TLS certificates for ZDLRA Use orapki to manage the certificates


Wallet names and type

When you look in the wallet directory you would see one, or both of these wallets.

cwallet.sso - This is an auto-login wallet.  With an auto-login wallet you can access the contents without having to provide a password. In almost all cases, you will have this type of wallet entry.

ewallet.p12 - This is the passworded wallet. In order add/change/delete entries you need to specify a password when making those changes.  

NOTE:

  • If only the cwallet.sso exist, you can assume it is an auto-login only wallet.
  • If both wallets exist, you can access the contents without a password, but any add/change/deletion commands will require a password and update both the passworded wallet and the auto-login wallet.
  • If only the ewallet.p12 exists, to access the contents of the wallet  you must provide a password.


Standard Password Protected wallet

This is the least common wallet type (at least alone without an auto-login wallet), since it requires a password to access the contents. This is most commonly used to protect encryption keys for databases since it will require entering password to open the wallet when the database is started.   In this configuration you create a new wallet using orapki or Administore key store and provide a password.  In this case there will only be a single wallet file, ewallet.p12.

NOTE: You cannot create a non auto-login wallet with mkstore 

  • orapki wallet create -wallet {wallet location}
  • administer key management create keystore {wallet location}

Auto-login only wallets

You can create an auto-login wallet using e mkstore,  orapki, or the administer key manage command.  The idea of an auto-login wallet, is that you can add entries to this wallet without needing a password. You can also list the entries in the wallet using either CLI tool. In this configuration there is only a cwallet.sso file in the wallet directory

Auto-login wallets

This is the most common configuration that you will see.  There is both a passworded wallet, and an auto-login wallet. With both wallets, it requires a password to make changes, but no password is required to open the wallet and use it.  The two wallets are synchronized when you make changes.

There are two ways to create auto-login wallets.

    1. Create a non auto-login wallet using orapki or within the database, then create an auto-login wallet from the non auto-login wallet.

  • orapki wallet create -wallet {wallet location}
    • orapki wallet create -wallet {wallet location} -auto_login  OR
    • mkstore -wrl {wallet location} -createSSO
  • administer keystore create keystore {wallet location}
    • administer keystore create auto_login keystore from keystore {wallet location}
     2. Create an auto-login wallet  and non auto-login wallet together
  •     orapki wallet create -wallet {wallet location} -auto_login

Local Auto-login wallets

Local auto-login wallets work the same way as the auto-login wallet, EXCEPT, the wallet is encrypted in a way that makes it only usable on the host it was created.  This limits any security risks if the wallet is copied (or restored) onto a different host.

When creating a local auto-login wallet you would use 
  • mkstore -wrl {wallet location} -createLSSO
  • orapki wallet create -wallet {wallet location} auto_login_local
  • administer keystore create local auto_login keystore from keystore {wallet location}

NOTE:

  • Local auto-login wallets are much more secure as they can only be used on the host  where the wallet was created. 
  • When backing up wallets, this includes Encryption wallets, only backup the ewallet.p12 file.  This ensures that a password is required to utilize the wallet.
NOTE: When only backing up the ewallet.p12, be sure you know the password so that you can recreate the auto-login wallet.
  • ALWAYS review the permissions on your wallet files, especially the auto-login wallet files containing credentials.  Any user that can access the auto-login wallet file can utilize the credentials contained within the wallet.

ASM/Exascale for Encryption wallets

You probably noticed that I am not a fan of ASM/Exascale as an encryption wallet location, even though ASM in mentioned in the documentation. 
I will add more to this section, but this is my reasoning for not preferring ASM.
  1. It's easy to forget backing up the wallet file.  Having it on ASM requires copying it back to the file system to get backed up.  It is very easy to forget about this, rotate the keys, and not have a wallet backup.
  2. WALLET_ROOT is becoming the starting point for different wallet files, not just encryption wallets.  ZDLRA is the first example. When WALLET_ROOT points to ASM or Exascale, then the same wallet cannot be used by many tools because they only expect wallets on the file system.
Shared wallets make sense, that's why I prefer ACFS, or a mounted filesystem for WALLET_ROOT.


Summary 

Starting with DB 19.18, you have the ability to store individual credential wallets for real-time redo transportation when leveraging ZDLRA for backups.  You can also use the TNS_ADMIN variable to set a different location when using SEPS authentication.  It is now possible to manage multiple wallets separately without having conflicts between products and features.


MY RECOMMENDATIONS (summary):

  • Use Oracle Key Vault (OKV) for encryption keys.  OKV is an Oracle product specifically designed to securely store and manage encryption keys, and much more.  OKV has tight integration with the Oracle Database.  If you are not using OKV, at least store Encryption Keys on ACFS as the shared location (not ASM or Exascale).
  • Use WALLET_ROOT if you are on 18c+.  This will continue to be used products to help separate wallet locations for different uses cases.  The ZDLRA is the first of many products to use the hierarchy for wallet files. 
  • Backup only the ewallet.p12.  This is the passworded wallet and with the password it can be used to recreate the auto-login wallet. This is especially critical for Encryption keys.

BUT - Make sure you know the password. Without the password, you can't recreate the auto-login wallet.

  • Lock down permissions on wallet files to only the account that needs access, especially the cwallet.sso file (auto-login).
  • Whenever possible create local auto-login wallets that can only be used on the source host where the wallet was created. This wallet, however,  cannot be shared across nodes.
  • Keep your SEPS wallets separate by utilizing the TNS_ADMIN variable and having a custom sqlnet.ora file.
  • If you are backing up to a ZDLRA create an encryption wallet with keys, and set the WALLET_ROOT location.  Put the SEPS wallet for ZDLRA under WALLET_ROOT/server_seps.  This wallet can also be used for the TPCS certificate if you configure HTTPS.   Keep this configuration separate to avoid conflicts with other products.


Wednesday, March 5, 2025

Oracle DB release 23.7 includes "Select AI" with the DBMS_CLOUD_AI package

 The latest release of Oracle DB23ai (23.7) now includes the promised packages for DBMS_CLOUD.  

I'm not talking about the ADB release, this is the general 23.7 DB release, and it even includes Select AI !!



You can find the documentation for how to install DBMS_CLOUD here.  This is updated documentation that supersedes the MOS note 2748362.1 - How To Setup And Use DBMS_CLOUD Package.


What's Included in 23.7

The Following packages are included in 23.7

DBMS_CLOUD - The SQL to install this package has been included with the DB release since 19.9.  More procedures have been added over time to provide more functionality with object storage.

DBMS_CLOUD_AI - This is the most interesting part of the release (at least to me).  This package is used as the basis for Select AI.

DBMS_CLOUD_NOTIFICATION -  This package allows you to send messages, or the output of a query to an e-mail or to Slack.

DBMS_CLOUD_PIPELINE -  This package allows you to create a data pipeline for loading and exporting data in the cloud.  This is mainly used to interact with data in object storage on a scheduled basis.

DBMS_CLOUD_REPO -  This package allows you to interact with hosted code repositories from the oracle Database. Repositories like Github are supported.


Where to start

The following are some great places to learn more about how to use the packages.

Videos:

Documentation:


Installing in your Database

I started by going through the install and prerequisites found here.
  1. Install the DBMS_CLOUD packages in a 23.7 CDB using the instructions in the 23.7 Documentation (20.2)
  2. Create the SSL wallet with certificates (20.3)
  3. Configure your environment with the new wallet (20.4).
NOTE: If you are using SEPS (ZDLRA uses SEPS), or other user authentication this is the same wallet that other authentication methods use).

    4. Configure the ACL list to allow DB calls to the LLM that you are going to be using (20.5)

    5. Verify the configuration for DBMS_CLOUD (20.6)

    6. Configure users or roles to use DBMS_CLOUD. (20.7).  In my case I granted the access to "SH".

    7. Create the credential for the LLM you are using in your PDB

    8. Create the Profile which identifies the tables that you want to use in your PDB

Example


I installed the Sample sales schema into my PDB (SH user) and followed the instructions in the documentation found here.


Below is the output of one of the queries that I ran using "Select AI" once I went through these steps to install it with the sample SH schema.

SQL> select ai tell me how many customers are in each country;

COUNTRY_NAME                             CUSTOMER_COUNT
---------------------------------------- --------------
Italy                                              7780
Singapore                                           597
Brazil                                              832
United Kingdom                                     7557
Australia                                           831
Japan                                               624
Canada                                             2010
Argentina                                           403
Poland                                              708
China                                               712
Germany                                            8173
United States of America                          18520
France                                             3833
Spain                                              2039
New Zealand                                         244
Denmark                                             383
South Africa                                         88
Saudi Arabia                                         75
Turkey                                               91


I am just getting starting determining how to best use this feature, and this should be enough to get your started.