Thursday, November 7, 2024

One-way TLS ODB Client/Server With CA-signed Certificates In OS Truststore

In recent months, I've helped many customers understand there options for centralizing Oracle Database authentication.  One of those options requires Transport Layer Security (TLS) connection between the database client and database server in order to securely pass an access token to the database server.  When customers want to evaluate this solution, one of their challenges is how to setup TLS between the database and server for a proof of concept or internal validation.  There are three approaches that customers can take for setting up TLS between client and server:

1. Self-signed private certs with wallets - For demonstrations and proofs of concept
2. Self-signed private certs with host trust store - Next step toward production
3. Publicly signed certs - For production

The focus of this blog post is on the third of the three.

Here's the streamlined workflow that I use for setting up one-way TLS between Oracle Database client and server where the client wallet is distributed to Oracle Database clients. This comes from the Oracle Database security guide at https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/configuring-transport-layer-security-encryption.html#GUID-03F216A2-76E0-47C9-9751-6F2D39BD75A1

As a side note, if you are not familiar with the WALLET_ROOT database parameter, please familiarize yourself with it at https://docs.oracle.com/en/database/oracle/oracle-database/23/refrn/WALLET_ROOT.html because it plays a large role in several security configuration options of the Oracle database including configuring TLS.

When specifying the SSL_CIPHER_SUITES in the database listener.ora and client tnsnames.ora, you will want to select the strongest cipher suites from the desired SSL_Version (1.3 or 1.2) that you want to support that all of the database clients support.  In this example, we will use version 1.2 and cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.

The full list of supported SSL_VERSION and SSL_CIPHER_SUITES values per database version are available here:



Step 1: Generate, sign and load database server certificate by public certificate authority

1.1 Setup the database server environment variables and make wallet directory

ssh opc@hrdb.example.com
export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
PATH=$ORACLE_HOME/bin:$PATH
mkdir -p $WALLET_ROOT/tls

1.2 Create autologin wallet 

orapki wallet create -wallet $WALLET_ROOT/tls -pwd Oracle123 -auto_login


1.3 Download and load the trusted root certificate chain (sf_bundle-g2-g1.crt) from the certificate authority and load into the wallet 

orapki wallet add -wallet $WALLET_ROOT/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/sf_bundle-g2-g1.crt


1.4 Create a private key for the database server using the fully qualified hostname for the distinguished name (DN). 

orapki wallet add -wallet $WALLET_ROOT/tls -pwd Oracle123 -keysize 2048 -dn CN=hrdb.example.com


1.5 Export a certificate request to be signed by the certificate authority 

orapki wallet export -wallet $WALLET_ROOT/tls -pwd Oracle123 -dn CN=hrdb.dbauthdemo.com -request hrdb.csr


1.6 Sign the certificate through the certificate authority and download the signed certificate


1.7 Load the signed certificate (31e303219bbcf898.crt) into the wallet

orapki wallet add -wallet $WALLET_ROOT/tls -pwd Oracle123 -user_cert -cert 31e303219bbcf898.crt


1.8 Show the contents of the wallet

orapki wallet display -complete  -wallet $WALLET_ROOT/tls -pwd Oracle123


Step 2: Create client wallet for 19c database clients that don't support WALLET_LOCATION=SYSTEM

2.1 Create client wallet
The purpose of the client wallet is to create a wallet that has the signing certificate authority's certificate (or certificate chain).

mkdir -p $WALLET_ROOT/client_wallet/tls
orapki wallet create -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/sf_bundle-g2-g1.crt


2.1 Copy client wallet to 19c database client hosts

rsync -Have ssh $WALLET_ROOT/client_wallet/tls/. opc@clientdb:/u01/app/oracle/tls 



Step 3: Configure 19c database server

3.1 Setup the database server environment variables on the hrdb host.

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export ORACLE_SID="hrdb"
export TNS_ADMIN="$ORACLE_HOME/network/admin"

PATH=$ORACLE_HOME/bin:$PATH


3.2 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


3.3 Configure listener.ora

cat $ORACLE_HOME/network/admin/listener.ora
SSL_CLIENT_AUTHENTICATION = FALSE

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
      (SECURITY=(WALLET_LOCATION=/u01/app/oracle/19c/wallet_root/tls))
    )
  )

ADR_BASE_LISTENER = /u01/app/oracle/19c

3.4 Set the wallet_root parameter and restart the database and listener

sqlplus / as sysdba
SQL> alter system set wallet_root='/u01/app/oracle/19c/wallet_root' scope=spfile;
SQL> shutdown immediate;
SQL> quit;
lsnrctl stop
lsnrctl stop
sqlplus / as sysdba
SQL> startup;
SQL> 
alter pluggable database all open;
SQL> alter system register;
SQL> quit;

3.5 Configure host firewall of database server to allow inboud (a.k.a. ingress) connections to non-secure port (1521) and secure port (2848)

sudo firewall-cmd --permanent --zone=public --add-port=1521/tcp
sudo firewall-cmd --permanent --zone=public --add-port=2484/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all


Step 4: Configure 19c database client

Instructions for downloading 19c database client at https://www.braddiggs.com/2024/11/setup-production-oracle-19c-database.html

4.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


4.2 Extract the 19c database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/
V982065-01.zip


4.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to SYSTEM to use the operating system trust store, which includes all major public certificate authorities.  Note that the HOST value should be the fully qualified hostname of the database server.

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


4.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
WALLET_LOCATION=
  (SOURCE=  
    (METHOD=file)    
    (METHOD_DATA=    
      (DIRECTORY=/u01/app/oracle/tls)
    )
  )

SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES=(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


Step 5: Test 19c client connections to the database

5.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


5.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


5.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


Step 6: Configure 23ai database client

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

6.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


6.2 Extract the 23ai database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/
V1044258-01.zip


6.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to SYSTEM

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


6.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


Step 7: Test 23ai client connections to the database

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

7.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


7.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


7.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


For troubleshooting, see my blog post on Troubleshooting Oracle One-way TLS Connection Errors.





Wednesday, November 6, 2024

One-way TLS ODB Client/Server With Self-signed Certificates In OS Truststore

In recent months, I've helped many customers understand there options for centralizing Oracle Database authentication.  One of those options requires Transport Layer Security (TLS) connection between the database client and database server in order to securely pass an access token to the database server.  When customers want to evaluate this solution, one of their challenges is how to setup TLS between the database and server for a proof of concept or internal validation.  There are three approaches that customers can take for setting up TLS between client and server:

1. Self-signed private certs with wallets - For demonstrations and proofs of concept
2. Self-signed private certs with host trust store - Next step toward production
3. Publicly signed certs - For production

The focus of this blog post is on the second of the three.

Here's the streamlined workflow that I use for setting up one-way TLS between Oracle Database client and server where the client wallet is distributed to Oracle Database clients. This comes from the Oracle Database security guide at https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/configuring-transport-layer-security-encryption.html#GUID-03F216A2-76E0-47C9-9751-6F2D39BD75A1

As a side note, if you are not familiar with the WALLET_ROOT database parameter, please familiarize yourself with it at https://docs.oracle.com/en/database/oracle/oracle-database/23/refrn/WALLET_ROOT.html because it plays a large role in several security configuration options of the Oracle database including configuring TLS.

When specifying the SSL_CIPHER_SUITES in the database listener.ora and client tnsnames.ora, you will want to select the strongest cipher suites from the desired SSL_Version (1.3 or 1.2) that you want to support that all of the database clients support.  In this example, we will use version 1.2 and cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.

The full list of supported SSL_VERSION and SSL_CIPHER_SUITES values per database version are available here:



Step 1: Setup Certificate Authority Server
In order to simplify this setup for a large number of databases, we first setup a private certificate authority (CA) on which we will create and sign individual database certificates.  This setup presumes that the Oracle Database software is installed on the host where orapki will be run.

1.1 Setup the environment variables on the dbca host.

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
PATH=$ORACLE_HOME/bin:$PATH


1.2 Create the root certificate authority wallet with a arbitrary distinguished name that makes it clear that it is the certificate authority.  For example, DN=root_ca.

mkdir -p $WALLET_ROOT/rootca_wallet/tls
orapki wallet create -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -dn CN=root_ca -keysize 2048 -sign_alg sha256 -self_signed -validity 3500
orapki wallet export -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -dn CN=root_ca -cert $WALLET_ROOT/
rootca_wallet/root_wallet.crt

Step 2: Generate and sign DB and client certificates

2.1 Create database server wallet and sign database server (hrdb) certificate.  Note that the distinguished name of the database can be completely arbitrary.  In this example (CN=db_19c_hr), I encapsulated the role (db), version (19c) and application (hr). It could have just as easily been CN=db_hr.

mkdir -p $WALLET_ROOT/hrdb_wallet/tls
orapki wallet create  -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/rootca_wallet/root_wallet.crt
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -keysize 2048 -dn CN=db_19c_hr
orapki wallet export -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -dn CN=db_19c_hr -request $WALLET_ROOT/hrdb_wallet/db_19c_hr.csr
orapki cert create -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -request $WALLET_ROOT/hrdb_wallet/db_19c_hr.csr -cert $WALLET_ROOT/hrdb_wallet/db_19c_hr.crt -validity 3500 -sign_alg sha256
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -user_cert -cert $WALLET_ROOT/hrdb_wallet/db_19c_hr.crt

2.2 Create client wallet and load with certificate authority root certificate.  The purpose of the client wallet is to create a wallet that has the signing certificate authority's certificate (or certificate chain).

mkdir -p $WALLET_ROOT/client_wallet/tls
orapki wallet create -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/rootca_wallet/root_wallet.crt


Step 3: Copy wallets to respective destinations

3.1 Copy hrdb_wallet to host of hrdb database server

export ORACLE_BASE="/u01/app/oracle/19c"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
rsync -Have ssh $WALLET_ROOT/hrdb_wallet/tls/. opc@hrdb:$WALLET_ROOT/tls

3.2  Lookup PDB GUIDs and copy hrdb wallet to each PDB GUID

ssh opc@hrdb
export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
export TNS_ADMIN="$ORACLE_HOME/network/admin"
export ORACLE_SID="hrdb"
PATH=$ORACLE_HOME/bin:$PATH
$ORACLE_HOME/bin/sqlplus / as sysdba
SQL> select name,guid from v$containers;
SQL> quit;

for pdbguid in 262D482FB47D7B8BE0638400000A1737
do
  mkdir -p $WALLET_ROOT/$pdbguid/tls
  cp $WALLET_ROOT/tls/ewallet.p12 $WALLET_ROOT/$pdbguid/tls
  cp $WALLET_ROOT/tls/cwallet.sso $WALLET_ROOT/$pdbguid/tls
done

3.3 Copy client_wallet.crt certificate to host of each database thick client

rsync -Have ssh $WALLET_ROOT/rootca_wallet/root_wallet.crt opc@clientdb:/u01/app/oracle/root_wallet.crt 


Step 4: Configure 19c database server

4.1 Setup the database server environment variables on the hrdb host.

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export ORACLE_SID="hrdb"
export TNS_ADMIN="$ORACLE_HOME/network/admin"

PATH=$ORACLE_HOME/bin:$PATH


4.2 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


4.3 Configure listener 

cat $ORACLE_HOME/network/admin/listener.ora
SSL_CLIENT_AUTHENTICATION = FALSE

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
      (SECURITY=(WALLET_LOCATION=/u01/app/oracle/19c/wallet_root/tls))
    )
  )

ADR_BASE_LISTENER = /u01/app/oracle/19c

4.4 Set the wallet_root parameter and restart the database and listener

sqlplus / as sysdba
SQL> alter system set wallet_root='/u01/app/oracle/19c/wallet_root' scope=spfile;
SQL> shutdown immediate;
SQL> quit;
lsnrctl stop
lsnrctl stop
sqlplus / as sysdba
SQL> startup;
SQL> 
alter pluggable database all open;
SQL> alter system register;
SQL> quit;

4.5 Configure host firewall of database server to allow inboud (a.k.a. ingress) connections to non-secure port (1521) and secure port (2848)

sudo firewall-cmd --permanent --zone=public --add-port=1521/tcp
sudo firewall-cmd --permanent --zone=public --add-port=2484/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all


Step 5: Configure 19c database client

Instructions for downloading 19c database client at https://www.braddiggs.com/2024/11/setup-production-oracle-19c-database.html

5.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
PATH=$ORACLE_HOME/bin:$PATH


5.2 Extract the 19c database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/
V982065-01.zip


5.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to SYSTEM

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


5.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
WALLET_LOCATION=
  (SOURCE=  
    (METHOD=file)    
    (METHOD_DATA=    
      (DIRECTORY=/u01/app/oracle/tls)
    )
  )

SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES=(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)

5.5 Append the root_wallet.crt certificate to the host wallet

cat /u01/app/oracle/root_wallet.crt | sudo tee -a /etc/pki/tls/cert.pem
rm 
/u01/app/oracle/root_wallet.crt


Step 6: Test 19c client connections to the database

6.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


6.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


6.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


Step 7: Configure 23ai database client

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

7.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
PATH=$ORACLE_HOME/bin:$PATH


7.2 Extract the 23ai database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/
V1044258-01.zip


7.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to SYSTEM

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=SYSTEM))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


7.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)

7.5 Append the root_wallet.crt certificate to the host wallet

cat /u01/app/oracle/root_wallet.crt | sudo tee -a /etc/pki/tls/cert.pem
rm 
/u01/app/oracle/root_wallet.crt

Step 8: Test 23ai client connections to the database

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

8.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


8.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


8.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


For troubleshooting, see my blog post on Troubleshooting Oracle One-way TLS Connection Errors.





One-way TLS ODB Client/Server With Self-signed Certificates In Wallets

In recent months, I've helped many customers understand there options for centralizing Oracle Database authentication.  One of those options requires Transport Layer Security (TLS) connection between the database client and database server in order to securely pass an access token to the database server.  When customers want to evaluate this solution, one of their challenges is how to setup TLS between the database and server for a proof of concept or internal validation.  There are three approaches that customers can take for setting up TLS between client and server:

1. Self-signed private certs with wallets - For demonstrations and proofs of concept
2. Self-signed private certs with host trust store - Next step toward production
3. Publicly signed certs - For production

The focus of this blog post is on the first of the three.

Here's the streamlined workflow that I use for setting up one-way TLS between Oracle Database client and server where the client wallet is distributed to Oracle Database clients. This comes from the Oracle Database security guide at https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/configuring-transport-layer-security-encryption.html#GUID-03F216A2-76E0-47C9-9751-6F2D39BD75A1

As a side note, if you are not familiar with the WALLET_ROOT database parameter, please familiarize yourself with it at https://docs.oracle.com/en/database/oracle/oracle-database/23/refrn/WALLET_ROOT.html because it plays a large role in several security configuration options of the Oracle database including configuring TLS.

When specifying the SSL_CIPHER_SUITES in the database listener.ora and client tnsnames.ora, you will want to select the strongest cipher suites from the desired SSL_Version (1.3 or 1.2) that you want to support that all of the database clients support.  In this example, we will use version 1.2 and cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.

The full list of supported SSL_VERSION and SSL_CIPHER_SUITES values per database version are available here:



Step 1: Setup Certificate Authority Server
In order to simplify this setup for a large number of databases, we first setup a private certificate authority (CA) on which we will create and sign individual database certificates.  This setup presumes that the Oracle Database software is installed on the host where orapki will be run.

1.1 Setup the environment variables on the dbca host.

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
PATH=$ORACLE_HOME/bin:$PATH

1.2 Create the root certificate authority wallet with a arbitrary distinguished name that makes it clear that it is the certificate authority.  For example, DN=root_ca.

mkdir -p $WALLET_ROOT/rootca_wallet/tls
orapki wallet create -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -dn CN=root_ca -keysize 2048 -sign_alg sha256 -self_signed -validity 3500
orapki wallet export -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -dn CN=root_ca -cert $WALLET_ROOT/
rootca_wallet/root_wallet.crt

Step 2: Generate and sign DB and client certificates

2.1 Create database server wallet and sign database server (hrdb) certificate.  Note that the distinguished name of the database can be completely arbitrary.  In this example (CN=db_19c_hr), I encapsulated the role (db), version (19c) and application (hr). It could have just as easily been CN=db_hr.

mkdir -p $WALLET_ROOT/hrdb_wallet/tls
orapki wallet create  -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/rootca_wallet/root_wallet.crt
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -keysize 2048 -dn CN=db_19c_hr
orapki wallet export -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -dn CN=db_19c_hr -request $WALLET_ROOT/hrdb_wallet/db_19c_hr.csr
orapki cert create -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -request $WALLET_ROOT/hrdb_wallet/db_19c_hr.csr -cert $WALLET_ROOT/hrdb_wallet/db_19c_hr.crt -validity 3500 -sign_alg sha256
orapki wallet add -wallet $WALLET_ROOT/hrdb_wallet/tls -pwd Oracle123 -user_cert -cert $WALLET_ROOT/hrdb_wallet/db_19c_hr.crt

2.2 Create client wallet and load with certificate authority root certificate.  The purpose of the client wallet is to create a wallet that has the signing certificate authority's certificate (or certificate chain).

mkdir -p $WALLET_ROOT/client_wallet/tls
orapki wallet create -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -auto_login
orapki wallet add -wallet $WALLET_ROOT/client_wallet/tls -pwd Oracle123 -trusted_cert -cert $WALLET_ROOT/rootca_wallet/root_wallet.crt


Step 3: Copy wallets to respective destinations

3.1 Copy hrdb_wallet to host of hrdb database server

export ORACLE_BASE="/u01/app/oracle/19c"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
rsync -Have ssh $WALLET_ROOT/hrdb_wallet/tls/. opc@hrdb:$WALLET_ROOT/tls

3.2  Lookup PDB GUIDs and copy hrdb wallet to each PDB GUID

ssh opc@hrdb
export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/dbhome_1"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
export TNS_ADMIN="$ORACLE_HOME/network/admin"
export ORACLE_SID="hrdb"
PATH=$ORACLE_HOME/bin:$PATH
$ORACLE_HOME/bin/sqlplus / as sysdba
SQL> select name,guid from v$containers;
SQL> quit;

for pdbguid in 262D482FB47D7B8BE0638400000A1737
do
  mkdir -p $WALLET_ROOT/$pdbguid/tls
  cp $WALLET_ROOT/tls/ewallet.p12 $WALLET_ROOT/$pdbguid/tls
  cp $WALLET_ROOT/tls/cwallet.sso $WALLET_ROOT/$pdbguid/tls
done

3.3 Copy client_wallet to host of each database thick client

export ORACLE_BASE="/u01/app/oracle/19c"
export WALLET_ROOT="$ORACLE_BASE/wallet_root"
rsync -Have ssh $WALLET_ROOT/client_wallet/tls/. opc@clientdb:/u01/app/oracle/tls 


Step 4: Configure 19c database server

4.1 Setup the database server environment variables on the hrdb host.

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="/u01/app/oracle/19c/dbhome_1"
export ORACLE_SID="hrdb"
export TNS_ADMIN="/u01/app/oracle/19c/dbhome_1/network/admin"

PATH=$ORACLE_HOME/bin:$PATH


4.2 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


4.3 Configure listener 

cat $ORACLE_HOME/network/admin/listener.ora
SSL_CLIENT_AUTHENTICATION = FALSE

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
      (SECURITY=(WALLET_LOCATION=/u01/app/oracle/19c/wallet_root/tls))
    )
  )

ADR_BASE_LISTENER = /u01/app/oracle/19c

4.4 Set the wallet_root parameter and restart the database and listener

sqlplus / as sysdba
SQL> alter system set wallet_root='/u01/app/oracle/19c/wallet_root' scope=spfile;
SQL> shutdown immediate;
SQL> quit;
lsnrctl stop
lsnrctl stop
sqlplus / as sysdba
SQL> startup;
SQL> 
alter pluggable database all open;
SQL> alter system register;
SQL> quit;

4.5 Configure host firewall of database server to allow inboud (a.k.a. ingress) connections to non-secure port (1521) and secure port (2848)

sudo firewall-cmd --permanent --zone=public --add-port=1521/tcp
sudo firewall-cmd --permanent --zone=public --add-port=2484/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all


Step 5: Configure 19c database client

Instructions for downloading 19c database client at https://www.braddiggs.com/2024/11/setup-production-oracle-19c-database.html

5.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/client"
PATH=$ORACLE_HOME/bin:$PATH


5.2 Extract the 19c database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/V982065-01.zip


5.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to the path of the client wallet (/u01/app/oracle/tls)

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


5.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
WALLET_LOCATION=
  (SOURCE=  
    (METHOD=file)    
    (METHOD_DATA=    
      (DIRECTORY=/u01/app/oracle/tls)
    )
  )

SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES=(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


Step 6: Test 19c client connections to the database

6.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


6.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


6.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


Step 7: Configure 23ai database client

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

7.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
PATH=$ORACLE_HOME/bin:$PATH


7.2 Extract the 23ai database client

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/
V1044258-01.zip


7.3 Add database configurations to tnsnames.ora setting the WALLET_LOCATION to the path of the client wallet (/u01/app/oracle/tls)

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )


7.4 Configure sqlnet.ora

cat $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (TCPS,NTS,BEQ)
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)


Step 8: Test 23ai client connections to the database

Instructions for downloading 23ai database client at https://www.braddiggs.com/2024/11/setup-production-oracle-23ai-database.html

8.1 Setup the database client environment variables

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
PATH=$ORACLE_HOME/bin:$PATH


8.2 Test to the container database (CDB) hrdb_ssl

sqlplus system/Oracle123@hrdb_ssl


8.3 Test to the pluggable database (PDB) pdb1_ssl

sqlplus system/Oracle123@pdb1_ssl


For troubleshooting, see my blog post on Troubleshooting Oracle One-way TLS Connection Errors.

Setup Production Oracle 19c Database Client


I've done quite a bit of work with the Oracle database clients lately and decided to write up the workflow that I use for my reference. I hope it is helpful to you as well.


Step 1: Go to eDelivery at https://edelivery.oracle.com/

Step 2: Login with your Oracle credentials

Step 3: Search on: "REL: Oracle Database Client 19.3.0.0.0" and click on Continue


Step 4: Select desired platform and click on Continue


Step 5: Read license terms, check agree checkbox to terms if you agree, and click continue


Step 6: Click on the V982065-01(V982065-01.zip) gold image to download

Step 7: Copy the image to target host


Step 8: Set the environment for the desired ORACLE_HOME

export ORACLE_BASE="/u01/app/oracle/19c"
export ORACLE_HOME="$ORACLE_BASE/client"


Step 9: Extract the software

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/V982065-01.zip


Step 10: Configure the tnsnames.ora for the data databases that you want to connect to from this database client.  For example:

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )





Setup Production Oracle 23ai Database Client

I've done quite a bit of work with the Oracle database clients lately and decided to write up the workflow that I use for my reference. I hope it is helpful to you as well.


Step 1: Go to eDelivery at https://edelivery.oracle.com/

Step 2: Login with your Oracle credentials

Step 3: Search on: "REL: Oracle Database Client 23.5.0.0.0" and click on Continue



Step 4: Select desired platform and click on Continue


Step 5: Read license terms, check agree checkbox to terms if you agree, and click continue

Step 6: Click on the V1044258-01(V1044258-01.zip) gold image to download

Step 7: Copy the image to target host


Step 8: Set the environment for the desired ORACLE_HOME

export ORACLE_BASE="/u01/app/oracle/23ai"
export ORACLE_HOME="$ORACLE_BASE/client"


Step 9: Extract the software

mkdir -p $ORACLE_HOME
cd 
$ORACLE_HOME
unzip -qo /u01/bits/V1044258-01.zip


Step 10: Configure the tnsnames.ora for the data databases that you want to connect to from this database client.  For example:

cat $ORACLE_HOME/network/admin/tnsnames.ora
HRDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hrdb.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

HRDB_SSL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = hrdb.example.com)(PORT = 2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = hrdb)
    )
  )

pdb1 =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCP)(HOST=hrdb.example.com)(PORT=1521))
    (CONNECT_DATA=
      (SERVER = DEDICATED)
      (SERVICE_NAME=pdb1)
    )
  )

pdb1_ssl =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=TCPS)(HOST=hrdb.example.com)(PORT=2484))
    (SECURITY=(WALLET_LOCATION=/u01/app/oracle/tls))
    (CONNECT_DATA=
      (SERVER=dedicated)
      (SERVICE_NAME=pdb1)
    )
  )