{scrollbar} Work in progress

This site is in the process of being reviewed and updated.

Add your first elements to the schema

This section shows how to define custom schema elements, and how to add them to an ApacheDS 1.5 instance.

22list

Motivation

The schema of an LDAP server is comprised of object classes, attributes, syntaxes and matching rules. Basically it defines which entries are allowed within the server and how the server should handle them. In contrast to the 1.0 release, ApacheDS 1.5.0 comes with a completely redesigned schema subsystem. It enables dynamic schema updates, like the creation of new attribute types or object classes at runtime (i.e. without restarting the server).

Is it always necessary to define my own schema elements?

No. ApacheDS comes with a comprehensive set of predefined, standardized schema elements (like inetOrgPerson). It is quite common to solely use the predefined schema. The same holds true for other directory servers, by the way.

In the following text the addition of user defined schema elements to the schema is described in tutorial style.

Browsing the schema of ApacheDS

LDAPv3 servers publish their schema via LDAP. Thus it is possible to list the schema elements with standard LDAP tools. For instance it is possible to use the ldapsearch command line tool to list all object classes

none $ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w ****** \ -b "cn=schema" -s base "(objectclass=subschema)" objectclasses ... objectClasses: ( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) X-SCHEMA 'core' ) ...

The output (formatted as defines in RFC 4512) contains all things which are interesting to know about an object class (required attributes, optional attributes etc.), but is not easy to read by a human user. It is therefore often appropriate to use a GUI tool to browse the schema (which basically performs the same search operations but presents the output prettily). One option is Apache Directory Studio, an Eclipse based LDAP tool set which contains a powerful graphical Schema browser:

The techniques described above work for all LDAP v3 compliant servers. The ability to browse the schema gives us a chance to check whether our future changes to the schema really took place.

The schema subsystem of ApacheDS 1.5 stores the schema elements as entries in the DIT. You can find them within a special partition with suffix ou=schema; simply browse the content with your favorite LDAP Browser. With Apache Directory Studio, it looks like this:

Browsing the schema like this gives a good impression of the ApacheDS implementation of the schema subsystem and an even better way to analyze effects during schema updates. But keep in mind that the storage scheme is server dependent; not all LDAP server implementations store the schema elements in the DIT.

Which OIDs should you use?

If you plan to add custom schema elements, you need numerical OIDs (object identifiers) for them. If you implement schema elements defined somewhere else (like eduPerson), you can use the OIDs which are are part of their descriptions. But what if you plan to design your own?

Some OID background information

An OID is a string formed by a series of numbers which are seperated by a dot (like "12.4.1971.0.1"). Many elements in directory world use OIDs: Controls, extended operations and schema elements (like "2.5.6.6" for object class person). They identify these objects in a unique fashion and therefore avoid name clashes.

How is this accomplished? OIDs are assigned hierarchically: The owner of an OID is allowed to create new IDs by simply appending numbers. S/he is also allowed to delegate ownership of newly created OIDs to someone else. This way every person or organization is able to allocate an arbitrary number of new OIDs after obtaining one from "higher command", and they are still unique world-wide.

OIDs in the example

OIDs starting with 1.3.6.1.4.1 represent IANA-registered private enterprises, Apache Software Foundation for instance owns the OID 1.3.6.1.4.1.18060. The 1.3.6.1.4.1.18060.0 has been assigned to the Apache Directory project by the ASF, and we have decided to use the branch "1.3.6.1.4.1.18060.0.4.3" for schema elements used as examples in the documentation.

OIDs for your own custom schema elements

If you just want to play around with the schema subsystem, want to explore the capabilities, or learn about LDAP in general, you will probably not mind about unique OIDs. This is comparable to using self-signed certificates for SSL experiments. But it is nevertheless necessary that you use OIDs which are not used in the schema yet (otherwise addition will fail).

But if you plan to use your schema elements in a production environment (an object class for instance which describes employees with company specific attributes), or to ship your schema elements with a product (e.g. a CRM or portal solution), you should definitely use unique OIDs. In order to do this you have to obtain OIDs from a branch assigned to your company or organization (your network administrators will be helpful here, do not invent OIDs without asking or obtaining a branch from someone who owns the prefix OID). If your company or organization does not own on OID, there are several option to obtain one, one is the IANA (Internet Assigned Numbers Authority). It is also possible to get an OID branch as an individual.

Obtaining a PEN

You can ask for your own PEN (Private Enterprise Number) here : http://pen.iana.org/pen/PenApplication.page
It takes a few weeks to have a private OID assigned to you, so be patient, or do it early !

A simple example

The goal is to store ship entries in our directory, backing the "Seven Seas" example used throughout the Basic User's Guide. There are no schema elements shipped with ApacheDS covering our naval requirements. So we add some.

Here is a sample entry for a ship in LDIF:

none dn: cn=HMS Victory,ou=ships,o=sevenSeas objectClass: top objectClass: ship cn: HMS Victory numberOfGuns: 104 description: a ship of the line of the Royal Navy description: built between 1759 and 1765

A ship entry is comprised of a mandatory value for common name (cn) of the ship, description values and the number of guns (numberOfGuns). Thus a new object class ship and a new attribute type numberOfGuns have to be added to the schema. There are different ways to accomplish the task. In any case, we have to add the attribute type first, because the object class refers to it.

attribute type numberOfGuns

Here is the definition of our custom attribute type numberOfGuns formatted according to RFC 4512.

none ( 1.3.6.1.4.1.18060.0.4.3.2.1 NAME 'numberOfGuns' DESC 'Number of guns of a ship' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

object class ship

Custom object class ship is defined as follows

none ( 1.3.6.1.4.1.18060.0.4.3.3.1 NAME 'ship' DESC 'An entry which represents a ship' SUP top STRUCTURAL MUST cn MAY ( numberOfGuns $ description ) )

Using Apache Directory Studio Schema Editor to load the new schema elements

A very convenient way to add your own schema elements to Apache Directory Server is to use the Schema Editor of Apache Directory Studio. It is even possible to define/design them within the UI, but we opt here use a prepared file in OpenLDAP format and import it using Studio. This is a good choice if you have the schema to add already described that way.

Our file sevenSeas.schema looks like this:

none attributetype ( 1.3.6.1.4.1.18060.0.4.3.2.1 NAME 'numberOfGuns' DESC 'Number of guns of a ship' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) objectclass ( 1.3.6.1.4.1.18060.0.4.3.3.1 NAME 'ship' DESC 'An entry which represents a ship' SUP top STRUCTURAL MUST cn MAY ( numberOfGuns $ description ) )

In Eclipse with the Apache Directory Studio plugins installed (or alternatively the standalone RCP application of Apache Directory Studio, if you prefer this), open the Schemas view.

When it is shown, press the Open a schema file button in the toolbar of it. In the file dialog, open the sevenSeas.schema. It is loaded and added to the schemas within the view.

Select Export For ApacheDS ... in the context menu of the sevenSeas elements. The schema will be stored in an LDIF file which can directly be imported into ApacheDS (we choose the file name sevenSeas.ldif).

Use Apache Directory Studio to open a connection to your ApacheDS server, bind as administrator, and select Import | LDIF Import ... in the context menu of the DIT. Choose the LDIF file previously stored, and import the file. Alternatively, you can use command line tools like ldapmodify to load the file. If no errors are displayed, you are done.

There are several options to check whether the additions has be successful. One is to use the browse techniques described above. You can also use specific search commands like this one:

none $ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w ****** \\ -b "ou=schema" -s sub "(m-name=numberOfGuns)" version: 1 dn: m-oid=1.3.6.1.4.1.18060.0.4.3.2.1,ou=attributeTypes,cn=other,ou=schema m-usage: USER_APPLICATIONS m-equality: integerOrderingMatch objectClass: metaAttributeType objectClass: metaTop objectClass: top m-name: numberOfGuns m-oid: 1.3.6.1.4.1.18060.0.4.3.2.1 m-singleValue: TRUE m-description: Number of guns of a ship m-collective: FALSE m-obsolete: FALSE m-noUserModification: FALSE m-syntax: 1.3.6.1.4.1.1466.115.121.1.27

Of course it visible possible within the Apache Directory Studio UI as well. You will likely have to refresh the schema to see the new elements in the schema browser

Now you are done: The schema elements are ready to use. Feel free to add your fleet!

Using LDIF to load schema elements in RFC 4512 format

You could write an LDIF with your schema elements in RFC 4512 format and import the LDIF using command line or Apache Directory Studio. The LDIF for our example looks like this:

none dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.1 NAME 'numberOfGuns' DESC 'Number of guns of a ship' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) - add: objectClasses objectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.1 NAME 'ship' DESC 'An entry which represents a ship' SUP top STRUCTURAL MUST cn MAY ( numberOfGuns $ description ) ) -

Using JNDI to add the schema elements programmatically

You may want to add schema elements programmatically (for instance in a unit test) via a Java program acting as a client. One option here is to use JNDI and its LDAP provider. The advantage of this approach is that it is server independent; it works on LDAP servers other than ApacheDS as well as long as the server supports dynamic updates and the bind user is allowed to perform these operations (normally only admistrators are allowed to do this).

Some simple Java programs

In the following you find source code examples on how to add the two elements. The proceeding is described in more detail in the JNDI Tutorial (Chapter "Tips for LDAP Users // Schema "). Both use connection data provided by jndi.properties of the following form

none java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url=ldap://zanzibar:10389/ java.naming.security.principal=uid=admin,ou=system java.naming.security.credentials=****** java.naming.security.authentication=simple

This simple program (file CreateAttributeType.java) creates the attribute type numberOfGuns

java import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; public class CreateAttributeType { public static void main(String[] args) throws NamingException { DirContext ctx = new InitialDirContext(); DirContext schema = ctx.getSchema(""); Attributes attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.18060.0.4.3.2.1"); attrs.put("NAME", "numberOfGuns"); attrs.put("DESC", "Number of guns of a ship"); attrs.put("EQUALITY", "integerOrderingMatch"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.27"); attrs.put("SINGLE-VALUE", "true"); schema.createSubcontext("AttributeDefinition/numberOfGuns", attrs); } }

and this one (file CreateObjectClass.java) the object class ship

java import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; public class CreateObjectClass { public static void main(String[] args) throws NamingException { DirContext ctx = new InitialDirContext(); DirContext schema = ctx.getSchema(""); Attributes attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.18060.0.4.3.3.1"); attrs.put("NAME", "ship"); attrs.put("DESC", "An entry which represents a ship"); attrs.put("SUP", "top"); attrs.put("STRUCTURAL", "true"); Attribute must = new BasicAttribute("MUST"); must.add("cn"); attrs.put(must); Attribute may = new BasicAttribute("MAY"); may.add("numberOfGuns"); may.add("description"); attrs.put(may); schema.createSubcontext("ClassDefinition/ship", attrs); } }

After successfully running the programs against the LDAP server defined in the connection data. The schema elements can also be found within a schema browser, but you may have to refresh the schema here as well. They are also ready to use

A final note for the JNDI approach: With the code shown above, the elements will be created by the ApacheDS schema subsystem within the other schema (in contrast to the sevenSeas schema ). You can also create them programmatically in a specific schema with the help of the X-SCHEMA attribute:

java ... attrs.put("X-SCHEMA", "sevenSeas"); ...

but in this case you have to create the skeleton entries for the sevenSeas schema before (loading an LDIF file like the one generated by Apache Directory Studio as depicted above). Otherwise you will get an NamingException ("LDAP: error code 54 - failed to modify entry cn=schema ...").

Using JNDI to add schema elements in RFC 4512 format programmatically

It is also possible to add schema elements in RFC 4512 format using JNDI:

java import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; public class CreateSevenSeasSchema { public static void main(String[] args) throws NamingException { DirContext ctx = new InitialDirContext(); Attributes atAttrs = new BasicAttributes(true); atAttrs.put("attributeTypes", "( 1.3.6.1.4.1.18060.0.4.3.2.1 NAME 'numberOfGuns' DESC 'Number of guns of a ship' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )"); ctx.modifyAttributes("cn=schema", DirContext.ADD_ATTRIBUTE, atAttrs); Attributes ocAttrs = new BasicAttributes(true); ocAttrs.put("objectClasses", "( 1.3.6.1.4.1.18060.0.4.3.3.1 NAME 'ship' DESC 'An entry which represents a ship' SUP top STRUCTURAL MUST cn MAY ( numberOfGuns $ description ) )"); ctx.modifyAttributes("cn=schema", DirContext.ADD_ATTRIBUTE, ocAttrs); } }

Resources

  • No labels