Dynamic Objects in OpenLDAP for Windows

OpenLDAP for Windows supports objects with a limited lifetime. The functionality is covered by the so called dds overlay. You can check the supported overlays by calling the slapd.exe program as follows:

slapd -VVV

Output:
OpenLDAP 2.4.26 Standalone LDAP Server (slapd)

  1. Included static overlays:
    • seqmod
    • syncprov
    • sssvlv
    • rwm
    • pcache
    • retcode
    • translucent
    • memberof
    • dynlist
    • constraint
    • dds
    • accesslog
    • auditlog
    • ppolicy
    • refint
    • unique
    • valsort
  2. Included static backends:
    • config
    • ldif
    • monitor
    • bdb
    • relay
    • sql
    • ldap
    • meta

The name dds stands for Dynamic Directory Service. It allows you to define dynamic objects, characterized by the dynamicObject objectClass. The behavior is defined in the RFC 2589.

Dynamic objects have a limited lifetime, determined by a time-to-live (TTL) that can be refreshed by means of a specific refresh extended operation. This operation allows you to set the Client Refresh Period (CRP), namely the period between refreshes that is required to preserve the dynamic object from expiration. The expiration time is computed by adding the requested TTL to the current time. When dynamic objects reach the end of their lifetime without being further refreshed, they are automatically deleted. There is no guarantee of immediate deletion, so clients should not count on it.

The configuration will be made in the slapd.conf file as follows:

ParameterValueDescripton
dds-max-ttl1dmax value for the default ttl time
dds-min-ttl10smin value for the default ttl time
dds-default-ttl1hthe life time of a dynmaic object
dds-interval120sthe internal polling interval to check the entryExpireTimestamp attribute of the dynamic object
dds tolerance5sadditional TTL for the expiration time point
dds-max-dynamicObjects5max number of dynamic objects
dds-stateTRUEenables or disable the dds overlay (default TRUE)

In the configuration above the max TTL is 1 day, the min TTL is 10 seconds with a real TTL of 1 hour. There is an interval of 120 seconds between expiration checks and a tolerance of 5 second (the lifetime of a dynamic object will be real TTL saved in the entryTtl attribute + tolerance). For a better performance an index for the entryExpireTimestamp should be used.

The attributes entryTTL and entryExpireTimestamp can only be read in the developer mode of the slapd service but you can check the existence of these attributes.

ldapsearch -x -h ldaphost -LLL -D cn=manager,dc=maxcrc,dc=com -w secret -b dc=maxcrc,dc=com entryttl=*

Output:

dn: cn=maxcrc project meeting,ou=groups,dc=maxcrc,dc=com
cn: maxcrc project meeting
objectClass: groupOfNames
objectClass: dynamicObject
member: cn=12161,ou=OU3,ou=OU2,ou=web-monitor,dc=maxcrc,dc=com
member: cn=12859,ou=USER,ou=OU4,ou=OU3,ou=OU2,ou=web-monitor,dc=maxcrc,dc=com
member: cn=Admins,ou=GRP,dc=maxcrc,dc=com
member: cn=manager,dc=maxcrc,dc=com

For better understanding you should use the LDIF backend to see the content of these attributes. The complete slapd.conf file for this backend is listed below:

# LDIF Backend configuration file
#See slapd.conf for details on configuration options.
# This file should NOT be world readable.
ucdata-path ./ucdata
include ./schema/core.schema
include ./schema/cosine.schema
include ./schema/nis.schema
include ./schema/inetorgperson.schema
include ./schema/openldap.schema
include ./schema/dyngroup.schema

pidfile ./run/slapd.pid
argsfile ./run/slapd.args

# Enable TLS if port is defined for ldaps
TLSVerifyClient never
TLSCipherSuite HIGH:MEDIUM:-SSLv2
TLSCertificateFile ./secure/certs/server.pem
TLSCertificateKeyFile ./secure/certs/server.pem
TLSCACertificateFile ./secure/certs/server.pem

#######################################################################
# LDIF database definitions
#######################################################################

database ldif
suffix „dc=maxcrc,dc=com“
rootdn „cn=Manager,dc=maxcrc,dc=com“
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw {SSHA}o5yFyNpDCAnOVHjGv99+0p4nn6vQFG+4

directory ./ldifdata

overlay dds
# Specifies the max TTL value. This is also the default TTL newly created dynamic objects receive, unless dds-default-ttl is set. When the client with a refresh extended operation requests a TTL higher than it, sizeLimitExceeded is returned. This value must be between 86400 (1 day, the default) and 31557600 (1 year plus 6 hours, as per RFC 2589).
dds-max-ttl 1d
# Specifies the min TTL value; clients requesting a lower TTL by means of the refresh extended operation actually obtain this value as CRP. If set to 0 (the default), no lower limit is set.
dds-min-ttl 60
# Specifies the default TTL value that newly created dynamic objects get. If set to 0 (the default), the dds-max-ttl is used.
dds-default-ttl 0
# Specifies the interval between expiration checks; defaults to 1 hour.
dds-interval 120
# Specifies an extra time that is added to the timer that actually wakes up the thread that will delete an expired dynamic object. So the nominal lifetime of the entry is that specified in the entryTtl attribute, but its lifetime will actually be entryTtl + tolerance. Note that there is no guarantee that the lifetime of a dynamic object will be exactly the requested TTL; due to implementation details, it may be longer, which is allowed by RFC 2589. By default, tolerance is 0.
dds-tolerance 5s
# Specifies the maximum number of dynamic objects that can simultaneously exist within a naming context. This allows to limit the amount of resources (mostly in terms of run-queue size) that are used by dynamic objects. By default, no limit is set.
#dds-max-dynamicObjects
# Specifies if the Dynamic Directory Services feature is enabled or not. By default it is; however, a proxy does not need to keep track of dynamic objects itself, it only needs to inform the frontend that support for dynamic objects is available.
#dds-state TRUE

# RFC 2589 recommends that anonymous clients should not be allowed to refresh a dynamic object.
# This can be implemented by appropriately crafting access control to obtain the desired effect.
#
#Example: restrict refresh to the creator of the dynamic object
access to attrs=entryTtl by dnattr=creatorsName manage by * read

Creating dynamic objects

You can create such objects by adding the objectclass dynamicObject to the LDIF backend. Here is a complete LDIF file which will create the structure for the backend above.

dn: dc=maxcrc,dc=com
objectClass: domain
objectClass: top
dc: maxcrc

dn: ou=People,dc=maxcrc,dc=com
objectclass: top
objectclass: organizationalUnit
ou: People
description: Container for user entries

dn: ou=groups,dc=maxcrc,dc=com
objectclass: top
objectclass: organizationalUnit
ou: groups
description: Container for group entries

dn: cn=project_meeting,ou=groups,dc=maxcrc,dc=com
objectClass: groupOfNames
objectClass: dynamicObject
cn: project_meeting
member: cn=manager,dc=maxcrc,dc=com

In the given example the object cn=project_meeting,ou=groups,dc=maxcrc,dc=com will be automatically deleted by not refreshing after a time period of 1 day, because the dds-default-ttl value is zero.

Checking the expiration time

Let’s have a look at the backend details. After creating the object with the ldapmodify tool for example, you have a ldif file in the backend directory

ldapmodify -a -x -h ldaphost -D cn=manager,dc=maxcrc,dc=com -w secret -f dynobject.ldif

After doing this below the ldifdata folder a file cn=pproject_meeting.ldif is produced.

If you open the file, the following entries can be found:

dn: cn=project_meeting
objectClass: groupOfNames
objectClass: dynamicObject
cn: project_meeting
member: cn=manager,dc=maxcrc,dc=com
entryTtl: 86400
entryExpireTimestamp: 20110904153952Z
structuralObjectClass: groupOfNames
entryUUID: acbd6364-641b-4a11-99cb-9e1ab52fd4f9
creatorsName: cn=Manager,dc=maxcrc,dc=com
createTimestamp: 20110903153952Z
entryCSN: 20110903153952.635923Z#000000#000#000000
modifiersName: cn=Manager,dc=maxcrc,dc=com
modifyTimestamp: 20110903153952Z

You can see the life time and expiration time stamp in the bold marked attributes. If you just add members to the group object the attribute entryExpireTimestamp will be modified accordingly. The life time itself can be managed by the ldapexop tool.

ldapexop -x -h ldaphost -D "cn=manager,dc=maxcrc,dc=com" –w secret refresh cn=project_meeting,ou=groups,dc=maxcrc,dc=com 3600

The object cn=project_meeting,ou=groups,dc=maxcrc,dc=com will be deleted without refreshing 3600 seconds after the current modification. If you modify the object within the TTL lifetime you specified, the expiration time will just postponed according the modification time.

original time pointentryExpireTimestamp: 20110904153952Z
time point after modificationentryExpireTimestamp: 20110904155242Z