LDAP Updates
Note
Examples in this documentation depend on features activated in the ds-evaluation
setup profile.
For details, see "Learn About the Evaluation Setup Profile".
For details on the LDIF format shown in the examples that follow, see RFC 2849.
Add Entries
The following example adds two new users:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: cn=Arsene Lupin,ou=Special Users,dc=example,dc=com
objectClass: person
objectClass: top
cn: Arsene Lupin
telephoneNumber: +33 1 23 45 67 89
sn: Lupin
dn: cn=Horace Velmont,ou=Special Users,dc=example,dc=com
objectClass: person
objectClass: top
cn: Horace Velmont
telephoneNumber: +33 1 12 23 34 45
sn: Velmont
EOF
The following example adds 10,000 generated entries, using the --numConnections
option to perform multiple add operations in parallel:
# Generate user entries with user IDs larger than those that exist, # and remove container entries from the output: $makeldif \ --outputLdif output.ldif \ <(sed "s/<sequential:0>/<sequential:100000>/" /path/to/opendj/config/MakeLDIF/example.template)
$sed '1,10d' output.ldif > /tmp/generated-users.ldif
# Bulk add the generated user entries: $ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \ --bindPassword bribery \ --numConnections 64 \ /tmp/generated-users.ldif
When you use the --numConnections
option, the number of connection is rounded up to the nearest power of two for performance reasons.
Modify Entries
The following example shows you how to add a description and JPEG photo to Sam Carter's entry:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=scarter,ou=people,dc=example,dc=com
changetype: modify
add: description
description: Accounting Manager
-
add: jpegphoto
jpegphoto:<file:///tmp/picture.jpg
EOF
The following example replaces the description on Sam Carter's entry:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=scarter,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: New description
EOF
The following example deletes the JPEG photo on Sam Carter's entry:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=scarter,ou=people,dc=example,dc=com
changetype: modify
delete: jpegphoto
EOF
The following example deletes a single CN value on Barbara Jensen's entry:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=bjensen,ou=People,dc=example,dc=com
changetype: modify
delete: cn
cn: Barbara Jensen
EOF
A double dash, --
, signifies the end of command options. After the double dash, only trailing arguments are allowed. To indicate standard input as a trailing argument, use a bare dash, -
, after the double dash.
Consider the following changes expressed in LDIF:
dn: uid=bjensen,ou=People,dc=example,dc=com changetype: modify replace: description description: New description from standard input
To send these changes to the ldapmodify command on standard input, use either of the following equivalent constructions:
# With dashes:
$ cat bjensen-stdin-description.ldif | ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery \
-- -
# Without dashes:
$ cat bjensen-stdin-description.ldif | ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery
Consider an application that lets end users update user profiles through a browser. It stores user profiles as DS entries. End users can look up user profiles and modify them. The application assumes that the end users can tell the right information when they see it, and updates profiles exactly as users see them on their screens.
Suppose two users, Alice and Bob, are busy and often interrupted. Alice has Babs Jensen's new phone and room numbers. Bob has Babs's new location and description. Both assume that they have all the information that has changed. What can you do to make sure that your application applies the right changes when Alice and Bob simultaneously update Babs Jensen's profile?
DS servers have two features to help you in this situation. One of the features is the LDAP Assertion Control, described in Assertion request control, used to tell the directory server to perform the modification only if an assertion you make stays true. The other feature is DS support for entity tag (ETag) attributes, making it easy to check whether the entry in the directory is the same as the entry you read.
Alice and Bob both get Babs's entry. In LDIF, the relevant attributes from the entry look like the following. The ETag is a generated value that depends on the content of the entry:
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --baseDN dc=example,dc=com \ "(uid=bjensen)" \ telephoneNumber roomNumber l ETag
dn: uid=bjensen,ou=People,dc=example,dc=com telephoneNumber: +1 408 555 1862 roomNumber: 0209 l: San Francisco ETag: ETAG
Bob prepares his changes in your application. Bob is almost ready to submit the new location and description when Carol stops by to ask Bob a few questions.
Alice starts just after Bob, but manages to submit her changes without interruption. Now Babs's entry has a new phone number, room number, and ETag:
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --baseDN dc=example,dc=com \ "(uid=bjensen)" \ telephoneNumber roomNumber l ETag
dn: uid=bjensen,ou=People,dc=example,dc=com telephoneNumber: +47 2108 1746 roomNumber: 1389 l: San Francisco ETag: NEW_ETAG
In your application, you use the ETag value with the assertion control to prevent Bob's update from succeeding. The application tries the equivalent of the following commands with Bob's updates:
$ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \ --bindPassword bribery \ --assertionFilter "(ETag=${ETAG})" << EOF dn: uid=bjensen,ou=People,dc=example,dc=com changetype: modify replace: l l: Grenoble - add: description description: Employee of the Month EOF
# The LDAP modify request failed: 122 (Assertion Failed) # Additional Information: Entry uid=bjensen,ou=People,dc=example,dc=com cannot be modified because the request contained an LDAP assertion control and the associated filter did not match the contents of the entry
The application reloads Babs's entry with the new ETag value, and tries Bob's update again. This time Bob's changes do not collide with other changes. Babs's entry is successfully updated:
$ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \ --bindPassword bribery \ --assertionFilter "(ETag=${NEW_ETAG})" << EOF dn: uid=bjensen,ou=People,dc=example,dc=com changetype: modify replace: l l: Grenoble - add: description description: Employee of the Month EOF
# MODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com
DS servers support attribute values that have JSON syntax as demonstrated in "JSON Query Filters".
This example depends on the configuration and sample data used in "JSON Query Matching Rule Index". Unless you have installed the server with the evaluation profile, perform the commands in that example to prepare the server before trying this one.
The following example replaces the existing JSON value with a new JSON value:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=bjensen,ou=people,dc=example,dc=com
changetype: modify
replace: json
json: {"stuff":["things","devices","paraphernalia"]}
EOF
Notice that the JSON object is replaced entirely.
When DS servers receive update requests for Json
syntax attributes, they expect valid JSON objects. By default, Json
syntax attribute values must comply with The JavaScript Object Notation (JSON) Data Interchange Format described in RFC 7159. You can use the advanced core schema configuration option json-validation-policy
to have the server be more lenient in what it accepts, or to disable JSON syntax checking.
The following example relaxes JSON syntax checking to allow comments, single quotes, and unquoted control characters such as newlines, in strings:
$ dsconfig \
set-schema-provider-prop \
--hostname localhost \
--port 4444 \
--bindDN uid=admin \
--bindPassword password \
--provider-name "Core Schema" \
--set json-validation-policy:lenient \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--no-prompt
Change Incoming Updates
Some client applications send updates including attributes with names that differ from the attribute names defined in the LDAP schema. Other client applications might try to update attributes they should not update, such as the operational attributes creatorsName
, createTimestamp
, modifiersName
, and modifyTimestamp
. Ideally, you would fix the client application behavior, but that is not always possible. You can configure the attribute cleanup plugin to filter add and modify requests, rename attributes in requests using incorrect names, and remove attributes that applications should not change.
The following example renames incoming email
attributes to mail
attributes. First, configure the attribute cleanup plugin to rename the inbound attribute:
$ dsconfig \
create-plugin \
--hostname localhost \
--port 4444 \
--bindDN uid=admin \
--bindPassword password \
--type attribute-cleanup \
--plugin-name "Rename email to mail" \
--set enabled:true \
--set rename-inbound-attributes:email:mail \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--no-prompt
Next, confirm that it worked as expected:
$ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \ --bindPassword bribery << EOF dn: uid=newuser,ou=People,dc=example,dc=com uid: newuser objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: top cn: New User sn: User ou: People email: newuser@example.com userPassword: chngthspwd EOF
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --baseDN dc=example,dc=com \ "(uid=newuser)" \ mail
dn: uid=newuser,ou=People,dc=example,dc=com mail: newuser@example.com
The following example prevents client applications from adding or modifying creatorsName
, createTimestamp
, modifiersName
, and modifyTimestamp
attributes. First, set up the attribute cleanup plugin:
$ dsconfig \
create-plugin \
--type attribute-cleanup \
--plugin-name "Remove attrs" \
--set enabled:true \
--set remove-inbound-attributes:creatorsName \
--set remove-inbound-attributes:createTimestamp \
--set remove-inbound-attributes:modifiersName \
--set remove-inbound-attributes:modifyTimestamp \
--hostname localhost \
--port 4444 \
--bindDN uid=admin \
--bindPassword password \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--no-prompt
Next, confirm that it worked as expected:
$ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \ --bindPassword bribery << EOF dn: uid=badattr,ou=People,dc=example,dc=com uid: newuser objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: top cn: Bad Attr sn: Attr ou: People mail: badattr@example.com userPassword: chngthspwd creatorsName: cn=Bad Attr createTimestamp: Never in a million years. modifiersName: uid=admin modifyTimestamp: 20110930164937Z EOF
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --baseDN dc=example,dc=com \ "(uid=badattr)" \ creatorsName createTimestamp modifiersTimestamp modifyTimestamp
dn: uid=badattr,ou=People,dc=example,dc=com creatorsName: uid=kvaughan,ou=people,dc=example,dc=com createTimestamp: <timestamp>
Rename Entries
The Relative Distinguished Name (RDN) refers to the part of an entry's DN that differentiates it from all other DNs at the same level in the directory tree. For example, uid=bjensen
is the RDN of the entry with the DN uid=bjensen,ou=People,dc=example,dc=com
. When you change the RDN of the entry, you rename the entry, modifying the naming attribute and DN.
In this example, Sam Carter is changing her last name to Jensen, and changing her login from scarter
to sjensen
. The following example shows you how to rename and change Sam Carter's entry. Notice the boolean field, deleteoldrdn: 1
, which indicates that the previous RDN, uid: scarter
, should be removed. Setting deleteoldrdn: 0
instead would preserve uid: scarter
on the entry:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: uid=scarter,ou=people,dc=example,dc=com
changetype: modrdn
newrdn: uid=sjensen
deleteoldrdn: 1
dn: uid=sjensen,ou=people,dc=example,dc=com
changetype: modify
replace: cn
cn: Sam Jensen
-
replace: sn
sn: Jensen
-
replace: homeDirectory
homeDirectory: /home/sjensen
-
replace: mail
mail: sjensen@example.com
EOF
Move Entries
When you rename an entry with child entries, the directory has to move all the entries underneath it.
Note
DS directory servers support the modify DN operation only for moving entries in the same backend, under the same base DN. Depending on the number of entries you move, this can be a resource-intensive operation.
The following example moves all entries at and below ou=People,dc=example,dc=com
under ou=Subscribers,dc=example,dc=com
. All the entries in this example are in the same backend. The line deleteoldrdn: 1
indicates that the old RDN, ou: People
, should be removed:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN uid=admin \
--bindPassword password << EOF
dn: ou=People,dc=example,dc=com
changetype: modrdn
newrdn: ou=Subscribers
deleteoldrdn: 1
newsuperior: dc=example,dc=com
EOF
Be aware that the move does not modify ACIs and other values that depend on ou=People
. You must also edit any affected entries.
The following example moves an application entry that is under dc=example,dc=com
under ou=Apps,dc=example,dc=com
instead. The line deleteoldrdn: 0
indicates that old RDN, cn
, should be preserved:
$ ldapmodify \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
--bindPassword bribery << EOF
dn: cn=New App,dc=example,dc=com
changetype: moddn
newrdn: cn=An App
deleteoldrdn: 0
newsuperior: ou=Apps,dc=example,dc=com
EOF
Delete Entries
The following example shows you how to give an administrator access to use the subtree delete control, and to use the subtree delete option to remove an entry and its child entries:
$dsconfig \ set-access-control-handler-prop \ --hostname localhost \ --port 4444 \ --bindDN uid=admin \ --bindPassword password \ --add global-aci:"(targetcontrol=\"SubtreeDelete\")\ (version 3.0; acl \"Allow Subtree Delete\"; allow(read) \ userdn=\"ldap:///uid=kvaughan,ou=People,dc=example,dc=com\";)" \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --no-prompt
$ldapdelete \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN "uid=kvaughan,ou=People,dc=example,dc=com" \ --bindPassword bribery \ --deleteSubtree "ou=Special Users,dc=example,dc=com"
A double dash, --
, signifies the end of command options, After the double dash, only trailing arguments are allowed. To indicate standard input as a trailing argument, use a bare dash, -
, after the double dash.
Consider the following list of users to delete:
$cat users-to-delete.txt
uid=sfarmer,ou=People,dc=example,dc=com uid=skellehe,ou=People,dc=example,dc=com uid=slee,ou=People,dc=example,dc=com uid=smason,ou=People,dc=example,dc=com uid=speterso,ou=People,dc=example,dc=com uid=striplet,ou=People,dc=example,dc=com
To send this list to the ldapdelete command on standard input, use either of the following equivalent constructions:
# With dashes:
$ cat users-to-delete.txt | ldapdelete \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN uid=kvaughan,ou=people,dc=example,dc=com \
--bindPassword bribery \
-- -
# Without dashes:
$ cat users-to-delete.txt | ldapdelete \
--hostname localhost \
--port 1636 \
--useSsl \
--usePkcs12TrustStore /path/to/opendj/config/keystore \
--trustStorePasswordFile /path/to/opendj/config/keystore.pin \
--bindDN uid=kvaughan,ou=people,dc=example,dc=com \
--bindPassword bribery