Defining New Schema Elements

   

If your schema needs are not adequately met by existing, predefined schemas, you will need to define your own object classes and attributes. It is fairly easy to define your own schemas, but as with all design tasks , there are pitfalls and trade-offs to be considered . In this section we describe an approach that should produce good results. We do not discuss defining new attribute syntaxes because in most implementations adding new syntaxes requires code to be written to support it, usually by the directory software vendor.

Choosing Names for New Attribute Types and Object Classes

You should choose a naming scheme for the new object classes and attributes you define. All names should be made as meaningful as possible but not too long or cumbersome. Attribute names and object classes are generally hidden from end users, but directory service administrators and applications developers will work with them extensively.

It is also important to make some effort to avoid collisions with the names chosen by other parties (standards committees , directory vendors, other software vendors , and so on). Remember, the entire attribute namespace is flat. The same is true for the object class namespace. A good strategy is to prefix the names of all the schema elements you define with something that resembles your organization's name . If you do that, collisions with other definitions are unlikely .

For example, the ACME Corporation might use the prefix "acme" and create attributes and object classes such as these:

 acmePerson (object class) acmePrinter (object class) acmeID (object class) acmeHoursAllowedAccess (attribute type) 

Tip

If you define schema elements that you intend to publish widely and submit to a standards body such as the IETF, there is no need to prefix the names of the attributes and object classes with a string that identifies your organization. In fact, acceptance of your schema by others will likely be hindered if the names include something specific to your organization!


Obtaining and Assigning Object Identifiers

Recall that each LDAP object class or attribute type must be assigned a unique name and OID. One of the biggest stumbling blocks faced by people new to LDAP directories is how to obtain OIDs for the new attribute types and object classes they want to define. Simply put, OIDs can be obtained from anyone who has one. In fact, one OID is sufficient to meet all your schema needs; you can simply add another level of hierarchy to create new branches, or OID arcs , for your attributes and object classes. An OID arc is an OID that has been reserved for use as a container for defining additional OIDs. The process of assigning an arc of the OID space to another party is called delegation .

As already mentioned, an OID can be obtained from anyone who has one; that person just needs to delegate it to you as an arc and record this fact so that he does not use the OID for any other purpose. The Internet Assigned Numbers Authority (IANA) gives out OIDs to any organization that asks. IANA calls the OIDs enterprise numbers because it gives them out primarily for use with Simple Network Management Protocol (SNMP). The IANA OIDs work fine for LDAP as well because any one OID is as good as another. A form for obtaining an OID from IANA can be accessed on the World Wide Web at http://www.isi.edu/cgi-bin/iana/enterprise.pl.

Other organizations known to give out OIDs are the American National Standards Institute (ANSI) for U.S. organizations and the British Standards Institution (BSI) for U.K. organizations. General information on OIDs maintained by a gentleman named Harald Alvestrand can be accessed at http://www.alvestrand.no/objectid.

As an example of obtaining and assigning OIDs, consider the University of Michigan (U-M) directory services team, which contacted IANA to obtain an OID arc (1.3.6.1.4.1.250) for its own use. The team then created the OID arcs shown in Table 8.6 for use in defining its own directory schema. The team assigned the OID 1.3.6.1.4.1.250.1.1 to the first attribute type it defined, 1.3.6.1.4.1.250.1.2 to the second, and so on.

Tip

After you obtain an OID, you should maintain a registry similar to Table 8.6 to ensure that no OID is ever used for more than one purpose (the registry can just be a text file, perhaps maintained by a revision control system). You should then publish the list of OIDs with your schemas (more on this topic later). Although it may seem unimportant to establish an OID registry when you're just getting started, you will want to have one because the number of attributes and object classes that you or others in your organization create may be quite large in the end.


Table 8.6. University of Michigan OID Schema Arcs

OID Arcs

Description

Owner/Contact

1.3.6.1.4.1.250.1

U-M defined attribute types

U-M directory service team

1.3.6.1.4.1.250.2

U-M defined attribute syntaxes

U-M directory service team

1.3.6.1.4.1.250.3

U-M defined object classes

U-M directory service team

Modifying Existing Schema Elements

It may be tempting just to alter some predefined schema elements to meet your needs, perhaps by adding a new attribute to a predefined object class. At first glance, this seems like a reasonable thing to do, but it isn't. Do not modify existing schema elements! Changing existing schemas will break some directory servers and clients , and it will probably lead to a lot of confusion. If the person object class that everyone knows about is different within each directory service deployment, chaos will rule.

Also be careful when completely deleting object classes or attributes from any of your directory server software's preinstalled schemas. It's OK to do this as long as you're sure that the schema is not used internally by any of the directory service software. However, you may run into trouble when you upgrade your software because the upgrade process may require that all the vendor's schemas be present. In general, there is no reason to remove schema elements even if you do not plan to use them; there is little or no penalty associated with leaving the schema elements installed.

Subclassing an Existing Object Class

It is fairly common to extend, or subclass , an existing, predefined object class to add new attribute types to it. To do this, define a new object class that is a subclass of the existing one by indicating in the definition of the new class that the existing class is its superior . You also need to define the new attribute types and include them in the new object class as required or as optional attributes.

When you subclass an existing object class in this way, the new class should generally be used to represent the same type of object as the class from which it was derived. For example, you might create a new subclass of a printer object class called hpPrinter that allows additional attributes specific to Hewlett-Packard printers. The hpPrinter class is still used to represent printers; it just holds more information.

Also the new object class should be the same kind as the class from which it is derived. For example, if you are subclassing a structural object class, the new class should also be a structural class. Note that in some directory service implementations, such as Netscape's, little or no distinction is made between different kinds of object classes during schema checking, so this may not be something you have to worry too much about initially.

As another example of subclassing an existing object class, suppose that the Example Corporation is developing a directory-enabled application called the Birthday Notification Service (to which managers will subscribe so that they remember to take each employee out to lunch on his or her birthday). The designers of the Example directory might define a new attribute to hold the day and month a person was born. The attribute type definition might look like this:

 (  bday-OID  NAME 'exampleBirthday' DESC 'birthday day-month' EQUALITY caseIgnoreMatch SUBSTR  caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) 

Note that bday-OID would need to be replaced by a real OID assigned by the Example directory administrators. An extension of the inetOrgPerson class that allows the new exampleBirthday attribute to be included in entries could be defined as shown in Listing 8.17.

Listing 8.17 The examplePerson Object Class
 (  examplePersonOID  NAME 'examplePerson' DESC 'Example Corporation extended person' SUP inetOrgPerson  STRUCTURAL MAY exampleBirthday ) 

Note that examplePersonOID should be replaced by a real OID assigned by the directory administrators. The examplePerson class would be used whenever a user entry was created inside Example Corporation. The following is a sample entry:

 dn: uid=jcarter,ou=People,dc=example,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson objectclass: examplePerson cn: John Carter sn: Carter uid: jcarter userPassword: secret exampleBirthday: 29-February 

Now we all know why John claims to be so much younger than he looks; he must be counting birthdays instead of elapsed time!

Note

In the LDIF just shown, values for all the superior object classes ( top , person , organizationalPerson , and inetOrgPerson ) are explicitly shown in the entry's objectClass attribute. This is how an entry will look when you retrieve it from an LDAP server. When you add or modify an entry, however, you should need to provide only the most specific superior object class value (for example, inetOrgPerson ). On the other hand, some LDAP server implementations do require all of the superior object class values to be listed, so it is safest always to do so.


Adding Auxiliary Information to a Directory Object

Sometimes it is preferable to create an auxiliary object class that allows attributes to be added to any type of LDAP entry, regardless of the kind of real-world object it represents. A class like this is sometimes called a mix-in class because it allows additional attributes to be "mixed into" an existing class. A mix-in class may be added to a wide range of entry types ”a much simpler approach than creating a subclass for each object class in which you want to allow the new attributes to appear.

To create an auxiliary object class, simply define a new class that is not subclassed from any existing object class (it should have the special class top as its superior). Typically, all the attributes in the auxiliary class should be optional rather than mandatory. That way, the auxiliary object class itself can be associated with an entry regardless of whether any values for its attributes are present. As a result, the burden on directory clients is reduced because they do not have to worry about removing the object class value itself when the auxiliary attributes are removed.

Listing 8.18 shows an example of a useful auxiliary object class. This class can be added to any LDAP entry to allow a dc (domain component) attribute value to be included in the entry.

Listing 8.18 The dcObject Auxiliary Object Class
 ( 1.3.6.1.4.1.1466.344 NAME 'dcObject' SUP top AUXILIARY MUST dc ) 

The following is an example of an organization entry that also contains domain components :

 dn: o=Example Inc.,c=US objectclass: top objectclass: organization objectclass: dcObject o: Example Inc. dc: example 

As another example of an auxiliary object class, suppose that you develop a directory-enabled application that keeps track of your organization's network- related inventory by storing information in the following custom attribute types:

 (  OID  NAME 'inventoryID' DESC 'numeric inventory ID' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.  1466.115.121.1.27 SINGLE-VALUE ) (  OID  NAME 'inventoryDatePlacedInService' DESC 'date item was placed into service' EQUALITY  generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.  121.1.24 SINGLE-VALUE ) (  OID  NAME 'inventoryContactPerson' DESC 'pointer to entry of the person responsible for item'  EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) (  OID  NAME 'inventoryComments' DESC 'comments related to inventory status' EQUALITY  caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) 

All the instances of OID would, of course, need to be replaced with real object identifiers you assign. Because you want to mix these attributes into several different types of entries (printers, hosts , and so on), you could handle your schema needs by defining an auxiliary object class such as the inventoryItem class shown in Listing 8.19.

Listing 8.19 The inventoryItem Auxiliary Object Class
 ( OID NAME 'inventoryItem' DESC 'auxiliary object class to hold inventory information'  SUP top AUXILIARY MUST inventoryID MAY ( inventoryDatePlacedInService $  inventoryContactPerson $ inventoryComments ) ) 

Here is a sample printer entry that has inventory information attached to it:

 dn: cn=2nd floor HP LaserJet 8150dn,ou=printers,dc=example,dc=com objectclass: top objectclass: printer objectclass: inventoryItem cn: 2nd floor HP LaserJet 8150dn pagesPerMinute: 32 inventoryID: 129055581 inventoryDatePlacedInService: 20011201000000Z inventoryContactPerson: uid=bjensen,ou=people,dc=example,dc=com inventoryComments: on loan to the art department 

Accommodating New Types of Objects

If you cannot find a predefined object class that is similar to the type of object you need to represent in your directory service, simply define a new structural class to hold whatever attributes are appropriate. This task is similar to creating a new auxiliary class, except that the structural class can stand on its own as the primary object class for an entry.

For example, if our friends at the Example Corporation plan to use their directory to track company-owned and -operated telephone sets, they might reuse some predefined attributes but create a new object class such as the one shown in Listing 8.20.

Listing 8.20 The exampleTelephone Object Class
 (  OID  NAME 'exampleTelephone' DESC 'Example Corporation telephone' SUP top STRUCTURAL MAY ( cn  $ telephoneNumber $ owner $ L ) ) 

Here is a sample entry:

 dn: cn=Mark Smith's phone,ou=phones,dc=example,dc=com objectclass: top objectclass: exampleTelephone cn: Mark Smith's phone telephoneNumber: 3477 owner: uid=bkady,ou=people,dc=example,dc=com L: security office 

Note that when you create an object class for an entirely new kind of object, you will need to put some thought into which attribute will most likely be used to form the RDNs of entries that belong to the class. For most object classes, the cn (common name) attribute is a good, generic choice.

In the exampleTelephone object class we just looked at, the telephone number itself might actually be a better choice for naming phone entries simply because it is more likely to be unique. The sample entry we just used might instead be defined like this:

 dn: telephoneNumber=3477,ou=phones,dc=example,dc=com objectclass: top objectclass: exampleTelephone cn: Mark Smith's phone telephoneNumber: 3477 owner: uid=bkady,ou=people,dc=example,dc=com L: security office 

The only difference is in the RDN (the first part of the DN), which uses the telephoneNumber attribute instead of cn to name the entry. See Chapter 9, Namespace Design, for more information on entry naming.

Tips for Defining New Schemas

Defining a good schema is as much art as science, and the more you do it, the easier the process becomes. The following are some tips that will help you produce better results:

  • Reuse existing elements as much as possible. Even if you need to define a new object class, you may find that many of the attributes you need already exist. When you reuse existing elements, make sure that the meaning and expected use is the same; otherwise , directory applications and users may be confused . For example, suppose that an attribute called drink has been defined that stores the name of a person's favorite beverage. Do not try to reuse the drink attribute with intended values of yes or no to indicate whether a person consumes alcohol. If you need to store a data value for that purpose, define a new attribute such as drinksAlcohol .

  • Define several smaller auxiliary object classes to mix needed attributes into existing objects. The alternative is to subclass many object classes, and this subclassing typically requires more new classes to be defined. By providing a general solution in an auxiliary class, you will make your schema simpler and easier to understand.

  • Minimize the number of mandatory attribute types within your object classes. If you're thinking of making an attribute required, proceed with caution. In our experience, required attributes inevitably get in the way at some point. Even the cn and sn attributes, which are required by the standard person class, can be a burden if, for example, a user needs to appear in the directory to get access to various systems but wants her name to remain private.

  • Do not define more than one object class or attribute type to hold the same kind of information. To maintain consistency in your schema, and thus in your directory service, strive to use a single schema element for a given purpose. For example, the following three attributes should likely all be consolidated into one:

     dateOfBirth birthDate birthDay 
  • When in doubt, keep it simple. Remember that the goal of a collection of schemas is to provide a framework for your data elements that is easily understandable and usable by directory applications, administrators, and users. The more complicated the schemas that you define are, the less approachable your directory service will be.

   


Understanding and Deploying LDAP Directory Services
Understanding and Deploying LDAP Directory Services (2nd Edition)
ISBN: 0672323168
EAN: 2147483647
Year: 2002
Pages: 242

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net