Extract the schema from a remote LDAP server
Published:
Updated:
How to extract the schema from a remote LDAP server and use it on a OpenLDAP instance.
Why?
This might be useful as a first step for duplicating a remote LDAP directory with a custom schema or for running your own minimal instance for testing/development.
Table of content
Extracting a schema from a remote LDAP service
Locating the subschema entry
We can discover the distingued name (DN) of the schema used by one LDAP entry through its subschemaSubentry
attribute:
ldapsearch ... -o ldif-wrap=no -LLL -s base \
-b "ou=foo,dc=example,dc=com" "(objectClass=subschema)" 'subschemaSubentry'
In practice, we are discovering the address of the root schema through the subschemaSubentry
attribute of the root DSE (DSA-specific Entry):
ldapsearch ... -o ldif-wrap=no -LLL -s base -b "" 'subschemaSubentry'
where the empty DN is the DN of the DSE (DSA-specific Entry)
This gives something such as:
dn:
subschemaSubentry: cn=Subschema
Fetching the subschema entry
No we can fetch the schema using this DN:
ldapsearch ... -o ldif-wrap=no -LLL -s base -b "cn=Subschema" '+' '*'
Which gives something like:
dn: cn=Subschema
structuralObjectClass: subentry
objectClass: top
objectClass: subentry
objectClass: subschema
objectClass: extensibleObject
cn: Subschema
[...]
attributeTypes: ( 2.999.33 NAME 'fooName' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} SINGLE-VALUE )
[...]
objectClasses: ( 2.999.42 NAME 'foo' SUP top AUXILIARY MAY ( fooName $ fooValue ) )
Integrating it into OpenLDAP
In order to integrate this into our own OpenLDAP server, we need to convert the schema to:
- the OpenLDAP schema format (see example):
- a LDIF (LDAP Data Interchange Format) using the OpenLDAP Configuration[1] (OLC) schema (see example).
Filtering the custom types
The first step is to only select the custom definitions which are not already present in OpenLDAP. We can use something such as:
grep -F " 2.999." ldapschema.ldif > ldapschema2.ldif
assuming all the definitions we are interested in are under the 2.999
OID.
Generating the OpenLDAP schema file
We can now generate the OpenLDAP schema file:
cat ldapschema2.ldif |
sed "s/^attributeTypes:/attributeType/" |
sed "s/^objectClasses:/objectClass/" > custom.schema
which yields:
attributeType ( 2.999.33 NAME 'fooName' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} SINGLE-VALUE )
[...]
objectClass ( 2.999.42 NAME 'foo' SUP top AUXILIARY MAY ( fooName $ fooValue ) )
Generating the OLC LDIF
The OLC LDIF can be generated from the schema file using slaptest
. Alternatively, it should be possible to generate it using some additional sed
:
(
echo 'dn: cn=custom,cn=schema,cn=config'
echo 'objectClass: olcSchemaConfig'
echo 'cn: custom'
cat ldapschema2.ldif |
sed "s/^attributeTypes:/olcAttributeTypes:/" |
sed "s/^objectClasses:/olcObjectClasses:/"
) > custom.schema
Which yields:
dn: cn=custom,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: custom
[...]
olcAttributeTypes: ( 2.999.33 NAME 'fooName' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} SINGLE-VALUE )
[...]
olcObjectClasses: ( 2.999.42 NAME 'foo' SUP top AUXILIARY MAY ( fooName $ fooValue ) )
Running through a Docker/OCI image
We can now run the LDAP service. For example, using the osixia/openldap
Docker image (using Docker or Podman):
FROM osixia/openldap:1.3.0
COPY custom.schema /container/service/slapd/assets/config/bootstrap/schema/custom.schema
podman build -t myldap .
podman run -p 127.0.0.1:8389:389 --name ldap docker.io/library/debian
Note
This Docker image only needs the .schema
file and automatically generates the .ldif
file from the .schema
file.
We can now check that everything went OK:
ldapsearch -H ldap://127.0.0.1:8389 -D "cn=admin,dc=example,dc=com" -w "$ldap_password" \
-o ldif-wrap=no -LLL -s base -b "" "cn=Subschema" '+' '*'
This LDIF file does not use the same schema as the
subschema
entry. ↩︎