Novell is now a part of Micro Focus

Designing NDS Schema Extensions

Articles and Tips: article

NANCY MCLAIN
Senior Technical Writer
Developer Information

STEVEN S. MCLAIN
Senior Software Engineer
NDS Development

01 Jul 1999


Describes some basic design principles to consider when you are extending the NDS schema. Designing your schema extension around some basic design principles helps ensure that your schema extensions are efficient and don't cause unnecessary repositories of the same information in the database. Also explains some of the basic concepts and vocabulary used to describe the NDS schema.

Introduction

This Developer Note describes some basic design principles to consider when you are extending the NDS schema.

NDS is a Directory Service that allows you to easily manage your network resources. Simply put, the NDS Directory is a globally accessible, distributed database of objects that represent network resources, such as network users, servers, printers, print queues, and applications. This database is extensible, which means that you can customize the NDS base schema so that the resulting database suits the particular needs of your company or your applications. Designing your schema extensions around some basic design principles helps ensure that your schema extensions are efficient and don't cause unnecessary repositories of the same data in the database.

In order to talk about the design principles involved in creating schema extensions, you must first understand the basic concepts and vocabulary used when we talk about the NDS schema.

What is the NDS Schema?

The NDS schema regulates the structure of the NDS tree. The schema contains the rules that define how the NDS tree is structured and how the NDS objects, attributes and attribute values are defined. The schema governs the

  • Tree's object types

  • Object's containment

  • Object's required attributes

  • Object's optional attributes

  • Object's inherited attributes

  • Attribute syntax

  • Object's naming

The schema also dictates the rules for adding, deleting, and managing objects and information about objects.

The NDS schema is extensible, which means you can add to the types of objects and attributes that NDS maintains.

What Are the Schema Components?

The NDS schema consists of two basic components:

  • Object Classes

  • Attributes

What Are Object Classes?

An object class is the set of rules that controls the creation of particular objects. Each object class is defined in terms of attributes, or specific pieces of information that describe the object. For example, the NDS schema contains an object class for users, called User. This User object class defines many attributes, such as the user's name, telephone number, address, and group memberships. An object is a specific instance of an object class.

You can extend the schema by defining new object classes.

What Are Attributes?

Attributes hold a piece of information that describes an object. This information is the attribute value. Attribute values can be multi-valued. That is, you can assign more than one value to a single attribute. For example, a User object can have two values for its Common Name (CN) attribute. My user object might have both "nmclain" and "Nancy McLain" as values for its CN attribute.

Administrators and applications define values for the attributes. The schema defines mandatory and optional attributes for every object class:

  • If an attribute is mandatory, administrators or applications must assign a value to the attribute before they can create an instance of the object.

  • If an attribute is optional, administrators or applications don't need to assign a value to create an instance of the object. However, if an optional naming attribute is the object's only naming attribute, the administrator or application must assign a value to the attribute before they can create the object. Objects must have a name before you can create them.

You can extend the schema by defining new attributes. However, once you create an attribute you can't modify it. And, you can only remove attributes from the schema if they aren't part of Novell's base schema and if they aren't assigned to a class.

Attributes are defined by attribute syntaxes and attribute constraints.

Attribute Syntaxes. Each attribute is assigned an attribute syntax that defines the attribute value's data format. For example, attribute syntaxes determine whether an attribute stores an integer, string, or stream data. The syntax also defines the matching rules that control the type of compare operations you can perform on the attribute value.

You can't extend the schema by creating new attribute syntaxes. You must select your attribute's syntax from the set of predefined attribute syntaxes. This means that you can't assign a new data type or create an attribute that requires a data type not already defined by the NDS schema.

Attribute Constraints. Attribute constraints are flags containing restrictions that affect an attribute value. They can also impose constraints on NDS and NDS client operations. Attributes constraints specify whether the attribute

  • Allows only a single value or multiple values.

  • Has a range or size limit to the value.

  • Is synchronized immediately, at the next scheduled interval, or never.

  • Is hidden or viewable.

  • Is writeable or read-only.

Note: You can't extend the schema by creating new attribute constraint flags.

NDS objects can inherit attributes from other objects that contain them in the NDS tree. To design good schema extensions, you must understand schema inheritance.

Schema Inheritance

The NDS schema depends upon class hierarchy and inheritance to pass attributes and other characteristics to defined objects. Classes that pass characteristics to other classes are called super classes. Super classes create the hierarchy of the schema. Allowing classes to inherit characteristics from super classes means that a number of characteristics are defined only once and then used by multiple classes.

The schema inheritance starts with the "Top" class. All NDS schema classes inherit characteristics from the Top class. Top passes one mandatory attribute to all the other classes: Object Class. This means that all NDS objects must include an Object Class attribute. In addition, Top passes several optional attributes to all NDS objects such as: ACL, Back Links Last Referenced Time, Obituary, Used By, as well as others. Basically, all objects inherit from Top the ability to hold values that NDS needs to be able to authenticate and synchronize the object.

In addition, Top also defines a default ACL (Access Control List) template that all objects inherit. An ACL defines the access rights objects have to each other. The default ACL provides only enough access rights to allow objects to be supervised by the object that created them. When you define an object, you can either use the default ACL it inherits from the Top class, or modify the ACL.

For inheritance purposes, the NDS schema defines two basic types of classes:

  • non-effective

  • effective

You can create objects only from effective classes. Non-effective classes exist to provide inheritance. You can create other classes from non-effective classes. For example, Figure 1 shows the inheritance of the Printer class.

Figure 1: The inheritance of the Printer class.

The Top class is at the top of the inheritance hierarchy, and it passes several characteristics to the Device class.

Note: Although the Top class is an effective class, it is the one exception in the schema effective classes in that you cannot create objects directly from the Top class.

The Device class is a non-effective class, so you cannot create objects directly from it. In addition to the attributes it inherits from Top, the Device class has several optional attributes that pertain to devices. You can derive other classes from a non-effective class, so the Printer class is derived from the Device class. In addition to the attributes it inherits from the Top and Device classes, the Printer class has several optional attributes that pertain specifically to printers. The Printer class is an effective class, so you can use it to create printer objects.

NDS 8 includes a third type of class, called auxiliary class. With the auxiliary class, you can create a class definition, label it as auxiliary, and assign that class to a sub-set of objects. For example, suppose you want some of your users, but not all, to have certain rights to a database. You can create new attributes to give the rights to these users. However, if you assign this attribute to the User object class, all of your User objects will get the attribute.

To solve this, you can create an auxiliary User object class called "Database Users". The Database Users class contains all of the attributes necessary to let the users access the database. You can then associate the Database User auxiliary class with the particular User objects that you select, creating a subset of database users. If in the future, you want to prevent certain users from using the database, you can remove the association with the Database User auxiliary class, thus removing the attributes that allow them to access the database. You can also assign the Database User auxiliary class to additional user objects.

The NDS schema also defines an object's containment. Containment helps to regulate an object's rights through inheritance and restricts its possible location in the NDS tree.

NDS Containment

An object's class definition includes information about its containment and its naming.

NDS has two types of objects:

  • container objects

  • leaf objects.

Objects that can contain other objects are called container objects. Container objects are building blocks of the NDS tree. Container objects are Locality, Country, Organization and Organizational Unit. Objects that cannot contain other objects are called leaf objects. Leaf objects comprise the actual network resources such as users, servers, or printers.

Figure 2 shows a typical NDS tree with appropriate object types.

Figure 2: Very Small Company's NDS Tree.

In Figure 2, Very Small Company's NDS tree is typical because it doesn't include Country and Locality container objects. The first object off [Root] is an Organization (O) container object. Organization contains three Organizational Unit (OU) objects: Accounting, Engineering, and Marketing. Each of those Organizational Unit objects contains other Organizational Unit objects or leaf objects.

The NDS schema documentation defines the rules that regulate object containment, or what type of container object a specific object can be contained by. For example, the schema dictates that Organization and Organizational Unit objects can contain either Organizational Unit or Leaf objects. Neither object can contain an Organization object. Each class definition defines what type of container can contain it. NDS 8 adds an additional container class, called domain. This class provides LDAP-compatibility.

Defining the types of container that can hold an object restricts its placement in the NDS tree. For example, because Organizational Unit objects cannot hold an Organization object, you will find all Organization objects higher in the NDS tree.

This hierarchy can organize objects in the database to reflect a company's organization and, thus, make network resources easier to find. It also allows NDS to use inheritance to regulate network rights. NDS uses inheritance to determine an object's rights. This inheritance is different from the schema inheritance because instead of passing on attributes through object classes, it passes rights through containment.

You can extend the schema by creating new object class and new attribute definitions. These are called schema extensions.

Why Extend the Schema?

You can customize the NDS database to suit your application's needs. Customizing the database is simply a matter of extending the NDS schema so that it holds additional objects and attributes. For example, you can add an attribute to the user class that would hold a user's photograph. Or, you could add an attribute to the user class that would hold a cell phone number.

Your application could then track these attributes and use them. It could also restrict access to these attributes so that only those objects that had a need to use these objects could access them. Keep in mind that if you add an attribute to an object in the base schema, you will not be able to delete that attribute. The only way to delete attributes added to pre-defined classes is to reinstall the NDS tree.

You can't associate an attribute with an object unless the attribute is listed among that object's mandatory or optional attributes in its class definition. For example, you can't add an attribute that holds a cell phone number to a specific User object. You must add that attribute to the User class, then all User objects could have a cell phone number associated with them. If your situation required it, you could create another User class, perhaps called the Cell Phone User class, which had the cell phone number attribute associated with it. Then, only those User objects created from this class could have a cell phone number associated with them.

Note: Even though this makes an easy example that illustrates a reason to extend the schema, it creates some problems. For example, you would not be able to use standard administrative and database tools with your Cell Phone User objects. You would have to provide your own tools. However, NDS 8 provides Auxiliary classes that help you modify objects and still use NWADMIN and ConsoleOne to administer those objects as though they were base schema classes. NDS 8 also provides generic methods that help you edit attributes and classes you've created to extend the schema.

If you must associate an attribute with an object and the object class does not specify that attribute, you must extend the schema by either:

  • Adding the new attribute to the class as an optional attribute.

  • Defining a new class that inherits from the original class and adds the new attribute as an optional attribute.

Because you can extend the NDS schema, it's easy to allow an application to store customized data in the NDS database. This allows independent software vendors (ISVs) and customers to integrate new services into NDS simply by extending the schema and adding new objects. For example, you could write an application that provides fax service functions simply by adding a fax server object class definition into the NDS tree.

There are some trade-offs to extending the schema, so when you consider extending the schema, keep in mind the following advantages and disadvantages.

Advantages of extending the schema:

  • You can represent your new network resource accurately in the NDS tree.

  • Users can build database search queries to easily locate objects of a custom class.

  • You can use standard NDS access control mechanisms (ACLs) to govern access to custom objects.

  • You can match the categories of information an object stores to the needs of a custom resource.

Disadvantages of extending the schema:

  • Only objects with Supervisor rights to the NDS tree Root can extend the schema. Since schema definitions are global to the entire tree, someone with Supervisor rights at the Root must run the installation utility that extends the schema.

    For this reason, Novell recommends that the portion of the installation utility that extends the schema be separate from the main installation utility. This allows users with Supervisor rights at the Root to run a very simple installation utility to extend the schema and a user with Supervisor rights to the appropriate container to run the main installation utility.

  • You cannot remove extensions made to the base schema without reinstalling the NDS tree.

The following general design principles will guide you in creating efficient schema extensions.

Designing Good Schema Extensions

Extending the schema is fairly simple. Designing your schema extension following some basic design guidelines makes it even simpler. The basic principles involved in designing schema extensions are to

  1. Determine the exact purpose of your custom object class or attribute

  2. Determine whether you should extend the schema

  3. Derive your new class from an existing base class, if possible

  4. Derive an appropriate new class definition, if possible, or inherit from Top. Consider the object's:

    • Naming attributes

    • Containment

    • Class flags

    • Default ACL Template

    • Mandatory and optional attributes

  5. Determine whether the attributes you need exist in the base schema

  6. Derive an appropriate new attribute. Consider the attribute's:

    • Name

    • Syntax

    • Constraints

  7. Register your schema extension

Using these principles to design your schema extension involves understanding the issues surrounding each principle. Understanding these issues helps simplify the decisions you must make when you design your schema attribute.

Determining the Exact Purpose of Your Custom Object Class or Attribute

As with any good software design, knowing some basic information about your object before you create it simplifies the design of your schema extension. You should know the specific purpose of your schema extension and how other applications will use it because this information influences the decisions you make about the following:

  • What other objects must access your object or attribute

  • Where in the NDS tree your object could be located

  • How your object will be named

  • What security your object or attribute requires

  • How you want to administer your object

  • What information your object must hold

  • What information your object might hold

  • What is the data-type of the object's information

  • What are the constraints on that information.

One of the benefits of carefully thinking through your object and its data is that you'll be able to limit the number of locations where the same data is stored. For example in NDS, the volume object doesn't contain the network address of the server it exists on. The volume object has an attribute that holds its host server object's DN. The server's object contains the server's network address in its Network Address attribute.

Accessing the volume is a matter of a few steps:

  1. Obtain the host server's DN from an attribute on the volume's object.

  2. Use the server's DN to locate the server's object.

  3. Obtain the server's network address from an attribute on the server's object.

  4. Connect to the server.

While it might seem more efficient to simply get the server's network address from the volume's object, it creates a lot of maintenance for the network administrator. Every time the server's network address changes, the administrator must then change that address on every object that contains it. However, if an attribute is holding the server's distinguished name, and that attribute is using the correct syntax, NDS will maintain any change to the server's distinguished name. This means no overhead for the network administrator, and it allows the server's network address to change without impacting any applications. Careful planning of an object's purpose and use will reveal other opportunities to provide indirection to protect against changing data such as network addresses.

Determining Whether You Must Extend the Schema

Review the existing base classes in the NDS schema to determine if one of them suits the resource that your object represents. A base class is a class that is predefined in Novell's shipping schema. If you can find an existing base class definition that suits your resource, your product installation will be much simpler and you won't have to provide your own administration utility or a ConsoleOne or NWADMIN Snap-in to administer the object.

Be careful not to accidentally create a class that is similar to a predefined class in the tree. If you find a class that is similar, but not exactly what you need, you can always derive a custom class from the original class. This avoids cluttering the schema with extraneous classes.

Deriving Your New Class from an Existing Base Class, if Possible, or from Top

If no base schema class exists that exactly suits your needs, determine whether one of the base class definitions has most of the attributes to accurately represent your object. Base classes that you use to derive new classes from are called super classes. Look for a class that already encompasses most or all of the attribute definitions that accurately represent your new object. If you find a class definition that accurately represents your object, determine if the class is effective or non-effective.

If the class is effective, you can choose one of two actions, depending upon what is best for your custom class:

  • Add your own custom attribute definitions to this effective class.

  • Derive your own custom object class from this base class and add your own custom attributes to it.

For example, if you wanted to add a cell phone number to a User object, you could either add a custom attribute that would hold a cell phone number to the User object base class, or you could derive a new User class, Cell Phone User, from the User base class. You would then add the cell phone number attribute to the cell phone User class. The method you choose depends upon the purpose of the custom object, the way the application will be using the custom object, and the way you plan on administering the object. For example, if you must have a group of users with cell phones that you must treat as a special case, you might want to have a Cell Phone User class. Keep in mind that if you create a special class, you must also provide the tools that use this class. NWADMIN can't help administrators manage the new class, and ConsoleOne only provides generic methods to help manage the new class.

If you derive a new class from an existing super class, you can inherit from that class. For example, the Printer class represents a type of Device. As Figure 1 shows, the Printer class is derived from the super class Device and inherits all the attributes that Device has inherited. It must have all the mandatory attributes that Device has inherited and defines. It inherits a selected sub-set of the optional attributes that the Device class includes. In addition, it adds a few new optional attributes specifically for printers.

Like the Printer class, your new object class can inherit from an appropriate super class. It then inherits all of the super class's mandatory attributes, and a subset of optional attributes that you select. You can add additional mandatory and optional attributes to your class.

If you find a class that accurately represents your object, but the class is non-effective, you must derive your object class from the base schema class and define your new class as effective. You can then create your object from your new class. For example, suppose you must create a Fax Server object. The base schema does not include a Fax Server class. But, it does include a non-effective Server class. The Server class contains many attributes relevant to any type of server. So, you can use the Server class to derive your custom Fax Server class. Define this class as effective, and add attributes that are relevant specifically to fax servers, or create new attributes for your class. You can then create Fax Server objects from the Fax Server class. Again, keep in mind that standard tools will not recognize your new class. You must provide the tools.

If you don't find an existing super class that accurately represents your object, you can derive a new class from Top. Your new class then inherits a basic set of mandatory and optional attributes from Top.

When you derive your new class, you must also consider:

  • The object's naming attributes

  • The object's containment.

  • The class flags your object class requires

  • Any mandatory and optional attributes your object class requires in addition to those it inherits

  • Additional default ACL templates

The Object's Naming Attributes. An object's naming attributes are the attributes that contain its name. Objects are identified by their own names and the names of their container objects. An object's class definition identifies the attributes, which can give an object its name. By convention, leaf objects are named by their CN attribute.

Naming attributes are passed to object classes through inheritance. Classes inherit naming attributes from the closest super class that designates the naming attributes. For example, the Organizational Person object class designates the CN attribute and the Organizational Unit Name attribute as the naming attributes for the classes derived from it. The User object class inherits those naming attributes from Organizational Person. The Printer class inherits the CN attribute as its naming attribute from the Device object class.

Keep in mind that if you specify any naming attributes in your class definition, you'll override all inherited naming attributes and not inherit any. If you specify any naming attributes in a class definition, you must then specify all the naming attributes.

Some object classes have more than one naming attribute. This means that its object name could be either one or both of the values in the naming attributes. If you put values in all of the naming attributes when you create the object, you must always use the combined values in all of the naming attributes to refer to that object. Combining the values held by both naming attributes makes the name more unique and differentiates it from a different object of the same type that could have an identical value for one of the naming attributes.

For example, its CN and its Organizational Unit Name attributes can name a User object. Figure 2 shows several user objects that could have jjones as a value for the CN attribute: Julia Jones, Jake Jones and Judy Jones. As I mentioned, Julia Jones' and either Jake Jones' or Judy Jones' User objects can both legitimately have the CN jjones because the names given by their naming attributes would be unique. The reason is that User objects can be named by both their CN attribute, jjones in this case, and their Organizational Unit Name attribute. That means that Julia Jones' object's name could be jjones+Development, and the other jjones User object's name could be jjones+AccountsPayable. Thus, both object names are unique.

Because their context is identical, Jake Jones and Judy Jones must somehow have different values in one of their naming attributes so that their object names can also be unique.

When deciding which attributes will give the object its name, consider the likelihood that objects created from your class will always have a unique name. For example, administrators commonly put similar objects in the same container. So, more than one of your custom objects could easily be placed in the same container and applications creating the objects could be naming all objects identically. So, include enough naming attributes that the object name is descriptive, and few enough attributes that a user can easily refer to the object.

You can designate any attribute that uses any string syntax, except for Octet string, as a naming attribute. An object's Relative DN can only contain 128 characters. Its Full DN is limited to 256 characters. Consider these limitations when you choose your naming attributes.

The Object's Containment. An object class's containment list specifies where an object of that class can be located in the NDS tree. Each object class defines a containment list. An object can only be contained by the container objects listed in its class's containment list. For example, a User object can be contained by Organization and Organizational Unit objects. Organization objects can only be contained by Top, Country, Locality, and Tree Root objects. They cannot be contained by other Organization objects or by Organizational Unit objects.

Object classes inherit their containment lists from their super classes. If you're deriving your class from Top, your class won't inherit a containment list. When you decide what types of objects can contain your object, keep in mind that it is a good idea to locate objects close to the other objects that use them. For this reason, you usually don't find such resources as printers located under the Tree Root object. Unless there's a good reason to place your object directly under the root or under a Locality, Top, Country, or Tree Root object, consider placing the Organization and Organizational Unit objects in your containment list. Because NDS 8's new Domain container class is on the same tree level as the Organization and Organizational Unit objects, you might also contain the Domain container in the containment list. This restricts your object to a place in the NDS tree that is close to other network resources. It also makes it easier for users to find and access the object.

Some objects, however, could belong in the upper hierarchies of the NDS tree. For example, container objects that contain database tables, or container objects that contain routers and board objects for the network's WAN links might belong under the Tree Root object.

You can also create classes for object containers. You can restrict new objects you might create to the containment of your new class. For example, you might need to have database objects that you want to contain in a database container. You could define a new containment object class called Database. You could then create a class for database objects. You could restrict the database objects so that they are only contained in a database container by placing Database in the class's containment list.

When you create your classes, make certain you create them in order of their dependency. In other words, create the classes your object will be contained by or inheirt from before you create your dependent definitions. You can't change a class's super classes or containment rules once you've created its definition.

Another thing to remember is that an object's containment determines its ACLs. Consider what rights your object requires when you determine its containment.

The Object's Class Flags. Object Class Flags define the operations NDS allows on the object class. When you create the object, you can set these flags.


Flag

Description

Container Flag

Indicates whether the object can contain other objects.

Turn the flag ON for those object classes that are designated as container classes.

Effective Flag

Indicates whether an object class is effective or non-effective. Effective classes must inherit or define a set of naming attributes and containment classes.

Turn the flag ON for effective classes, or those classes that can be used both to provide definition and to create objects.

Auxiliary Flag

Indicates whether an object class is an auxiliary class. When this flag is set, NDS ignores the container and effective class flags.

Turn the flag ON for auxiliary classes.

Non-removable Flag

Indicates whether the object class can be removed from the schema.

Turn the flag ON for objects that can't be removed.

All operational schema object classes are flagged non-removable. Object classes added to extend the schema are the only classes that don't have the non-removable flag turned ON.

In NDS 8, you can turn this flag ON. In previous NDS versions, this flag was reserved for NDS.

NDS controls the rest of the object class flags. These flags are:


Flag

Description

Ambiguous Container Flag

Indicates whether the object class has clearly defined containment classes. As a general rule, non-effective classes can be created with ambiguous containment, but effective classes must have non-ambiguous containment. Ambiguous containment occurs when an object inherits non-identical containment classes from different super classes.

In the base schema this flag is turned ON for object classes Top, Alias, Person, and Partition.

Ambiguous Naming Flag

Indicates whether the object class has clearly defined naming attributes. As a general rule, non-effective classes can be created with ambiguous naming, but effective classes must have non-ambiguous naming attributes. Ambiguous naming occurs when an object inherits non-indentical naming attributes from different super classes.

In the base schema this flag is turned ON for object classes Top, Alias, Person, and Partition.

Operational Flag

Indicates that NDS requires this object class to exist.

This flag is turned ON for object classes that NDS must have in order to operate correctly.

The Object's Mandatory and Optional Attributes. Object classes have attributes associated with them. These attributes hold information that defines the object. If you have derived your object class from an existing class, your class inherits a set of mandatory and optional attributes. Mandatory attributes must have values assigned to them when the object is created. Optional attributes don't require a value. They can also have values assigned to them later. If you are deriving an object class, you must determine:

  • Any inherited optional attributes you want to designate as mandatory

  • Any additional optional attributes you want to include

  • Any additional mandatory attributes you want to include.

Sometimes, the attributes you want to add to an existing class, or to your new class don't exist in the schema. In this case, you must define new attributes.

The Object's Default ACL Templates. All object classes inherit a default ACL template from Top. This ACL template provides a minimum amount of security. It gives all objects the rights to supervise any objects they create. This ensures that every object added to the NDS tree has a supervisor.

In addition to the default ACL template they inherit from Top, object classes inherit any default ACL templates that are defined for any of their super classes. For example, the NCP Server object inherits default ACL templates from Top and Server, and then defines one for itself.

When you extend the schema, you can't create a template that overwrites or adds to the templates in the base schema. However, when an object is created, the creation process can set the object's ACLs to any value, including one that changes a value that comes from a default ACL template.

Determining Whether the Attributes You Need Exist in the Base Schema

Review the schema's pre-defined attributes to determine if appropriate attributes exist for your object. Keep in mind that if you add an attribute to the NDS schema and assign that attribute to one of the schema base classes, you cannot delete that attribute unless you reinstall your NDS tree. So, you want to be sure that you add only necessary attributes that you probably won't want to delete later. If a pre-defined attribute exists that holds your custom information, you won't have extraneous attributes in the schema that you can't delete later.

If you add your attributes to any classes you have created to extend the schema, you must remove your classes that are using the new attributes before you can delete the new attributes.

Deriving an Appropriate New Attribute

If you can't find a pre-defined attribute that accurately describes your information, you can create a new one. You can create a new attribute by:

  • Giving the attribute a name that appropriately describes the type of information it will hold

  • Assigning it an attribute syntax

  • Selecting the appropriate attribute constraints

Naming Your Attribute. You really only have two things to consider when you name your attribute:

  • Make sure your attribute accurately describes your information. This makes selecting the correct attribute easy.

  • Keep attribute names short and easily typed. For example, the Common Name attribute is named "CN" so that 11 characters aren't wasted that could be used in the Full DN.

Selecting an Attribute Syntax. Every attribute must have a syntax assigned to it. The syntax defines the attribute's data format. The data format depends upon the type and purpose of the information in the attribute. For example:

  • If your custom attribute will hold a distinguished name, choose the DN syntax.

  • If it holds a boolean, choose the Boolean syntax.

  • If your data size is larger than 63K Bytes, you must use the Stream syntax.

The following tables summarize the attribute syntaxes you can choose from. These tables show only enough information to help you select the syntax you need. For more detailed information about using the syntax, see the NDS schema documentation that came with the NDK, or view it at: www.developer.novell.com.

Name Syntaxes. NDS automatically maintains the distinguished name in attribute values that use any of these syntaxes. This is a main reason why you wouldn't want to choose an Octet String syntax for a value that contains a DN. NDS wouldn't maintain the name, and if the object's context changed, your application would have to be responsible for relocating the object and changing its distinguished name. If your data names or helps to locate an object, you should choose one of these syntaxes.


Name

Description

Class Name

Attributes whose values represent object class names.

Distinguished Name

Attributes whose values are the names of objects in the Directory tree

Typed Name

Attributes whose values represent a level and an interval associated with an object.

This syntax names an NDS object and attaches two numeric values to it:

The level of the attribute indicates the priority.

The interval indicates the frequency of reference.

The level and interval values are 32-bit numbers and aren't interpreted by NDS. The application must interpret them.

Path

Attributes whose values are a UINT32, unicode string, and a distinguished name. These values are often used to represent a volume and file system path.

Object ACLs

Attributes whose values represent ACL entries. An object ACL value can protect either an object or an attribute. The protected object is always the one that contains the ACL attribute.

Hold

Attributes whose values represent an object name/level pair. This syntax is an accounting quantity, which is an amount tentatively held against a subject's credit limit, pending completion of a transaction.

NDS treats the Hold amount similarly to the Counter syntax, with new values added to or subtracted from the base total. If the evaluated Hold amount goes to 0 (zero), the Hold record is deleted.

Back Link

Attributes that are a UINT32 and a DN. NDS uses the Back Link syntax for Back Link attributes, which NDS uses for its internal management.

Character String Syntax. If your data will be a character string, you could choose one of these syntaxes:


Name

Description

Case Exact String

Attributes whose values are strings, and you want to consider upper and lower cases when they're compared. For example, the strings "Nancy" and "nancy" would not match when they are compared.

Case Ignore String

Attributes whose values are strings, and you don't want to consider upper and lower cases when they're compared. For example, the strings "Nancy" and "nancy" would match when they are compared.

Case Ignore List

Attributes whose values are ordered sequences of strings, and you don't want to consider the upper and lower cases when they're compared. For example, the strings "Nancy" and "nancy" would match when they're compared.

Printable String

Attributes whose values are printable strings as defined in CCITT X.208, which specifies the Abstract Syntax Notation One (ASN.1). ASN.1 standardizes the format of data transmitted between systems.

Numeric String Syntaxes. If your data is a string of numbers, you could choose one of these syntaxes:


Name

Description

Numeric String

Attributes whose values are numeric strings as defined in CCITT X.208. X.208 is one of the RFCs that standardize ASN.1. ASN.1 standardizes the format of transmitted data between systems.

Octet String

Attributes whose values are byte strings and aren't interpreted by NDS.

Octet List

Attributes that describe an ordered sequence of octet strings.

Stream Syntax. If your data is a stream of data, or a file, you would choose this syntax:


Name

Description

Stream

Attributes that are login scripts or other stream attributes. Streams are files of information. The data stored in a stream file has no syntax enforcement of any kind. It is purely arbitrary data, defined by the application that created and uses it.

Any attribute defined with this syntax is single-valued.

The data size is limited to the maximum free space left on volume that contains your NDS database. On a NetWare server, this is the SYS: volume. Also, use this syntax whenever your data string exceeds 63K bytes.

Numeric Syntaxes. If your data is a type of number, you could choose one of the following syntaxes:


Name

Description

Boolean

Attributes whose values represent TRUE (1) or FALSE (0). Any attribute that uses this syntax is single-valued.

Counter

Attributes whose values are signed integers. Any attribute that uses this syntax is single-valued. This syntax differs from Integer in that any value added to this type of attribute is arithmetically added to the total, and any value deleted is arithmetically subtracted from the total.

Hold

See the definition in the Name Syntaxes table.

Integer

Attributes whose values are signed integers.

Address and Phone Number Syntaxes. If your data is a physical address, such as an email address, a postal address, a network address or a phone number, you could choose one of these syntaxes.


Name

Description

EMail Address

Attributes whose values represent Email addresses.

Facsimile Telephone Number

Strings that comply with the internationally agreed format for showing international telephone numbers, E.123, and an optional bit string formatted according to Recommendation T.30, which defines the format of data transmitted over a phone line. A telephone number in the E.123 format looks like: +44 171 732 8011..

This syntax combines a telephone number with an optional bit string.

Net Address

Network addresses in the NetWare environment. The address type indicates the type of communications protocol used (IPTM, AppleTalk, etc.).

Postal Address

Attributes whose values are postal addresses only. An attribute value for Postal Address will be typically composed of selected attributes from the MHS Unformatted Postal O/R Address version 1 according to Recommendation F.401, which is a recommendation for Naming and Addressing for Public Message Handling Service.

The value must be six lines of up to of 30 characters each, including a Postal Country Name. Normally the information contained in such an address could include a name, street address, city, state or province, postal code and possibly a postal office box number depending on the specific requirements of the named object.

Telephone Number

Attributes whose values are telephone numbers only.

The length of telephone number strings must be between 1 and 32.

Time Syntaxes. If your data has to do with time, you could choose one of these syntaxes:


Name

Description

Interval

Attributes whose values represent intervals of time in seconds.

Time

Attributes whose values represent time. A Time value consists of a whole number of seconds, where zero equals 12:00 midnight, January 1, 1970, UTC (Universal Time Coordinates).

Timestamp

Attributes whose values mark the time when a particular event occurred or will occur.

Unknown Syntax. The Unknown syntax is used for attributes whose attribute definition was deleted from the schema. This syntax is reserved for use by NDS.

Setting Attribute Constraints. You must set the Attribute Constraint flags to appropriately restrict the information the attribute can store and to constrain NDS and NDS client operations on that data. Because these values are flags, they are either TRUE or FALSE. The next lists summarize the attribute constraints you can choose from. These lists show only enough information to help you determine the attribute constraint you need. For more detailed information about the attribute constraints, see the NDS schema documentation that came with the NDK, or view it at: www.developer.novell.com.

Reading the Attribute. To regulate whether only servers can read the attribute, or whether clients can also read the attribute, use these constraints:


Name

Description

Hidden Attribute

Attributes that only applications running on the NetWare server can use.

Set this constraint to TRUE, if you want server applications to be the only entities to use this attribute. In NetWare 4, this constraint restricts the attribute to NDS only.

Public Read

Attributes that that anyone can read without having read privileges being assigned. You can't use inheritance masks to prevent an object from reading attributes with this constraint.

Using this constraint can make access to this attribute extremely efficient because NDS won't look up the ACLs to see who has the rights to read this attribute.

Set this constraint to TRUE, if you don't care what objects can read the attribute, and you want to save the time of looking up the ACLs.

Server Read

Attributes that NCP Server objects can read even though the right to read it has not been inherited or explicitly granted. You can't use inheritance masks to restrict servers from reading attributes with this constraint.

Set this constraint to TRUE if you want NCP Server objects to always be able read this attribute, regardless of the rights granted in the ACL.

Operational Attributes. These constraints regulate whether this attribute is operational.


Name

Description

Nonremovable Attribute

Attributes that can't be removed from the schema. In NetWare 5, clients can set this constraint when they create the attribute. In NetWare 4, only NDS can set this constraint. All base schema attributes have the non-removable constraint flag set to TRUE.

Set this constraint to TRUE, if you never want this attribute to be removed from the schema.

If this constraint is FALSE, the attribute can be removed if it hasn't been assigned to a class.

Operational

Attribute definitions that NDS uses internally and requires in order to function correctly.

You probably will not set this constraint to TRUE.

Modifying the Attribute. These constraints regulate who can change the attribute's value.


Name

Description

Read Only Attribute

Attributes that are created and maintained by NDS or applications running with NDS. Clients can read the attribute's value, but they can't modify it.

Set this constraint to TRUE if you don't want clients to remotely modify this attribute or remotely add a value for this attribute on an object.

Write Managed

Attributes that must have explicit rights granted to them before they can be changed.

Set this constraint to TRUE, if you want to force users to have managed rights on the object that contains this attribute before they can change this attribute's value.

Synchronizing the Attribute. These constraints regulate when the attribute's value will be synchronized with the NDS information.


Name
Description

Per Replica

Attributes whose information is not synchronized with the other replicas.

Set this constraint to TRUE if you want to mark this attribute so that its information is not synchronized with other replicas.

Schedule Sync Never

Allows the attribute's value to change without scheduling synchronization.

The attribute can wait to propagate its change until the next regularly scheduled synchronization cycle or some other event triggers synchronization.

Set this constraint to TRUE, if you don't want changes to this attribute's information to schedule synchronization.

Sync Immediate

Attributes whose information must be immediately propagated or changed throughout the NDS tree.

Set this constraint to TRUE, if you want to force immediate synchronization with other replicas when this attribute's value changes.

If all of these constraints are false, NDS synchronizes the data at the slow synchronization level set on the server that contains the replica holding the change.

Constraining Attribute Values. These constraints regulate whether the attribute's value is single or multi-valued, whether it has upper and lower boundaries, and whether it's a string.


Name

Description

Single Valued Attribute

Attributes that have single values, with no order implied.

Set this constraint to TRUE, if you want to restrict the attribute's value so that it can hold only one value. For example, if you want user objects to have only one telephone number, you would set the telephone number attribute's DS_SINGL_VALUED_ATTR flag to TRUE.

Sized Attribute

Indicates that the attribute has an upper and lower boundary. This can be the length for strings or the value for integers. The first number indicates the lower boundary and the second, the upper boundary.

If this constraint is TRUE, the attribute's value has a fixed size.

String Attribute

Attributes whose values are string types.

NDS sets this flag when it creates the attribute.

If this constraint is FALSE, the attribute isn't a string and can't be used as a naming attribute.

Registering the Schema Extension

Novell strongly recommends that you register your schema extensions before you release a product that extends the NDS schema. All schema object and attribute class definitions must be unique to the NDS tree. If you don't register your schema extension, your product could encounter a name collision during its installation. Novell maintains an NDS schema registry to avoid these collisions.

To register your schema extension, call Developer Support at 800-REDWORD (800-733-9673), or at the international number, 801-429-5588. You can also register at the Novell Developer Support Web site: www.developer.novell.com/support/schreg2c.htm.

When you register, you receive a unique prefix that you prepend to the names of your new attribute and class definitions. You also receive two ASN.1 (Abstract Syntax Notation One) identifiers: one for object classes and one for attribute definitions. You can expand these to include as many unique IDs as you need for object classes and attributes.

In and prior to NetWare 4.11, object class and attributes are not required to have an ASN.1 ID. In NetWare 5, all object classes and attributes must have ASN.1 IDs to pass Novell certification. ASN.1 IDs serve as a common syntax for transferring information between two systems.

Once you've registered your schema extension, it becomes available for other developers to use. So, if you must modify your schema extension, be careful before you remove or redefine any of its attribute meanings because other developers might be using it. Remember that you can

  • Extend it with new attributes.

  • Create an auxiliary class to add to your current object class.

  • Create a new extension.

This way, you won't create problems for other developers who have used your extension.

Designing a Sample Service Locator Object Schema Extension

Now that we've discussed some of the basic principles involved in designing a schema extension, we can use them to design a simple object class. Suppose we want to create a Service Locator object. We must first design the object, using the principles we just discussed.

Determining the Exact Purpose of the Service Locator Object and Its Attributes

The Service Locator object's purpose is to contain information that helps clients find the service this object represents on an NDS tree. This purpose tells us that:

  • The client must be able to find the service locator object in the tree. We can locate the object by searching for its class name. This way the client can locate all objects of this class without knowing the names the administrators gave the objects. The object must have an attribute that holds its class name.

  • The service locator object must be able to find servers that are running the service this object represents. We don't want to locate the server by its network address because that could change. We can use the server's DN to find its object and then look up its address. The object must have an attribute that holds the server's distinguished name.

  • We want clients to have efficient access to our object, and we don't need to restrict access to our object. So, we'll let anybody who has public rights read our object.

We decide that if an error occurs when a client attempts to connect to the server running our service, we want our application to find that server's administrator's user object. Our application can then read the administrator's phone number or email address from attributes on their user object and inform the administrator of the error. So we also know that our object must have an attribute that contains the distinguished name of the administrator's user object.

We now know that the object must have attributes that

  • Hold the object's class name.

  • Hold the server's DN.

  • Hold the server administrator's DN.

These attributes will be mandatory attributes in our class definition.

We can fill out a class definition template with the information we have so far (see Figure 3 below):

Figure 3: The Service Locator Class's Preliminary Information.

Determining Whether We Must Extend the Schema and Create a New Service Locator Object Class

Examining the classes in the schema shows that it doesn't define a class for service locators. So, we'll have to create our own class definition. The schema also doesn't define any super classes that the Service Locator object class can logically inherit from. The Service Locator object class doesn't fit any of the defined categories of super classes, such as Device, Organization, Server, Resource, etc. It seems to be in a unique category. So, we'll derive a new object class from Top. This means that the Service Locator object class will have no super classes, besides Top.

We can fill out the object class template with this additional information. Figure 4 shows the object template with the new information.

Figure 4: The Service Locator Class's Class Type and Super Class Information.

Deriving the Service Locator Object from Top

We've already determined that we can't derive our new Service Locator object from any super class besides Top. When we derive a new object class, we have to make decisions about its

  • Naming attributes

  • Containment

  • Object Class Flag

  • ACLs

Because we know that we are going to create objects from this class, we'll make the Service Locator object class type effective. This means that we must define its naming attributes and containment list.

Deciding the Service Locator Object's Naming Attributes. In this case, we can probably give the object one naming attribute. The likelihood of more than one of these objects having identical names is slim. And, because the naming convention for a leaf object is to name it by its CN Attribute, we'll designate the CN attribute as its naming attribute. The CN attribute lets administrators search for the object they created from this class.

Determining the Service Locator Object's Containment. We don't need to locate this object very high in the NDS tree. Most of the resources that will use this object and that this object will use are contained by Organizations and Organizational Units. So, we will keep this object on that same level in the tree.

Selecting the Service Locator Object's Class Flags. We can set four class flags: Container flag, Effective flag, Auxiliary flag, and Non-removable flag. NDS sets the other flags automatically. Because we intend to use the object to do something, locate a service, it's a leaf object, not a container. So, we'll leave the Container flag OFF. We intend to use this class to derive objects, so we'll set the Effective flag ON. We are not deriving an Auxiliary class, so we'll leave the Auxiliary Class flag OFF. And, we won't allow administrators and applications to remove our object, so we'll set the Non-removable flag to ON.

We can put our new information on our object template, as shown in Figure 5.

Figure 5: Object Template.

Selecting the Service Locator Object's Mandatory and Optional Attributes. Looking at the Top class definition, shown in Figure 6, we see that we inherit only one mandatory attribute, Object Class, and several optional attributes. The Object Class attribute is intended to contain the object's class. We intended to require Service Locator objects to have a mandatory object class name attribute so that we could locate all objects of the Service Locator class. The Object Class attribute's syntax and constraints are appropriate for our use, so we will use the Object Class attribute that the Service Locator Class inherits from Top. This way, we won't have to define a new attribute.

Figure 6: The Top Class Definition.

When we look at Top's optional attributes, we can see that the only attributes relevant to our object are the ones that allow NDS to operate on our object. We don't need any other optional attributes.

Default ACL Templates. Service Locator Objects don't need any special ACL templates. In fact, we are going to override whatever access restrictions the ACL defines for the Server Name DN and the Server Admin's DN, whether it inherits the access restrictions or an administrator defines them. So, we'll just use the basic ACL template the Service Locator Class inherits from Top.

We can fill out the Service Locator class definition template with the new information. Figure 7 shows the new information in the template.

Figure 7: The Service Locator Class's Naming, Containment, Attribute, and Class Flags Information.

The template doesn't contain the Object Class attribute because our object has inherited it from Top, and we don't have to include it in our definition. This is the same reason that the template doesn't list any optional attributes; they are all inherited Top.

Determining Whether the Object Service Locator Object's Attributes Exist in the Base Schema

The Service Locator Class has three mandatory attributes: CN, Server Name DN, and Server Admin's DN. One of these attributes, CN is defined in the base schema. The base schema also contains attributes called Host Server and Operator. These attributes' values are distinguished names, which is exactly the value that we wanted for our Sever Name DN and Server Admin's DN attributes. However, their PUBLIC READ constraint is set to FALSE, and we want our attributes' PUBLIC READ constraint set to TRUE so that anybody who has public rights can read these attributes. Setting the Public Read constraint to TRUE means that NDS won't check the ACLS. This saves time and it also ensures that regardless of the ACL restrictions, anyone with public rights will always be able to read this attribute. This means that we have two attributes, Server Name DN and Server Admin's DN, that we must define for the Service Locator object class.

Deriving the Server Name DN and Server Admin's DN Attributes

We designed the Service Locator object to use DNs to locate other objects. The Host Server and Operator attributes in the base schema also hold distinguished names and almost describes how we want to use the data, so we can base our attributes' definition on them, making necessary modifications. Or, we can simply examine the attribute syntaxes and constraints and choose the ones we want. Another option would be to use the Host Server and Operator attributes and modify their ACLs to allow public read.

Name Server, Name DN, and Server Admin's DN Attributes. We used the names ServerName DN and Server Admin's DN as placeholder names. More suitable attribute names might be Server Name and Server Admin. These names adequately describe the information in the attributes; they're shorter and easier to type. We can begin filling out an attribute template for these attributes. Because these attributes' definitions will be similar, we can use the same template for both attributes. Figure 8 shows this template.

Figure 8: The Attribute Definition Template.

Now, we have to select attribute syntaxes.

Selecting Attribute Syntaxes for the Server Name and Server Admin Attributes. We want to require administrators to enter the full distinguished name as values for these attributes, so the appropriate syntax would be the DN syntax. We can put that information in the attribute definition template, shown in Figure 9.

Figure 9: The Attribute Syntaxes.

Now, when administrators create Service Locator objects, NSD will require them to enter fully distinguished names as values for these attributes in order to create the object.

Now we must select the constraints for these attributes.

Selecting Attribute Syntaxes for the Server Name and Server Admin Attributes. We can examine each of the constraints and decide how we want our attribute to behave.


Attribute Syntax
Explanation

HIDDEN ATTRIBUTE

We don't want our new attributes' values to be hidden because we want the client to use them. We will leave this constraint FALSE.

NONREMOVABLE ATTRIBUTE

Our application depends on the existence of these attributes, so we don't want them to be removed accidentally. We will set this constraint to TRUE.

OPERATIONAL

Our attributes are not essential to NDS's functioning. We will leave this constraint FALSE.

PUBLIC READ

We want clients to read our attribute so that they can find instances of the service the object represents. We don't need to restrict access to this object, so we don't want the overhead of checking the ACL's trustee list. This constraint exempts our attributes from the security restrictions defined by the object's ACL attribute. In fact, choosing the DS_PUBLIC_READ constraint speeds up access to the object because NDS won't check the object's ACL to see who has rights to access the attributes. We will set this constraint to TRUE.

READ ONLY ATTRIBUTE

The attribute values might have to change. Especially, the value of the Server Admin attribute. We will leave this constraint FALSE.

PER REPLICA

We want this data to replicate. We'll leave this constraint FALSE.

SCHEDULE SYNC NEVER

We don't want to schedule synchronization whenever our attributes' values change. We will set this constraint to TRUE.

SERVER READ

Because the PUBLIC READ constraint is TRUE, we don't have to set this constraint because any object can read our atrributes. We will leave this constraint FALSE.

SINGLE VALUED ATTRIBUTE

We want our attributes to hold only one value. We will set this constraint to TRUE.

SIZED ATTRIBUTE

Because the DN syntax has a fixed length, this constraintcan be left FALSE.

STRING ATTRIBUTE

NDS sets this flag for us. Because the DN syntax is a string, NDS will set this flag to TRUE.

SYNC IMMEDIATE

We don't need to have changes to our attributes' values immediately scheduled for synchronization. We will leave this constraint FALSE.

WRITE MANAGED

We don't want to restrict access to our attributes to only those with managed write rights. We will leave this constraint FALSE.

We can now finish filling in our attributes' template with the constraints. Figure 10 shows the completed attribute template.

Figure 10: Attribute Constraints.

These constraints mean that our Server Name and Server Admin attributes

  • Cannot be removed

  • Can have only one value

  • Are strings

  • Can be read by any other object, even if that object is not listed as a trustee in the Service Locator object's ACL. In fact, NDS will not even check the ACL, saving time in accessing these attributes.

Conclusion

Now that you have designed your schema extension, you are ready to write the code for it. Remember to create any new attributes before you create a new object class so that you can assign the attributes to the class when it's created. If you create the attributes after you create the code, you must modify the class after you create the attributes. This is a problem because if you wanted to add new mandatory attributes to your class, you will not be able to. You must add mandatory attributes when the class is created; you can't add them afterward.

Kevin Burnett's article in this issue of Developer Notes entitled, "Extending NDS Schema with DSAPIs,"gives more details and the code to create the schema extension.

For detailed information about the schema, see the schema documentation in the Novell Developer's Kit (NDK). You can also view or download this documentation from www.developer.novell.comat no cost.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates