PingDS 7.5.1

Change LDAP schema

Learn how to change LDAP schema definitions online and offline.

Description

Estimated time to complete: 30 minutes

LDAP schema definitions determine the kinds of information in the directory and how the information is related. You can update the schema definitions online and offline to change what the directory allows.

Develop and test schema changes online to catch any errors in the updated definitions. After you validate the schema changes, you can deploy them online with the ldapmodify command or offline by copying updated schema files. Replication replays the LDAP schema changes to other DS servers.

In this use case, you:

  • Understand a scenario where schema changes make sense.

  • Understand how schema changes can require rebuilding indexes.

  • Develop and test schema changes.

  • Practice rolling out schema changes by copying updated schema files.

Goals

In completing this use case, you learn to:

  • Use the ldapmodify command to change LDAP schema.

  • Rebuild indexes affected by schema changes.

  • Review and remove replication metadata from changed schema files.

Example scenario

One of the directory application owners asks Pat to let their application page through accounts by class of service.

Pat’s directory deployment uses the definition for the classOfService attribute based on the evaluation profile.

Pat can add an index for the classOfService attribute, but wonders if the application owner has additional requirements. In discussion with the application owner, Pat learns the application owner:

  • Found the class of service attribute can accept any random string value.

    They ask Pat if class of service could be restricted to an enumeration of bronze, silver, gold, and platinum.

  • Wants a sharedQuota attribute like the diskQuota and mailQuota attributes.

    The application owner doesn’t use sharedQuota yet, but plans to use it in a few weeks.

Prerequisites

Knowledge

Before you start:

  • Make sure you are familiar with the command line on your operating system.

  • If you’re new to directory services, work through the examples to learn LDAP.

Actions

Before you try this example, install a DS server in evaluation mode.

Tasks

Pat shows the tasks with DS servers in evaluation mode. The order and content of the tasks for production deployments are the same.

Task 1: Add a classOfService index

The application owner wants to page through accounts by class of service. Class of service has only a few values, and every user account could have the attribute. This is a good match for a big index.

  1. Create the index:

    $ /path/to/opendj/bin/dsconfig \
     create-backend-index \
     --backend-name dsEvaluation \
     --index-name classOfService \
     --set index-type:big-equality \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
  2. Build the new index:

    $ /path/to/opendj/bin/rebuild-index \
     --baseDn dc=example,dc=com \
     --index classOfService \
     --hostname localhost \
     --port 4444 \
     --bindDn uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin

Applications can now use the simple paged results control to page through entries with a specified class of service.

Task 2: Develop schema changes

Pat notices the classOfService attribute has SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 (directory string syntax). Pat can change the schema definition to use a custom enumeration syntax, so DS only allows applications to set one of the desired values. Pat can update the schema again to extend the enumeration as necessary.

Pat also adds a new sharedQuota attribute modeled on the diskQuota and mailQuota attributes.

Pat knows DS rejects malformed online modifications to schema definitions. Pat develops and tests the schema changes with the ldapmodify command.

When changing a schema definition, delete the existing value and add the new value as part of the same modification. Otherwise, there’s a window after you delete a definition and before you add the new one where an update could fail or an index could become degraded due to the missing schema definition.

The definition you delete must match the definition in the schema LDIF exactly, not including space characters.

When you update schema definitions online, DS sets the X-SCHEMA-FILE value even if you don’t.

  1. Update the schema definitions.

    The following example command:

    • Adds an enumeration syntax for class of service

    • Updates the classOfService attribute to use the enumeration syntax

    • Adds a sharedQuota attribute to the cos object class for class of service attributes

    $ /path/to/opendj/bin/ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: cn=schema
    changetype: modify
    add: ldapSyntaxes
    ldapSyntaxes: ( example-custom-syntax-oid
      DESC 'Enumeration syntax for class of service'
      X-ENUM ( 'bronze' 'silver' 'gold' 'platinum' )
      X-ORIGIN 'DS Documentation Examples' )
    -
    delete: attributeTypes
    attributeTypes: ( example-class-of-service-attribute-type
      NAME 'classOfService'
      EQUALITY caseIgnoreMatch
      ORDERING caseIgnoreOrderingMatch
      SUBSTR caseIgnoreSubstringsMatch
      SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
      SINGLE-VALUE
      USAGE userApplications
      X-ORIGIN 'DS Documentation Examples' )
    -
    add: attributeTypes
    attributeTypes: ( example-class-of-service-attribute-type
      NAME 'classOfService'
      EQUALITY caseIgnoreMatch
      ORDERING caseIgnoreOrderingMatch
      SUBSTR caseIgnoreSubstringsMatch
      SYNTAX example-custom-syntax-oid
      SINGLE-VALUE
      USAGE userApplications
      X-ORIGIN 'DS Documentation Examples' )
    -
    add: attributeTypes
    attributeTypes: ( example-class-of-service-shared-quota
      NAME 'sharedQuota'
      EQUALITY caseIgnoreMatch
      ORDERING caseIgnoreOrderingMatch
      SUBSTR caseIgnoreSubstringsMatch
      SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
      USAGE userApplications
      X-ORIGIN 'DS Documentation Examples' )
    -
    delete: objectClasses
    objectClasses: ( example-class-of-service-object-class
      NAME 'cos'
      SUP top
      AUXILIARY
      MAY ( classOfService $ diskQuota $ mailQuota )
      X-ORIGIN 'DS Documentation Examples' )
    -
    add: objectClasses
    objectClasses: ( example-class-of-service-object-class
      NAME 'cos'
      SUP top
      AUXILIARY
      MAY ( classOfService $ diskQuota $ mailQuota $ sharedQuota )
      X-ORIGIN 'DS Documentation Examples' )
    EOF
  2. Rebuild affected indexes.

    This update changes the classOfService syntax, so rebuild the index to use the new syntax:

    $ /path/to/opendj/bin/rebuild-index \
     --baseDn dc=example,dc=com \
     --index classOfService \
     --hostname localhost \
     --port 4444 \
     --bindDn uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin

    If the enumeration syntax changes again, rebuild the classOfService index.

Task 3: Save changed schema files

For the production servers, Pat doesn’t change the schema online. Pat keeps schema definition files under source control to track all schema changes.

After modifying the schema online, Pat locates the schema definitions added and changed in the db/schema LDIF files. Pat notices DS rewrites the updated LDIF files with one schema definition per line.

Before putting the changed LDIF files under source control, Pat takes care to remove the operational attributes including the ds-sync-generation-id and ds-sync-state attributes. Using the wrong values for those attributes could break schema replication. Pat lets DS replication manage the operational attributes.

In Pat’s copies of the LDIF files, the schema definitions are folded for readability. Each line continuation starts with two spaces before a schema element keyword. LDIF continuation consumes the first space. The second space separates the keyword from the preceding text.

Show 60-ds-evaluation-schema.ldif
dn: cn=schema
objectclass: top
objectclass: ldapSubentry
objectclass: subschema
cn: schema
ldapSyntaxes: ( example-custom-syntax-oid
  DESC 'Enumeration syntax for class of service'
  X-ENUM ( 'bronze' 'silver' 'gold' 'platinum' )
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( example-class-of-service-disk-quota
  NAME 'diskQuota'
  EQUALITY caseIgnoreMatch
  ORDERING caseIgnoreOrderingMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  USAGE userApplications
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( example-class-of-service-mail-quota
  NAME 'mailQuota'
  EQUALITY caseIgnoreMatch
  ORDERING caseIgnoreOrderingMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  USAGE userApplications
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( example-class-of-service-shared-quota
  NAME 'sharedQuota'
  EQUALITY caseIgnoreMatch
  ORDERING caseIgnoreOrderingMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  USAGE userApplications
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( json-attribute-oid
  NAME 'json'
  EQUALITY caseIgnoreJsonQueryMatch
  SYNTAX 1.3.6.1.4.1.36733.2.1.3.1
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( oauth2token-attribute-oid
  NAME 'oauth2Token'
  EQUALITY caseIgnoreOAuth2TokenQueryMatch
  SYNTAX 1.3.6.1.4.1.36733.2.1.3.1
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( jsonToken-attribute-oid
  NAME 'jsonToken'
  EQUALITY caseIgnoreJsonTokenIDMatch
  SYNTAX 1.3.6.1.4.1.36733.2.1.3.1
  SINGLE-VALUE
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
attributeTypes: ( example-class-of-service-attribute-type
  NAME 'classOfService'
  EQUALITY caseIgnoreMatch
  ORDERING caseIgnoreOrderingMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX example-custom-syntax-oid
  SINGLE-VALUE
  USAGE userApplications
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
objectClasses: ( json-object-class-oid
  NAME 'jsonObject'
  SUP top
  AUXILIARY
  MAY json
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
objectClasses: ( oauth2token-object-class-oid
  NAME 'oauth2TokenObject'
  SUP top
  AUXILIARY
  MAY oauth2Token
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
objectClasses: ( json-token-object-class-oid
  NAME 'JsonTokenObject'
  SUP top
  AUXILIARY
  MAY jsonToken
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
objectClasses: ( example-class-of-service-object-class
  NAME 'cos'
  SUP top
  AUXILIARY
  MAY ( classOfService $ diskQuota $ mailQuota $ sharedQuota )
  X-ORIGIN 'DS Documentation Examples'
  X-SCHEMA-FILE '60-ds-evaluation-schema.ldif' )
Show 99-user.ldif
dn: cn=schema
objectclass: top
objectclass: ldapSubentry
objectclass: subschema
cn: schema

Pat also keeps copies of the original DS schema files under source control. When upgrading, Pat compares the original files with the upgraded files and applies any changes to the modified production files as necessary.

Task 4: Deploy changed schema files

To make a schema change in deployment, stop the server, add the custom schema, and restart the server.

  1. Prepare to show schema change deployment by setting up two replicated DS directory servers as described in Install DS and Learn replication.

  2. Make sure you have local copies of the changed schema definition files:

    60-ds-evaluation-schema.ldif

    This file contains the changed schema definitions.

    99-user.ldif

    This file removes the replication metadata.

  3. Stop a server:

    $ /path/to/opendj/bin/stop-ds
  4. Add the custom schema files and start the replica:

    $ cp 60-ds-evaluation-schema.ldif /path/to/opendj/db/schema/
  5. Start the server:

    $ /path/to/opendj/bin/start-ds

Replication applies the changes to other servers.

Task 5: Deploy the classOfService index

Create and build the index on each replica an application uses for searches:

  1. Create the index on the first server:

    $ /path/to/opendj/bin/dsconfig \
     create-backend-index \
     --backend-name dsEvaluation \
     --index-name classOfService \
     --set index-type:big-equality \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
  2. Build the new index on the first server:

    $ /path/to/opendj/bin/rebuild-index \
     --baseDn dc=example,dc=com \
     --index classOfService \
     --hostname localhost \
     --port 4444 \
     --bindDn uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin
  3. Create the index on the second server:

    $ /path/to/replica/bin/dsconfig \
     create-backend-index \
     --backend-name dsEvaluation \
     --index-name classOfService \
     --set index-type:big-equality \
     --hostname localhost \
     --port 14444 \
     --bindDN uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/replica/config/keystore \
     --trustStorePassword:file /path/to/replica/config/keystore.pin \
     --no-prompt
  4. Build the new index on the second server:

    $ /path/to/replica/bin/rebuild-index \
     --baseDn dc=example,dc=com \
     --index classOfService \
     --hostname localhost \
     --port 14444 \
     --bindDn uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/replica/config/keystore \
     --trustStorePassword:file /path/to/replica/config/keystore.pin

The new schema definitions and indexes are ready to use.

Validation

After you deploy the changed schema definitions and classOfService indexes, follow these steps to check you can use the updated schema definitions and index.

  1. Page through entries with gold class of service on the second replica as a user who doesn’t have the unindexed-search privilege:

    $ ldapsearch \
     --hostname localhost \
     --port 11636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/replica/config/keystore \
     --trustStorePassword:file /path/to/replica/config/keystore.pin \
     --bindDN uid=kvaughan,ou=People,dc=example,dc=com \
     --bindPassword bribery \
     --baseDn dc=example,dc=com \
     --simplePageSize 5 \
     "(classOfService=gold)" \
     mail
    dn: uid=abarnes,ou=People,dc=example,dc=com
    mail: abarnes@example.com
    
    dn: uid=ahall,ou=People,dc=example,dc=com
    mail: ahall@example.com
    
    dn: uid=aknutson,ou=People,dc=example,dc=com
    mail: aknutson@example.com
    
    dn: uid=alutz,ou=People,dc=example,dc=com
    mail: alutz@example.com
    
    dn: uid=ashelton,ou=People,dc=example,dc=com
    mail: ashelton@example.com
    
    Press RETURN to continue
  2. Show users can now have platinum class of service:

    $ /path/to/replica/bin/ldapmodify \
     --hostname localhost \
     --port 11636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/replica/config/keystore \
     --trustStorePassword:file /path/to/replica/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=bjensen,ou=People,dc=example,dc=com
    changetype: modify
    replace: classOfService
    classOfService: platinum
    EOF
  3. Show users can’t have a random string for class of service:

    $ /path/to/replica/bin/ldapmodify \
     --hostname localhost \
     --port 11636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/replica/config/keystore \
     --trustStorePassword:file /path/to/replica/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=bjensen,ou=People,dc=example,dc=com
    changetype: modify
    replace: classOfService
    classOfService: custom extended service
    EOF
    # The LDAP modify request failed: 21 (Invalid Attribute Syntax)
    # Additional Information:  When attempting to modify entry uid=bjensen,ou=People,dc=example,dc=com to replace the set of values for attribute classOfService, value "custom extended service" was found to be invalid according to the associated syntax: The provided value "custom extended service" cannot be parsed because it is not allowed by enumeration syntax with OID "example-custom-syntax-oid"

What’s next

Pat knows schema definition changes are safe in files under source control. The reasons for the schema changes are not so well known. Pat plans to start and maintain a schema dictionary. The schema dictionary will describe each attribute known to be in use. It will track:

  • Who uses the attribute, including their contact information, and how they use it

  • What data it stores, and who owns the data, including contact information

  • Where the data comes from, especially if it comes from another system

  • When there are maintenance windows for the attribute (for reindexing and so on)

In addition, Pat has more to discuss with the application owner, who asked for the new sharedQuota attribute. The diskQuota and mailQuota attributes depend on the classOfService attribute for their values.

  • How should DS define sharedQuota values?

  • What should the quotas be for classOfService: platinum?

Explore further

Reference material

Reference Description

Background and how-to instructions for working with indexes

An in-depth look at LDAP schema definitions

LDAP schema in client applications

Schema for HTTP client applications

A reference for all default schema definitions

Copyright © 2010-2024 ForgeRock, all rights reserved.