Introduction
To centralise Oracle naming resolution, you can use an LDAP server. You can use the commercial products from Oracle like Oracle Internet Directory (OID) or Oracle Universal Directory (OUD). Alternatively, you can also use OpenLDAP from your Linux distribution. I have used this successfully with customers for many years.
I now wanted to build a new test environment for myself on an Enterprise Linux 9 system (RedHat, Oracle Linux). But then I noticed that the opendap server is no longer available. After some internet searching, I found the following blog post that describes how to install OpenLDAP on EL9: https://seanstuber.com/2019/12/29/setting-up-openldap-on-oracle-linux-8-for-tns-name-resolution/
But is there no way to do this with on-board tools? A further search then revealed that RedHat has switched to 389-ds-base (https://www.port389.org/). So I want to try it with this native tool. And as I fear, almost everything is different here again… To spare you this try-and-error, I’ll give you the commands here on how to get an executable environment.
Installation and configuration
First of all, install the software:
[root@ol9b ~]# dnf install -y 389-ds-base openldap-clients
Caution! I stongly recommend to do a dnf upgrade before. I had the problem that you couldn’t log in with ssh afterwards and the ssh daemon couldn’t be restarted.
OpenSSL version mismatch. Built against 30000070, you have 30500080
At least a dnf upgrade "openssh*" was required and restart of sshd.
Afterwards, you can configure and start the LDAP server. We will use “orcladmin” as administrative user and “dbi” as instance name.
[root@ol9b ~]# dscreate interactive
Install Directory Server (interactive mode)
===========================================
Enter system's hostname [ol9b]:
Enter the instance name [ol9b]: dbi
Enter port number [389]:
Create self-signed certificate database [yes]:
Enter secure port number [636]:
Enter Directory Manager DN [cn=Directory Manager]: cn=orcladmin
Enter the Directory Manager password:
Confirm the Directory Manager Password:
Choose whether mdb or bdb is used. [bdb]:
Enter the database suffix (or enter "none" to skip) [dc=ol9b]: none
Do you want to start the instance after the installation? [yes]:
Are you ready to install? [no]: yes
Starting installation ...
Validate installation settings ...
Create file system structures ...
Create self-signed certificate database ...
Perform SELinux labeling ...
Perform post-installation tasks ...
Completed installation for instance: slapd-dbi
[root@ol9b ~]# systemctl status dirsrv@dbi
● [email protected] - 389 Directory Server dbi.
Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/system/[email protected]
└─custom.conf
...
After configuration, the daemon is already started and the service is also set to enabled. If you use a firewall on your server, open the ldap ports:
[root@ol9b ~]# firewall-cmd --permanent --add-service=ldap
[root@ol9b ~]# firewall-cmd --permanent --add-service=ldaps
[root@ol9b ~]# firewall-cmd --reload
Now we have to extend the schema with the extensions for Oracle naming resolution. Since Oracle 26ai (23.26), a schema file is available in $ORACLE_HOME/network/ldap/schema/openldap/orclnetnaming.schema; This file has to be converted to an ldif file for the ldapmodify tool. From:
attribute ( 2.16.840.1.113894.7.1.1
NAME 'orclVersion'
EQUALITY octetStringMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' )
attribute ( 2.16.840.1.113894.7.1.2
NAME 'orclOracleHome'
EQUALITY octetStringMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' )
...
to:
dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.1
NAME 'orclVersion'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.2
NAME 'orclOracleHome'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
...
And now you can load this schema extensions
[root@ol9b ~]# ldapmodify -x -H ldap://ol9b:389 -D "cn=orcladmin" -W -f orclnetnaming.ldif
Enter LDAP Password:
modifying entry "cn=schema"
We will create the DN dbi-services,dn=com
[root@ol9b ~]# dsconf dbi backend create --suffix="dc=com" --be-name="com" --create-suffix
The database was sucessfully created
[root@ol9b ~]# ldapadd -x -H ldap://ol9b:389 -D "cn=orcladmin" -W -f dbi-services.ldif <<EOD
dn: dc=dbi-services,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Oracle Internet Directory
dc: dbi-services
dn: cn=OracleContext,dc=dbi-services,dc=com
objectclass: orclContext
cn: OracleContext
EOD
Enter LDAP Password:
adding new entry "dc=dbi-services,dc=com"
adding new entry "cn=OracleContext,dc=dbi-services,dc=com"
Oracle tools need the so-called “anonymous bind” so that they can query the data without logging in. We still have to activate this.
[root@ol9b ~]# ldapmodify -x -H ldap://ol9b:389 -D "cn=orcladmin" -W <<EOD
dn: dc=dbi-services,dc=com
changetype: modify
add: aci
aci: (targetattr = "*")(version 3.0; acl "Anonymous read access"; allow (read, search, compare) userdn = "ldap:///anyone";)
EOD
The configuration is now complete, and we can insert the first sqlnet alias
[root@ol9b ~]# ldapadd -x -H ldap://ol9b:389 -D "cn=orcladmin" -W <<EOD
dn: cn=DB1970,cn=OracleContext,dc=dbi-services,dc=com
objectclass: top
objectclass: orclNetService
cn: DB1970
orclNetDescString: (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=ltp14s-i)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DB1970A.erfinder)))
EOD
Enter LDAP Password:
adding new entry "cn=DB1970,cn=OracleContext,dc=dbi-services,dc=com"
Testing
Now it gets exciting: does the Oracle name resolution work?
Probably we have to adapt our ldap.ora and sqlnet.ora files. For the test, I will create a temporary TNS_ADMIN directory.
[oracle@ltp14 ~]# mkdir /tmp/ldap
[oracle@ltp14 ~]# export TNS_ADMIN=/tmp/ldap
[oracle@ltp14 ~]# echo 'DIRECTORY_SERVERS= (ol9b:389:636)
DEFAULT_ADMIN_CONTEXT = "dc=dbi-services,dc=com"
DIRECTORY_SERVER_TYPE = OID' >$TNS_ADMIN/ldap.ora
[oracle@ltp14 ~]# echo 'NAMES.DEFAULT_DOMAIN=dbi-services.com
NAMES.DIRECTORY_PATH=(LDAP)' >sqlnet.ora
[oracle@ltp14 ~]# tnsping DB1970
TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 18-SEP-2026 13:48:26
Copyright (c) 1997, 2019, Oracle. All rights reserved.
Used parameter files:
/u00/app/oracle/network/admin/ldapdbi/sqlnet.ora
Used LDAP adapter to resolve the alias
Attempting to contact (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=ltp14s-i)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DB1970A.erfinder)))
OK (0 msec)
And YES! it works 🙂
Disclaimer: I’m not the expert of LDAP. I wanted to be able to quickly set up an LDAP server for Oracle name resolution. The setup certainly still has some optimization potential. Feel free to adapt it for your needs.
Annex
orclnetnaming.ldif (converted from 26ai $ORACLE_HOME/network/ldap/schema/openldap/orclnetnaming.schema)
dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.1 NAME 'orclVersion' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.2 NAME 'orclOracleHome' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.3 NAME 'orclSystemName' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.4 NAME 'orclServiceType' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.5 NAME 'orclSid' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.7.1.6 NAME 'orclProductVersion' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.1 NAME 'orclNetSourceRoute' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.2 NAME 'orclNetLoadBalance' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.3 NAME 'orclNetFailover' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.4 NAME 'orclNetSdu' EQUALITY numericStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.5 NAME 'orclNetServer' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.6 NAME 'orclNetServiceName' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.7 NAME 'orclNetInstanceName' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.8 NAME 'orclNetHandlerName' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.9 NAME 'orclNetParamList' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.10 NAME 'orclNetAuthenticationType' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.11 NAME 'orclNetAuthParams' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.12 NAME 'orclNetDescName' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.13 NAME 'orclNetDescString' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.14 NAME 'orclNetAddressString' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.15 NAME 'orclNetProtocol' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.16 NAME 'orclNetShared' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.17 NAME 'orclNetAddrList' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.18 NAME 'orclNetProtocolStack' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.19 NAME 'orclNetDescList' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.20 NAME 'orclNetConnParamList' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: attributeTypes
attributeTypes: ( 2.16.840.1.113894.3.1.21 NAME 'orclNetAuthenticationService' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.7.2.3 NAME 'orclContext' SUP top MAY ( cn $ orclNetDescName ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.7.2.6 NAME 'orclSchemaVersion' SUP top MUST ( cn $ orclProductVersion ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.1 NAME 'orclNetAddress' SUP top MUST (cn) MAY ( orclNetAddressString $ orclNetProtocol $ orclNetShared $ orclVersion $description) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.2 NAME 'orclNetAddressList' SUP top MUST (cn)
MAY ( orclNetAddrList $ orclNetSourceRoute $ orclNetLoadBalance $ orclNetFailover $ orclNetShared $ orclVersion $ description ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.3
NAME 'orclNetDescription' SUP top
MUST (cn)
MAY ( orclVersion $ orclNetSourceRoute $ orclNetSdu $ orclNetServer $ orclNetServiceName $ orclNetInstanceName $ orclNetHandlerName $ orclNetParamList $ orclNetAuthenticationType $ orclNetAuthParams $ orclNetShared $ orclNetAddrList $ orclNetProtocolStack $ orclNetConnParamList $ orclNetAuthenticationService $ orclNetLoadBalance $ orclNetDescList $ orclNetFailover $ orclNetShared $ orclNetAddrList ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.30
NAME 'orclNetDescriptionAux1' SUP top
AUXILIARY MUST (cn)
MAY ( orclVersion $ orclNetSourceRoute $ orclNetSdu $ orclNetServer $ orclNetServiceName $ orclNetInstanceName $ orclNetHandlerName $ orclNetParamList $ orclNetAuthenticationType $ orclNetAuthParams $ orclNetShared $ orclNetAddrList $ orclNetProtocolStack $ orclNetConnParamList $ orclNetAuthenticationService $ orclNetLoadBalance $ orclNetDescList $ orclNetFailover $ orclNetShared $ orclNetAddrList ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.4
NAME 'orclNetDescriptionList' SUP top
MUST (cn)
MAY ( orclNetLoadBalance $ orclNetDescList $ orclNetFailover $ orclNetShared $ orclNetAddrList ) )
-
add: objectClasses
objectClasses: ( 2.16.840.1.113894.3.2.5
NAME 'orclNetService' SUP top
MUST (cn)
MAY ( orclNetServiceName $ orclNetDescString $ orclNetDescName $ orclNetSourceRoute ) )