Oracle Enterprise User Security with multiple ldap.ora
Recently I came across the situation where I have to configure Enterpriser User Security for a database server with multiple databases for different directories. This is quite tricky when using a shared Oracle Home and a central TNS_ADMIN directory for SQLNet configuration. A common TNS_ADMIN also implies the use of only one ldap.ora file. Several ldap servers can be registered in one ldap.ora, but this is primarily used for failover configuration in a high-availability LDAP server architecture. The use of multiple EUS contexts in different LDAP servers is not supported. At least not in one single file. But there are some workarounds.
Oracle does look for the ldap.ora file in a few different places. The following sequence is maintained:
- $LDAP_ADMIN environment variable setting
- $ORACLE_HOME/ldap/admin directory
- $TNS_ADMIN environment variable setting
- $ORACLE_HOME/network/admin directory
Notes on this order can be found at different places in the Oracle documentation e.g Oracle Database Database Net Services Reference 19c Overview of Directory Server Usage File, Oracle Database Security Guide 19c About Using a dsi.ora File or in the Oracle Support Note 363283.1 What Is The Search Order For The LDAP.ORA File?
If you don’t trust the documentation, you can also verify the search order with strace. First define a few values for TNS_ADMIN and LDAP_ADMIN to be sure we do not use the default values.
export LDAP_ADMIN="/u01/config" export TNS_ADMIN="/u00/app/oracle/network/admin"
If we make sure, that LDAP is the first names resolution in sqlnet.ora we could use strace with tsnping.
[email protected]:~/ [TEUS01] grep -i NAMES.DIRECTORY_PATH $TNS_ADMIN/sqlnet.ora NAMES.DIRECTORY_PATH=(LDAP, TNSNAMES, EZCONNECT ) [email protected]:~/ [TEUS01] strace -o /u01/config/tnsping.txt tnsping TEUS01 TNS Ping Utility for Linux: Version 18.104.22.168.0 - Production on 28-NOV-2019 20:47:33 Copyright (c) 1997, 2019, Oracle. All rights reserved. Used parameter files: /u00/app/oracle/network/admin/sqlnet.ora Used TNSNAMES adapter to resolve the alias Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = eusdb)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = TEUS01))) OK (30 msec)
Checking the output does show the different directories
[email protected]:~/ [TEUS01] grep -i ldap.ora /u01/config/tnsping.txt stat("/u01/config/ldap.ora", 0x7ffd149f6af0) = -1 ENOENT (No such file or directory) stat("/u00/app/oracle/product/22.214.171.124/ldap/admin/ldap.ora", 0x7ffd149f6af0) = -1 ENOENT (No such file or directory) stat("/u00/app/oracle/network/admin/ldap.ora", 0x7ffd149f6af0) = -1 ENOENT (No such file or directory) stat("/u00/app/oracle/product/126.96.36.199/network/admin/ldap.ora", 0x7ffd149f6af0) = -1 ENOENT (No such file or directory) stat("/u00/app/oracle/product/188.8.131.52/network/admin/ldap.ora", 0x7ffd149f6be0) = -1 ENOENT (No such file or directory)
As you can see the search order does match the documented search order. But how does that help us? It’s actually relatively simple. To use different LDAP server configuration per database, we do have to make sure, that each database has an individual ldap.ora file. This can be ensured by one the following points:
- Have a dedicated Oracle Home for each database with an individual ldap.ora file in each Oracle Home
- Define an environment variable for LDAP_ADMIN for each database.
Both methods have their advantages and disadvantages, but aren’t optimal. As often, several paths lead to the goal. The third option uses a static listener configuration for the database with an ENVS parameter. Unfortunately, the information about ENVS has disappeared in the latest version of the Oracle documentation. At least in the Oracle Database Database Net Services Reference 19c. But you can search for ENVS in the Oracle Database Bookshelf. The parameter ENVS can be used to specify environment variables for the listener to set prior to executing (as a child process) a dedicated server program or an executable specified with the PROGRAM parameter. This allows a static listener entry to be defined for each database, where LDAP_ADMIN or TNS_ADMIN is explicitly set. Below you see an excerpt of listener.ora for ORACLE_SID TEUS01.
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = TEUS01 ) (ORACLE_HOME = /u00/app/oracle/product/184.108.40.206) (SID_NAME = TEUS01) (ENVS="LDAP_ADMIN=/u00/app/oracle/network/TEUS01") )))
The database TEUS01 does use a dedicated ldap.ora. If you add the listener entry just for this DB, you can keep the default ldap.ora in the regular TNS_ADMIN directory. Thus one can apply the following principle:
- Use a generic ldap.ora configuration in the TNS_ADMIN directory. e.g which is valid for most of the database on this server
- Add a static listener configuration for each database which does have to use a dedicate Oracle Enterprise User Security configuration and therefor a dedicated ldap.ora.
This method is not only helpful when configuring LDAP server or Oracle Enterprise User Security, but also in other SQLNet use cases. In particular the following:
- Define TNS_ADMIN and use a dedicate sqlnet.ora configuration for Kerberos authentication. e.g. when you want to use or engineer Kerberos authentication for just one database in an shared environment.
- Define TNS_ADMIN and use dedicate sqlnet.ora configuration for network encryption.
- Define LDAP_ADMIN for dedicated ldap.ora or dsi.ora files for engineering centrally managed users.
- And a couple more…
A few links and references related to this blog post