Wednesday, March 25, 2026

Linux Entra ID Authentication Integration Options



In recent months, I've been asked by several customers what options exist for centralizing Linux authentication, authorization and user life cycle management with Microsoft Entra ID integration.  This would enable end users to connect via the secure shell (ssh) to Linux hosts using their existing Entra ID credentials. Unfortunately, the short answer is ... not enough. Based on my research as of March, 2026 there are three options that use an intermediate broker or server to provide indirect authentication against Entra ID.  However, the direct solution that most customers desire through the System Security Services Daemon (SSSD) is still in progress.  The target Red Hat/Oracle/CentOS version for the native SSSD solution is 10.

The in-direct connect option is through Microsoft Azure command line tool (az ssh) by way of the Azure Arc agent.  Let's look at each method to understand pros and cons of each.









Himmelblau
Himmelblau is an open source project that operates as an identity broker to Entra ID via the himmelblaud daemon.  This is the most comprehensive solution available thus far.
  • Type: Password + PIN verification authentication or just Microsoft HELLO PIN
  • Project: https://himmelblau-idm.org
  • GitHub Repo: https://github.com/himmelblau-idm/himmelblau
  • Walkthrough: https://www.youtube.com/watch?v=wCibnqVQ_bs
  • Pros: 
    • Users and groups can be managed in Entra ID 
    • Users can use standard ssh/putty into Linux hosts with this integration
    • Supports Entra ID MFA
    • Directly integrated into SuSE Linux and works for SSH and GDM
  • Cons:
    • Does not provide native OAuth2 authentication with Entra ID
    • Not officially supported by other major Linux vendors such as Red Hat and Oracle
    • Not an officially vendor supported solution outside of SuSE Linux
    • Already has a few security vulnerabilities (CVE-2025-54781, CVE-2026-31957, CVE-2026-31979, ...) 
    • It is not yet clear if this solution fully supports Entra ID conditional access policies
    • May require additional cost for license and/or support

Red Hat IPA Federation To Entra ID
This option extends Red Hat's IPA (Identity, Policy and Audit) solution by way of OpenID Connect (OIDC) to Entra ID where Entra ID is an identity provider (IdP) to IPA.  IPA is effectively an authentication and authorization broker to either internal or external identity providers.  The method of authentication between the Linux host and IPA appears to be either Kerberos or LDAP BIND even though the authentication between the IPA server and Entra ID is OIDC.
  • Type: Password, ssh key, and/or MFA
  • Support solution pages:
    • Login to RHEL using Microsoft Entra ID - https://access.redhat.com/solutions/7076188
    • Configure IdM to use Entra ID (Azure AD) as external IdP - https://access.redhat.com/solutions/7073948
  • Pros:
    • Users and groups can be managed in Entra ID 
    • Users can use standard ssh/putty into Linux hosts with this integration 
    • Officially supported by Red Hat
    • Enables use of identities in Entra ID
  • Cons:
    • Does not provide native OAuth2 authentication with Entra ID
    • Not officially supported by other Linux vendors
    • It is not yet clear if this solution fully supports Entra ID conditional access policies
    • Is not yet clear if solution supports Entra ID MFA
    • May require additional cost for license and/or support

Kerberos Domain Join With Microsoft Entra Domain Services
Microsoft's Entra Domain Services (e.g. managed AD Kerberos Domain Servers) can be used as an intermediary authentication to Entra ID via Kerberos authentication.
  • Type: Kerberos ticket
  • Kerberos Join to managed AD - https://learn.microsoft.com/en-us/entra/identity/domain-services/join-rhel-linux-vm?tabs=rhel
  • Pros:
    • Users and groups can be managed in Entra ID 
    • Users can use standard ssh/putty into Linux hosts with this integration
    • Does not support Entra ID MFA
  • Cons:
    • Does not provide native OAuth2 authentication with Entra ID
    • It is not yet clear if this solution fully supports Entra ID conditional access policies
    • May require additional cost for license and/or support

Azure Arc Enabled SSH Authentication
Azure Arc is a Microsoft Azure cloud service that provides a variety of host management capabilities such as updating the operating system, collecting log data, and providing proxied ssh to the hose via the Azure command line tool (az).  For example, once a Linux host is registered with Azure Arc, configured with Azure AD ssh Login software, specified the ssh port and the AADSSHLoginForLinux extension has been enabled, an Entra ID user can authenticate to the Linux host from the Azure console command prompt or any host running the Azure command line tool (e.g. az ssh arc ...).  Here is the basic workflow:
1. Login to Entra ID via the Azure command line tool:

az login

2. Use the Azure command line tool to remotely login to a Linux host:

az ssh arc --resource-group <az_resource_group> --name <linux_host> 

Note that this solution does not enable the standard ssh command to be able to authenticate using Entra ID integration. It only applies to authenticating through the Azure command line tool.
    • Type: Whatever is prescribed by Entra ID password and conditional access policies
    • SSH access to Azure Arc-enabled servers - https://learn.microsoft.com/en-us/azure/azure-arc/servers/ssh-arc-overview
    • Arc-enabled servers: Configuration and remote access - https://learn.microsoft.com/en-us/azure/azure-arc/servers/security-machine-configuration
    • Sign in to a Linux virtual machine in Azure by using Microsoft Entra ID and OpenSSH - https://learn.microsoft.com/en-us/entra/identity/devices/howto-vm-sign-in-azure-ad-linux
    • Pros:
      • Users and groups can be managed in Entra ID 
      • Provides native OAuth2 authentication with Entra ID
      • Supports Entra ID MFA
      • Supports Entra ID conditional access policies
      • Can ssh to the host without need of direct or indirect (e.g. VPN) connection to the Linux host
    • Cons:
      • Can only ssh to Linux hosts via the Azure command line tool
      • Users cannot use standard ssh/putty into Linux hosts
      • Linux hosts must run an local agent to facilitate authentication to the host
      • Azure agent will require additional resources and compute to facilitate connections to the host

    System Security Services Daemon (SSSD) Entra ID Integration
    The solution that most customers desire is native support of Entra ID integration by the SSSD service.  This solution appears to be in progress with a tentative target for inclusion in Red Hat/Oracle Linux 10.
    The SSSD 2.11.0 release notes announces the introductory of support of Entra ID integration through the sssd-idp package:
    "New generic id and auth provider for Identity Providers (IdPs), as a start Keycloak and Entra ID are supported."

    However, testing of this new capability indicates that the requisite libsss_idp.so library is not yet available. This is made evident by the following error in the /var/log/sssd/ssd_<domain>.log file:

    Unable to load module [idp] with path [/usr/lib64/sssd/libsss_idp.so]: /usr/lib64/sssd/libsss_idp.so: cannot open shared object file: No such file or directory

     Once SSSD finally and fully supports native OAuth2 integration with Entra ID, I expect that will support MFA and Entra ID Conditional Access Policies. However, time will tell. Here are references to this project:

    • Type: Whatever is prescribed by Entra ID password and conditional access policies
    • SSSD Identity Provider (IdP) Support - https://sssd.io/docs/idp/idp-introduction.html
    • sssd-idp man page - https://www.mankier.com/5/sssd-idp
    • Pros:
      • Users and groups can be managed in Entra ID 
      • Provides native OAuth2 authentication with Entra ID
      • Supports Entra ID MFA
      • Supports Entra ID conditional access policies
      • Can ssh to Linux hosts with standard ssh/putty tools
    • Cons:
      • Not yet fully implemented
    I hope you find this information helpful and useful.

    Blessings!


    Wednesday, March 18, 2026

    ODB Entra ID Integration For JDBC-thin Applications

    Centralizing Oracle AI Database Authentication, Authorization, and User Lifecycle Management is a great way to improve operational efficiency and improve security posture through the addition of multi-factor authentication (MFA).  For C-based Oracle Call Interface (OCI) and JDBC-thick driver clients, this is enabled through the Oracle instant client or Oracle full client applications.  However, JDBC-thin driver based applications such as SQL Developer, SQLcl and many others require the ojdbc-extensions libraries and all dependencies from the GitHub project https://github.com/oracle/ojdbc-extensions to enable Entra ID integration. In my previous blog post on Entra ID Integration For SQLDeveloper, I provided a sample set of ojdbc-extensions and dependencies as a standalone downloadable zip file.  Thanks to the great work of the Oracle JDBC team, there is a new command (get-deps) that enables downloading all of the extensions and requisites through the OJDBC driver.

    Lets say that you want to evaluate the next stable version of ojdbc-extensions driver version 1.0.5 with SQL Developer 24.3.1.  The following sequence guides you through that setup. Note that the same sequence can be applied to the previous ojdbc-extensions version 1.0.4 as well as the upcoming version 1.0.6 and future versions.

    1. Download 23.26.1 (or newer) of the Oracle JDBC-thin library from Maven repository or Oracle AI Database instant client.

    Oracle JDBC-thin library from Maven:

    curl -sko ojdbc11.jar https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc11/23.26.1.0.0/ojdbc11-23.26.1.0.0.jar

    Alternatively, the JDBC-thin library is included with the Oracle instant client at:
     https://www.oracle.com/database/technologies/instant-client/downloads.html

    2. Extract the Oracle instant client. In my case, I extracted into C:\u01\app\instantclient_23_26_1

    3. Download the desired 1.0.5 version of ojdbc-extensions into a version specific directory:

    cd C:
    cd \u01\app\instantclient_23_26_1
    java -jar ojdbc11.jar get-deps --coords com.oracle.database.jdbc/ojdbc-provider-azure/1.0.5 --path C:\u01\app\ojdbc-extensions-1.0.5

    If this fails, you may need also need to load private certificate chain for Web Application Firewall (WAF) SSL/TLS termination or SSL/TLS offloading service into the Java cacerts truststore:

    keytool -import -trustcacerts -alias privateca -keystore cacerts -file "C:\Users\dbUser\privateca.cer"



    4. Produce the output with Windows PowerShell that will be needed to update the SQL Devleoper product.conf configuration file located in <home>\AppData\Roaming\sqldeveloper\<version>:

    Get-ChildItem -Path "C:\u01\app\ojdbc-extensions-1.0.5" -Include "*.jar" -Recurse -Name -Force | ForEach-Object { Add-Content -Path C:\u01\app\ojdbc-extensions-1.0.5\product.txt  -Value "AddJavaLibFile C:\u01\app\ojbc-extensions-1.0.5\$_"}


    5. Stop SQL Developer

    6. Make a backup copy of the existing SQL Developer product.conf config file in <home>\AppData\Roaming\sqldeveloper\<version>.

    7. Update the <home>\AppData\Roaming\sqldeveloper\<version>\product.conf configuration file replacing all AddJavaLibFile references with those resulting from step 4 above.  Here was the resulting output for this iteration of these commands. Note that your execution may result in different library versions because they can change over time.

    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\accessors-smart-2.5.1.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\asm-9.6.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-core-1.54.1.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-core-http-netty-1.15.7.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-data-appconfiguration-1.7.3.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-identity-1.14.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-json-1.3.0.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-security-keyvault-secrets-4.9.1.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\azure-xml-1.1.0.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\content-type-2.3.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jackson-annotations-2.17.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jackson-core-2.17.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jackson-databind-2.17.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jackson-datatype-jsr310-2.17.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jcip-annotations-1.0-1.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jna-5.13.0.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\jna-platform-5.13.0.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\json-smart-2.5.1.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\lang-tag-1.7.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\msal4j-1.17.2.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\msal4j-persistence-extension-1.3.0.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-buffer-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-codec-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-codec-dns-4.1.112.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-codec-http-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-codec-http2-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-codec-socks-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-common-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-handler-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-handler-proxy-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-resolver-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-resolver-dns-4.1.112.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-resolver-dns-classes-macos-4.1.112.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-resolver-dns-native-macos-4.1.112.Final-osx-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-boringssl-static-2.0.69.Final-linux-aarch_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-boringssl-static-2.0.69.Final-linux-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-boringssl-static-2.0.69.Final-osx-aarch_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-boringssl-static-2.0.69.Final-osx-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-boringssl-static-2.0.69.Final-windows-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-tcnative-classes-2.0.69.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-classes-epoll-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-classes-kqueue-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-native-epoll-4.1.115.Final-linux-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-native-kqueue-4.1.115.Final-osx-x86_64.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\netty-transport-native-unix-common-4.1.115.Final.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\nimbus-jose-jwt-9.40.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\oauth2-oidc-sdk-11.18.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\ojdbc-provider-azure-1.0.4.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\ojdbc-provider-common-1.0.4.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\ojdbc8-23.7.0.25.01.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\oraclepki-23.7.0.25.01.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\reactive-streams-1.0.4.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\reactor-core-3.4.41.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\reactor-netty-core-1.0.48.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\reactor-netty-http-1.0.48.jar
    AddJavaLibFile C:\u01\app\ojdbc-extensions-1.0.5\slf4j-api-1.7.36.jar


    8. Start SQL Developer and test Entra ID integrated database authentication

    Try it out and let me know if it works for you.

    Blessings!

    Wednesday, February 18, 2026

    TLS Cert Rotation Lifetime Compression

    One way that vendors and customers are forcing the improvement of security posture of web public key infrastructure (PKI) is through progressively shortening the certificate rotation lifetime of the TLS Baseline Requirements (TBRs).  Apple led a charge in 2025 toward this end through a CA/Browser (CA/B) Forum Ballot SC-081v3 initiative.  The measure was overwhelmingly approved and certificate authorities and browser vendors have begin preparations for the eventual support of the following TLS certificate lifetime shortening guidelines:

    Root CA Validity
    Between 2922 days (approximately 8 years) and 9132 days (approximately 25 years)

    Short-lived Subscriber Certificates
    Certificates issued between March 15, 2024 and March 15, 2026 have maximum validity period of 10 days
    Certificates issued after March 15, 2026 have a maximum validity period of 7 days

    Domain Name and IP Address (Subject Alternative Name [SAN]) validation data reuse periods
    Certificates issued before March 15, 2026 have a validity period of up to 398 days
    Certificates issued between March 15, 2026 and March 15, 2027 have a validity period of up to 200 days
    Certificates issued between March 15, 2027 and March 15, 2029 have a validity period of up to 100 days
    Certificates issued after March 15, 2029 have a validity period of up to 10 days

    Subscriber Certificate Subject Identity Information and validation data reuse periods
    Certificates issued before March 15, 2026 have validity window of up to 825 days
    Certificates issued on or after March 15, 2026 have a validity window of up to 398 days

    Subscriber Certificate operational periods and key pair usage periods
    Certificates issued before March 15, 2026 have a validity period of up to 398 days
    Certificates issued between March 15, 2026 and March 15, 2027 have a validity period of up to 200 days
    Certificates issued between March 15, 2027 and March 15, 2029 have a validity period of up to 100 days
    Certificates issued after March 15, 2029 have a validity period of up to 47 days

    What does this mean to you?  Enterprises need to work through automating detection, validation, issuing and deploying certificates across their infrastructure as soon as possible.  There are many ways to detect certificate but the easiest is by using the openssl command to check the certificate validity period of a target <host>:<port>.  For example: 

    echo|openssl s_client -connect <database_host>:2484 2>&1 | openssl x509 -noout -text|egrep "^Certificate:|^        Issuer:|^        Subject|^        Validity|^            Not "
    Certificate:
            Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", OU = http://certs.starfieldtech.com/repository/, CN = Starfield Secure Certificate Authority - G2
            Validity
                Not Before: Oct 27 17:49:47 2024 GMT
                Not After : Nov  6 16:19:28 2025 GMT
            Subject: CN = hrdb.dbauthdemo.com
            Subject Public Key Info:

    Cloud providers such as Oracle Cloud Infrastructure (OCI) include services such as Cloud Guard for some certificates.

    Automating the issuing of certificate renewal and certificate retrieval is available via API for most public certificate authorities.

    Automating of rotating the old certificate out and the new one into a given product is product specific.

    Here are some great references and commentaries on these TLS certificate lifetime reductions:

    1. DigitCert: TLS Certificate Lifetimes Will Officially Reduce to 47 days

    2.  DigiCert: How Short-Lived Certificates Improve Certificate Trust


    I hope you find this information helpful.


    Blessings!


    Tuesday, November 18, 2025

    How To Make Database Client Certificate Trust Store

    While helping out a customer with Oracle Database TLS configuration, they realized that they didn't have a trust store for their database clients.  I shared that there is an easy way of creating the client trust store all necessary store formats with openssl. Here's how to accomplish for Oracle wallet, Java JKS and PKCS trust store formats.

    Note in all of the following examples, you will want to use your own password. For these examples, I've used Oracle123.

    Get Cert Chain

    The first thing to do is capture the cert-chain into a PEM file with openssl.  

    OpenSSL Export Method

    The easiest way to do this is via the openssl command with:

    timeout 5 openssl s_client -connect <db_host>:2484 -showcerts > ~/cert-chain.pem

    Standalone Oracle Database Export Method

    For a standalone Oracle database, you can use orapki to export the certificate.

    Setup the environment variables with:

    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


    Lookup the CN= value of the CA cert chain or if self signed, the certificate subject with:

    orapki wallet display -nologo -wallet $WALLET_ROOT/rootca_wallet/tls -complete


    Export the certificate using the CN= value of the previous command for <cnvalue> with:

    orapki wallet export -wallet $WALLET_ROOT/rootca_wallet/tls -pwd Oracle123 -dn <cnvalue> -cert ~/cert-chain.pem

    Exadata Export Method

    For Oracle Exadata systems, you can lookup the current certificate CN value via orapki command with:

    sudo su - grid -c "orapki wallet display -nologo -wallet /var/opt/oracle/dbaas_acfs/grid/tcps_wallets -complete"


    Then, use the orapki command to export the certificate to a file using the CN= value of the certificate returned from the previous command as an input (<cnvalue>) to the the following command:

    sudo su - grid -c "orapki wallet export -nologo -wallet /var/opt/oracle/dbaas_acfs/grid/tcps_wallets -dn CN=<cnvalue> -cert ~/cert-chain.crt"


    Then, you can view the contents of the certificate file as the grid user with:

    sudo cat ~grid/cert-chain.crt

    Client Wallet

    For Oracle database clients using the Oracle Call Interface (OCI) and JDBC-thick drivers, you will need an Oracle wallet containing the certificate chain.  Here's how to create the client wallet with Oracle's orapki command:

    mkdir clientwallet
    cd clientwallet
    orapki wallet create -wallet . -pwd Oracle123 -auto_login
    orapki wallet add -wallet . -pwd Oracle123 -trusted_cert -cert ~/cert-chain.pem

    Display the contents of the Oracle wallet with:

    orapki wallet display -wallet . -complete

    Java Key Store (JKS) Trust Store

    For JDBC-thin clients they will need either a JKS or PKCS12 trust store.  Here is how to create the JKS trust store from the certificate: 

    keytool -importcert -storepass Oracle123 -keystore clientstore.jks -alias root-ca-chain -file ~/cert-chain.pem -noprompt

    Display the contents of the JKS trust store:

    keytool -list -keystore clientstore.jks  -storetype JKS  -storepass Oracle123 -v

    PKCS12 Trust Store

    For JDBC-thin clients they will need either a JKS or PKCS12 trust store.  Here is how to create the PKCS12 trust store from the certificate: 

    keytool -importcert -storepass Oracle123 -storetype PKCS12 -keystore clientstore.p12 -alias root-ca-chain -file ~/cert-chain.pem -noprompt

    Display the contents of the PKCS12 trust store:

    keytool -list -storetype PKCS12 -keystore clientstore.p12 -storepass Oracle123 -v

    I hope this was helpful and informative.

    Blessings!

    Friday, November 14, 2025

    Analyzing TLS Negotiation With tshark

    One of the ever strengthening domains of security posture is network cryptography.  Every few years a new protocol version, set of cipher suites or key exchanges are introduced to strengthen network cryptography.    The current network cryptography standard is TLSv1.3. Looking ahead, Quantum-safe key exchange algorithms are on the horizon with ML-KEM.  However, the maximum advertised cryptographic standards don't always represent what the client and server negotiation agree upon. For example, an older version of a client may may not support modern standards and request to connect with a weaker protocol like SSLv3 or weaker cryptographic cipher suites.  This begs the question, how can you gain visibility into the negotiated terms offered by the client and agreed upon or rejected by the server.

    Wireshark and its command line equivalent tshark are packet analysis tools that we can use to watch the network traffic in real time to discern the cryptographic terms offered by the client and what was accepted by the server.

    Let's look at a few examples with 
    1. Oracle AI Database 26 (TCP port 2484)
    2. Oracle Database 19c (TCP port 2484) 
    3. Oracle Unified Directory (TCP port 1636).

    tshark Command

    In each of the examples, we will use the following tshark command with the exception of the port number.  For database queries, we will use port 2484. For Oracle Unified Directory, we will use port 1636.

    $ sudo tshark -i any -d "tcp.port==2484,ssl" -V -a duration:10 2>&1 | egrep "^    TLSv|Handshake Protocol:|Cipher Suites \(|Cipher Suite:|^            Version: |Handshake Protocol: .* Hello|Record Layer|^                Supported Version:|^            Extension: key_share|^                Key Share extension|^                    Key Share Entry:|Extension: supported_groups|Supported Group:|Curve Type:|Named Curve:|Server Params"| uniq | sed -e "s/(0x.*)//g" -e "s/^.*Handshake Protocol: Client Hello/Client requested:/g" -e "s/.*Version:/   Protocol Version:/g" -e "s/.*Cipher Suites /   Cipher Suites Requested:/g" -e "s/.*Handshake Protocol: Server Hello/Server replied with:/g" |egrep -v "Server replied with: Done|Encrypted Handshake Message|Application Data Protocol: Application Data|Handshake Protocol: Certificate|Change Cipher Spec Protocol|http-over-tls" &


    Oracle AI Database 26

    Here is the command run against Oracle AI 26 database with port 2484 immediately after running the tshark command.

    $ $ORACLE_HOME/bin/sqlplus system/Oracle123@pdb1_ssl

    SQL*Plus: Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems on Thu Nov 13 20:49:49 2025
    Version 23.26.0.0.0

    Copyright (c) 1982, 2025, Oracle.  All rights reserved.

    Last Successful login time: Thu Nov 13 2025 20:49:20 +00:00

    Connected to:
    Oracle AI Database 26ai Enterprise Edition Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
    Version 23.26.0.0.0

    SQL> quit
    Disconnected from Oracle AI Database 26ai Enterprise Edition Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
    Version 23.26.0.0.0


    Here is the result returned by tshark for Oracle AI 26 database.  

    Client requested:
    Client requested:
       Protocol Version: TLS 1.2 
       Cipher Suites Requested:(10 suites)
                    Cipher Suite: TLS_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 
                    Cipher Suite: TLS_AES_128_CCM_SHA256 
                    Cipher Suite: TLS_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 
                Extension: supported_groups (len=56)
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: secp521r1 
                        Supported Group: secp384r1 
                        Supported Group: secp256r1 
                        Supported Group: x25519 
                        Supported Group: sect571r1 
                        Supported Group: sect571k1 
                        Supported Group: sect409r1 
                        Supported Group: sect409k1 
                        Supported Group: sect283r1 
                        Supported Group: sect283k1 
                        Supported Group: ffdhe8192 
                        Supported Group: ffdhe6144 
                        Supported Group: ffdhe4096 
                        Supported Group: ffdhe3072 
                        Supported Group: ffdhe2048 
                        Supported Group: sect233k1 
                        Supported Group: sect233r1 
                        Supported Group: secp224r1 
                        Supported Group: secp192r1 
                        Supported Group: sect163k1 
                        Supported Group: sect163r2 
       Protocol Version: TLS 1.3 
       Protocol Version: TLS 1.2 
                Extension: key_share (len=806)
                    Key Share extension
                        Key Share Entry: Group: Unknown (512), Key Exchange length: 800
    Server replied with:
    Server replied with:
       Protocol Version: TLS 1.2 
                Cipher Suite: TLS_AES_256_GCM_SHA384 
       Protocol Version: TLS 1.3 
                Extension: key_share (len=772)
                    Key Share extension
                        Key Share Entry: Group: Unknown (512), Key Exchange length: 768
    Client requested:
    Client requested:
       Protocol Version: TLS 1.2 
       Cipher Suites Requested:(10 suites)
                    Cipher Suite: TLS_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 
                    Cipher Suite: TLS_AES_128_CCM_SHA256 
                    Cipher Suite: TLS_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 
                Extension: supported_groups (len=56)
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: Unknown 
                        Supported Group: secp521r1 
                        Supported Group: secp384r1 
                        Supported Group: secp256r1 
                        Supported Group: x25519 
                        Supported Group: sect571r1 
                        Supported Group: sect571k1 
                        Supported Group: sect409r1 
                        Supported Group: sect409k1 
                        Supported Group: sect283r1 
                        Supported Group: sect283k1 
                        Supported Group: ffdhe8192 
                        Supported Group: ffdhe6144 
                        Supported Group: ffdhe4096 
                        Supported Group: ffdhe3072 
                        Supported Group: ffdhe2048 
                        Supported Group: sect233k1 
                        Supported Group: sect233r1 
                        Supported Group: secp224r1 
                        Supported Group: secp192r1 
                        Supported Group: sect163k1 
                        Supported Group: sect163r2 
       Protocol Version: TLS 1.3 
       Protocol Version: TLS 1.2 
                Extension: key_share (len=806)
                    Key Share extension
                        Key Share Entry: Group: Unknown (512), Key Exchange length: 800
    Server replied with:
    Server replied with:
       Protocol Version: TLS 1.2 
                Cipher Suite: TLS_AES_256_GCM_SHA384 
       Protocol Version: TLS 1.3 
                Extension: key_share (len=772)
                    Key Share extension
                        Key Share Entry: Group: Unknown (512), Key Exchange length: 768

    The things to note from this output is that the client requested to connect with TLS 1.3 with the TLS_AES_256_GCM_SHA384 cipher suite using an unknown 768 bit key exchange group.  The key group is actually a hybrid TLS 1.3 connection using quantum-safe ML-KEM algorithm.  This algorithm is so new that RedHat/Oracle Linux 9 does not yet have it identified and thus marks it as Unknown.  To learn more about Oracle AI 26 database support of the new quantum-safe ML-KEM algorithm, go to the "Securing Oracle AI Database 26ai for the Quantum Era" blog.  The new ML-KEM algorithm groups are identified by IANA (https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8) as:
    • MLKEM512
    • MLKEM768
    • MLKEM1024
    • SecP256r1MLKEM768
    • X25519MLKEM768
    • SecP384r1MLKEM1024
    Once RedHat/Oracle 9 and Wireshark get updated to support these groups, they will be accurately represented in the tshark output.

    Oracle Database 19c

    Here's the SQL*Plus command that we run for Oracle 19c database with port 2484 immediately after running the tshark command:

    $ $ORACLE_HOME/bin/sqlplus system/Oracle123@pdb1_ssl

    SQL*Plus: Release 19.0.0.0.0 - Production on Thu Nov 13 17:44:02 2025
    Version 19.25.0.0.0

    Copyright (c) 1982, 2024, Oracle.  All rights reserved.

    Last Successful login time: Thu Nov 13 2025 17:29:44 +00:00

    Connected to:
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Version 19.25.0.0.0

    SQL> quit;
    Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Version 19.25.0.0.0


    Here is the result returned by tshark for Oracle 19c database:

    Client requested:
    Client requested:
       Protocol Version: TLS 1.2 
       Cipher Suites Requested:(25 suites)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV 
                Extension: supported_groups (len=32)
                        Supported Group: secp256r1 
                        Supported Group: secp521r1 
                        Supported Group: sect571k1 
                        Supported Group: sect571r1 
                        Supported Group: secp384r1 
                        Supported Group: sect409k1 
                        Supported Group: sect409r1 
                        Supported Group: sect283k1 
                        Supported Group: sect283r1 
                        Supported Group: secp224r1 
                        Supported Group: sect233k1 
                        Supported Group: sect233r1 
                        Supported Group: secp192r1 
                        Supported Group: sect163k1 
                        Supported Group: sect163r2
    Server replied with:
    Server replied with:
       Protocol Version: TLS 1.2 
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
        TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
            Handshake Protocol: Server Key Exchange
                EC Diffie-Hellman Server Params
                    Curve Type: named_curve 
                    Named Curve: secp256r1 
        TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
            Handshake Protocol: Client Key Exchange

    The things to note from the 19c connection output is that the client requested to connect with TLS 1.2 with the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite using an Elliptic Curve Diffe-Hellman key exchange. 

    Oracle Unified Directory 14c

    Here's the LDAP search command that we run for OUD immediately after running the tshark command with port 1636:

    $ /u01/mw_oud14c/oud1/OUD/bin/ldapsearch -h poc.example.com -Z -X -p 1636 -D 'cn=Directory Manager' -j /u01/cfg/...pw -b dc=example,dc=com -s sub uid=user1 dn
    dn: uid=user1,ou=People,dc=example,dc=com

     Here is the result returned by tshark for OUD directory server:

    Client requested:
    Client requested:
       Protocol Version: TLS 1.2 
       Cipher Suites Requested:(36 suites)
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 
                   Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA 
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA 
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA 
                Extension: supported_groups (len=22)
                        Supported Group: x25519 
                        Supported Group: secp256r1 
                        Supported Group: secp384r1 
                        Supported Group: secp521r1 
                        Supported Group: x448 
                        Supported Group: ffdhe2048 
                        Supported Group: ffdhe3072 
                        Supported Group: ffdhe4096 
                        Supported Group: ffdhe6144 
                        Supported Group: ffdhe8192 
       Protocol Version: TLS 1.3 
       Protocol Version: TLS 1.2 
                Extension: key_share (len=107)
                    Key Share extension
                        Key Share Entry: Group: x25519, Key Exchange length: 32
                        Key Share Entry: Group: secp256r1, Key Exchange length: 65
    Server replied with:
    Server replied with:
       Protocol Version: TLS 1.2 
                Cipher Suite: TLS_AES_128_GCM_SHA256 
       Protocol Version: TLS 1.3 
                Extension: key_share (len=36)
                    Key Share extension
                        Key Share Entry: Group: x25519, Key Exchange length: 32

    From the above output, we see that the LDAP search connected with TLS protocol version 1.3 using TLS_AES_128_GCM_SHA256  cipher suite with Elliptic Curve Diffie Hellman key exchange (x25519).

    In all of the tshark examples provided, I presumed that both wireshark/tshark and sudo are available available for use on the database or directory server host.  If that is not the case you can work with your administrator to collect the tcpdump file, copy the file to another host and then run the tshark analaysis on that file.

    $ sudo timeout 10 tcpdump -s 65535 -w /var/opt/tfile -i any "tcp port 1636 or tcp port 2484"

    Copy the file (/var/opt/tfile or whatever name and location you used) to the host where tshark can analyize the tcpdump file.  Here is the tshark command using the tcpdump file as the input.  It is the same command as before but with an additional parameter to read the data from an input file.

    $ sudo tshark -r /var/opt/tfile -i any -d "tcp.port==2484,ssl" -V -a duration:10 2>&1 | egrep "^    TLSv|Handshake Protocol:|Cipher Suites \(|Cipher Suite:|^            Version: |Handshake Protocol: .* Hello|Record Layer|^                Supported Version:|^            Extension: key_share|^                Key Share extension|^                    Key Share Entry:|Extension: supported_groups|Supported Group:|Curve Type:|Named Curve:|Server Params"| uniq | sed -e "s/(0x.*)//g" -e "s/^.*Handshake Protocol: Client Hello/Client requested:/g" -e "s/.*Version:/   Protocol Version:/g" -e "s/.*Cipher Suites /   Cipher Suites Requested:/g" -e "s/.*Handshake Protocol: Server Hello/Server replied with:/g" |egrep -v "Server replied with: Done|Encrypted Handshake Message|Application Data Protocol: Application Data|Handshake Protocol: Certificate|Change Cipher Spec Protocol|http-over-tls" 

    Although Wiresharek and tshark are great external tools for analyzing the cryptographic negotiation at the network layer, my hope and desire for all network products is that they will one day log the agreed upon terms of cryptographic negotiation.  This will greatly streamline network cryptographic analysis and help IT professionals identify clients using weak cryptography that need to be updated to use modern cryptography and mischievous clients that are intentionally using weak cryptography to find weak points of entry for penetration and lateral movement once inside an organization.

    Several yeas ago, OUD implemented a feature for this very purpose. It can be implemented on access and admin log publishers by setting log-connection-details:true.  For example:

    set-log-publisher-prop --publisher-name "File-Based Access Logger" --set log-connection-details:true

    Once enabled, secure connections log the protocol, version and cipher suite. For example:

    [14/Nov/2025:17:14:29 +0000] CONNECT CONN_DETAILS conn=2 tlsVersion=TLSv1.3 cipherSuite=TLS_AES_128_GCM_SHA256

    Log analytics tools such as OCI Logging Analytics can consume the log data and identify clients using weak cryptography as seen in the following dashboard example.  The upper right widget reveals clients using weak cryptographic protocols such as SSLv3, TLSv1.0, ... etc.   The widget right below it shows use of weak cryptographic cipher suites.


    Details on OUD Logging Analytics is available on my blog here.

    I hope you found this information informative and helpful.

    Blessings!

    Wednesday, November 12, 2025

    Rotate Oracle Database CA-signed TLS Certificates

    Transport Layer Security (TLS) certificate rotation is an annual part of database operationalization.  The purpose of this blog post is to know when and how to rotate certificate authority (CA) signed TLS certificate(s).

    When To Rotate TLS Certificates

    In short, the TLS certificate should be rotated before the certificate expires.  However, you have a range of operational approaches available.

    1. SCHEDULE - Use your internal systems to track when each certificate should be rotated and schedule rotation at least a week in advance of certificate expiration.

    2. SCAN - Proactively periodic review of each database host's certificate.  Here is a command that you can use on a Linux host to check the validity of a database server's certificate. 

    echo|openssl s_client -connect <database_host>:2484 2>&1 | openssl x509 -noout -text|egrep "^Certificate:|^        Issuer:|^        Subject|^        Validity|^            Not "
    Certificate:
            Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", OU = http://certs.starfieldtech.com/repository/, CN = Starfield Secure Certificate Authority - G2
            Validity
                Not Before: Oct 27 17:49:47 2024 GMT
                Not After : Nov  6 16:19:28 2025 GMT
            Subject: CN = hrdb.dbauthdemo.com
            Subject Public Key Info:


    3. SUPPORT CLIENT REACTION - Reactively respond to rejected secure client SQL connections with error "ORA-29024: Certificate validation failure". This happens when the certificate has expired but the database server has not yet been restarted.


    4. SUPPORT SERVER REACTION - Reactively respond to an error logged by the database server after restarting with an expired certificate or see errors in the listener log ($ORACLE_BASE/diag/tnslsnr/hrdb/listener/trace/listener.log):  

    13-NOV-2025 00:20:39 * 28791
    ORA-28791: certificate verification failure
     TNS-12560: TNS:protocol adapter error
      TNS-00540: SSL protocol adapter failure

    Or, secure client connections may be rejected with error  "ORA-28864: SSL connection closed gracefully" or "ORA-28860: Fatal SSL error".  These are errors that you may see after restarting a database with an expired certificate. You can use the Linux openssl command to determine if there is a valid certificate.  If "no peer certificate available" is returned, that means that the database server didn't load the certificate because it has expired.

    echo|openssl s_client -connect $(hostname -f):2484 -showcerts 
    CONNECTED(00000003)
    140280481429312:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl/record/rec_layer_s3.c:1544:SSL alert number 40
    ---
    no peer certificate available
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 7 bytes and written 339 bytes
    Verification: OK
    ---
    New, (NONE), Cipher is (NONE)
    Secure Renegotiation IS NOT supported
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    Early data was not sent
    Verify return code: 0 (ok)
    ---


    How To Rotate TLS Certificates

    When it is time to rotate in the new certificate, here is the process for a certificate that is signed by a certificate authority.

    1. Backup all of the existing wallets

    cd $WALLET_ROOT
    zip -r wallet-backup-$(date +'%Y%m%d').zip tls [0-9A-Z]*/tls


    2. Download and extract the updated certificate from the certificate authority.  In my case, the downloaded zip file contains the current signed certificate (ee406cc00e4cb32a) in crt and pem formats and the certificate chain (sf_bundle-g2) in crt format.

    unzip hrdb.dbauthdemo.com.zip
    Archive:  hrdb.dbauthdemo.com.zip
      inflating: sf_bundle-g2.crt
      inflating: ee406cc00e4cb32a.crt
      inflating: ee406cc00e4cb32a.pem


    3. Replace the certificate and certificate chain in each of the TLS wallets.

    orapki wallet replace -wallet $WALLET_ROOT/tls -pwd Oracle123 -user_cert -cert $WALLET_ROOT/a5b3357724f807a.crt

    orapki wallet replace -wallet $WALLET_ROOT/31E8327905743479E0632100000A7958/tls -pwd Oracle123 -user_cert -cert $WALLET_ROOT/a5b3357724f807a.crt

    ... for each PDBGUID wallet


    4. Restart the database

    5. Confirm the certificate successfully loaded with Linux openssl command or sqlplus.

    Test with Linux openssl command:

    echo|openssl s_client -connect <database_host>:2484 2>&1 | openssl x509 -noout -text|egrep "^Certificate:|^        Issuer:|^        Subject|^        Validity|^            Not "
    Certificate:
            Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", OU = http://certs.starfieldtech.com/repository/, CN = Starfield Secure Certificate Authority - G2
            Validity
                Not Before: Oct 27 17:49:47 2025 GMT
                Not After : Nov  6 16:19:28 2026 GMT
            Subject: CN = hrdb.dbauthdemo.com
            Subject Public Key Info:

    Test with SQL*Plus command:

    sqlplus system/Oracle123@pdb1_ssl

    SQL*Plus: Release 19.0.0.0.0 - Production on Thu Nov 13 00:03:32 2025
    Version 19.25.0.0.0

    Copyright (c) 1982, 2024, Oracle.  All rights reserved.

    Last Successful login time: Thu Nov 13 2025 00:02:55 +00:00

    Connected to:
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Version 19.25.0.0.0

    SQL> 


    6. Remove certs and certificate chain files

    rm -f sf_bundle-g2.crt ee406cc00e4cb32a.crt ee406cc00e4cb32a.pem


    That's it. I hope you found this information informative and helpful.

    Blessings!

    Friday, October 3, 2025

    Constraining TNS Searches

    This week, I had a most interesting customer request regarding limiting the scope of Oracle database name resolution (e.g. Transparent Network Substrate (TNS) / Net Service record lookups) search results by database clients to a single result.  The customer wanted the Oracle Unified Directory (OUD) directory service to limit the results returned by wild card searches by database clients to a single result.  For example, they didn't want a database client to be able to return all registered databases in OUD.

    Fortunately with OUD this is a very easy problem to solve.  You simply change the system wide default size-limit to 1.  This will prevent anonymous and any non-administrative users from returning the full list of registered databases. However, it is important to note this is not a recommended approach for general use because most directory service client applications return more than one result.  In the case of TNS name resolution, that is the the only use case for normal clients.

    With the default TNS configuration an anonymous search can list all registered databases:

    $ ldapsearch -T -h tns1.example.com -p 1389 -b dc=example,dc=com -s sub 'orclNetDescString=*'  dn
    dn: cn=mydb1,ou=Databases,cn=OracleContext,DC=example,DC=com

    dn: cn=mypdb1_tns1,ou=Databases,cn=OracleContext,DC=example,DC=com

    dn: cn=mytestdb,cn=OracleContext,DC=example,DC=com

    Changing the system wide size-limit to 1 per OUD directory service instance limits the results returned to just 1 entry.

    $ dsconfig -h tns1.example.com -X -p 4444 -D 'cn=Directory Manager' -j /u01/cfg/...pw --no-prompt set-global-configuration-prop --set size-limit:1

    With this system wide change applied, here is what is now returned to the database client for a wildcard search attempting to show all databases:

    $ ldapsearch -T -h tns1.example.com -p 1389 -b dc=example,dc=com -s sub 'orclNetDescString=*'  dn
    dn: cn=mydb1,ou=Databases,cn=OracleContext,DC=example,DC=com

    SEARCH operation failed
    Result Code:  4 (Size Limit Exceeded)
    Additional Information:  This search operation has sent the maximum of 1 entries to the client

    Specific searches for an individual database continue to work as expected. For example:

    $ ldapsearch -T -h tns1.example.com -p 1389 -b dc=example,dc=com -s sub 'cn=mydb1' orclNetDescString
    dn: cn=mydb1,ou=Databases,cn=OracleContext,DC=example,DC=com
    orclNetDescString: (DESCRIPTION= (ADDRESS = (PROTOCOL = TCP)(HOST = tns1.example.com )(PORT = 1521))(CONNECT_DATA = (SERVICE_NAME = mydb1 )))

    Some directory experts might point out that this can be worked around by reducing the page size to 1. Again with OUD, that is a privilege that can be taken away and is not enabled by default for anonymous users as you can see from the example below:

    ldapsearch -T -h tns1.example.com -p 1389 --simplePageSize 1 -b dc=example,dc=com -s sub 'orclNetDescString=*'  dn
    SEARCH operation failed
    Result Code:  50 (Insufficient Access Rights)
    Additional Information:  The request control with Object Identifier (OID) "1.2.840.113556.1.4.319" cannot be used due to insufficient access rights


    There is one thing that needs to be addressed.  TNS administrators are impacted by this system wide change as well. To resolve this constraint, we simply override the system wide size-limit with a user specific size-limit.  For example:

    $ ldapmodify -h tns1.example.com -Z -X -p 1636 -D "cn=Directory Manager" -j /u01/cfg/...pw <<EOF
    dn: cn=tnsadmin,ou=TNSAdmins,cn=OracleContext
    changetype: modify
    add: ds-rlim-size-limit
    ds-rlim-size-limit: 0
    EOF

    Now, the TNS administrator has sufficient privilege to list all databases in OUD.

    I hope you found this information useful and insightful.

    Blessings!