Using any old LDAP server as an Oracle name server

Setting up Oracle naming using LDAP is pretty straightforward, although the doc is, as usual, many pages of nothing.

To do this you need to: (1) set up the required entries on your LDAP directory; (2) configure your Oracle (e.g. sqlplus) clients to use LDAP.

Directory Server Set Up

For recent Oracle client versions this is only going to work correctly if you set up a “cn=OracleContext” entry directly under your LDAP root. The individual database service objects will live under this branch. For example, “cn=OracleContext,dc=example,dc=com”. This must be an orclContext objectclass entry, so you’ll need to add that objectclass to your directory schema. This already exists by default on Oracle Internet Directory (OID), but is easy to set up on other directories like OpenLDAP and Sun (now Oracle) Directory Server Enterprise Edition.

Here’s the raw schema entry for the orclContext objectclass in OpenLDAP schema format (see below for Sun Directory schema details, OID already has these schema objects by default):

objectclasses ( 2.16.840.1.113894.7.2.3
	NAME 'orclContext'
	DESC 'Oracle sqlnet context objects'
	SUP top
	STRUCTURAL
	MUST cn
        MAY description
 )

Note that allowing “description” as an attribute is totally optional and only included by me to allow self-documentation.

A separate entry for each Oracle database service needs to be created under “cn=OracleContext”. To do this, you need to add the structural objectclass orclService to your LDAP schema, along with the DirectoryString, single-valued attribute orclNetDescString.

Here are the raw schema entries for this new objectclass and attribute, in OpenLDAP schema format:

objectclasses ( 2.16.840.1.113894.7.2.1001
	NAME 'orclService'
	DESC 'Oracle sqlnet service objects'
	SUP top
	STRUCTURAL
	MUST cn
        MAY ( orclNetDescString $ description )
  )
attributetype ( 2.16.840.1.113894.3.1.13
	NAME 'orclNetDescString'
	DESC 'Oracle sqlnet tns connect string'
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	SINGLE-VALUE
 )

Once the schema is extended to include these new elements, you can go ahead and create your OracleContext and database service objects. Here’s how these would look in LDIF format:

cn=OracleContext,dc=example,dc=com
objectclass: top
objectclass: orclContext
cn: OracleContext
description: Oracle sqlnet context
	
cn=exampledb,cn=OracleContext,dc=example,dc=com
objectclass: top
objectclass: orclService
cn: exampledb
description: Example database service
orclnetdescstring: (DESCRIPTION= (ADDRESS = (PROTOCOL = TCP)
 (HOST = db.example.com)(PORT = 1521))(CONNECT_DATA =
 (SERVICE_NAME = exampledb)))

Note that the connect string is identical to what you’d see in a tnsnames.ora file, except that all the linefeeds are removed. For loading via an LDIF you should follow the accepted convention of making your lines no more than 80 columns long, continuing any that go over that limit on the next line with a single indent character indicating line continuation. I’ll try to come up with a script to automate this process for a later article.

As with tnsnames.ora files, the database listener configuration will determine whether you use “SID=” or “SERVICE_NAME=” in the CONNECT_DATA block.

If you restrict anonymous access to objects in your directory, you will need to adjust your access controls so that the orclContext and orclService entries can be searched by a client binding anonymously. In my environments I usually add an explicit access control allowing an anonymous client to search on objectclass, cn, description and orclnetdescstring from the OracleContext entry down.

Oracle Client Configuration

Configuring Oracle clients will involve modifying or creating an sqlnet.ora and ldap.ora file, as well as making sure these files are in the user environment TNS_ADMIN path. On Unix systems TNS_ADMIN is usually set by doing an “export TNS_ADMIN=[directory path]. For example “export TNS_ADMIN=/etc/oracle”.

The format for sqlnet.ora can be as simple as:

# sqlnet.ora Network Configuration File
NAMES.DIRECTORY_PATH= (LDAP, TNSNAMES, HOSTNAME)

For ldap.ora, you should have something like:

# ldap.ora Directory Service config file
DIRECTORY_SERVERS= (ldap.example.com:389:636)
DEFAULT_ADMIN_CONTEXT = "dc=exampledc=com"
DIRECTORY_SERVER_TYPE = OID

The “DIRECTORY_SERVER_TYPE = OID” is required, and will work for most LDAP directories. If you are trying to do this with a Microsoft Active Directory you need to set the value to “AD” and follow Oracle’s documentation for setup rather than what I’ve written here.

To test that things are really working I would recommend changing the “NAMES.DIRECTORY_PATH” parameter in sqlnet.ora to just “(LDAP)”.

This setup has been tested with Oracle Instant Client 11.1.0.7.0 and DBD::Oracle on Linux, with either a Sun JSDS or OpenLDAP server as the LDAP directory host.

Special Note for Sun (now Oracle) Directory Server Enterprise Edition admins:

The Sun Directory schema (v5 +) entries in 99user.ldif would be as follows:

objectClasses: ( 2.16.840.1.113894.7.2.3 NAME 'orclContext' SUP top
 STRUCTURAL  MUST cn MAY description X-ORIGIN 'user defined' )
	
objectClasses: ( 2.16.840.1.113894.7.2.1001 NAME 'orclService' SUP
 top STRUCTURAL MUST cn MAY ( description $ orclNetDescString )
 X-ORIGIN 'user defined'
 )
	
attributeTypes: ( 2.16.840.1.113894.3.1.13 NAME 'orclNetDescString'
 DESC 'Sqlnet connect string' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
 SINGLE-VALUE X-ORIGIN 'user defined' )