ldap cheatsheet
1 Install (OpenLDAP's daemon is slapd)
On CentOS:
1.1 slapd commands:
slapacl
: Checks the access to a list of attributesslapadd
: Adds entries from an LDIF file to an LDAP directoryslapauth
: Checks a list of IDs for authentication and authorization permissions- slapcat: Generates LDIF output from an LDAP directory
slapdn
: Checks a list of distinguished names (DNs) based on schema syntaxslapindex
: Re-indexes the directory. Run slapindex whenever indexing options are changed in the configuration file.slappasswd
: Is a password utility for creating an encrypted user passwordslapschema
: Checks compliance of a database with the corresponding schemaslaptest
: Checks the LDAP server configuration
2 OpenLDAP Command Cheats
slapcat
: concatenate ldap directory in ldif format works great with grep. i.e:slapcat | grep -i group
slapcat | grep -i people
slapcat | grep -i passwd
slapcat | grep -i shadow
slapcat | grep -i uid
slapcat | grep -i dn
slapadd
: add a user (in batch)ldapadd
: add a user one at a timeldappasswd
: change a user's passwordldapsearch
: search the ldap databaseldapsearch
johnldapsearch
ldaprootldapwhoami
ldaproot
3 Background on LDAP
o LDAP = Lightweight Directory Access Protocol,
LDAPV2 defined in RFC1777 (1995)
LDAPv3 defined in RFC2251 (1997)
LDAPv3 defined in RFC4510 (2006)
A protocol for accessing data from X.500 directory services like:
- OpenLDAP
- Microsoft Active Directory, AD
- Netscape Directory Server
- Novell eDirectory
What directory?
- any database that is in a standard format, that stores attribute based data, and that is optimized for read access.
- examples are a telephone directory offers up name, address, number. a corporate email directory a username / password directory
What format?
Similar to X.500 format, but a simpler subset of X.500, X.500 stores descriptive key: value pairs, a.k.a. attribute: value pairs in a hierarchical tree-like data structure, called the Directory Information Tree (DIT).
3.1 Lightweight DAP
LDAP is an simpler alternative to the X.500 Directory Access Protocol (DAP) but it is still a hierarchical DIT
3.2 Database
A directory database is typically fairly static with reads far outstripping writes. As such they typically have:
- no transactions
- no rollback
- updates are all or nothing, or possibly not allowed at all.
- tuned for read performance, i.e. high-volume read
Implementations can use various databases. The DIT could be local to an organization, or global. A directory defines a uniform namespace, i.e. the same view is presented regardless of where queried, even in global directories.
Examples of global directory service is the Open Directory Project, dmoz.org This link will not respond to a typicall http request, but a ldap request.
Could be a relational database system, rdbs, or could be LDBS (built-in to OpenLDAP, a.k.a. slapd)
3.3 What is stored in this customized database called a "Directory"?
Typically organization and user authentication and authorization data. i.e. user rights data.
4 LDAP the protocol
LDAP is a client-server protocol.
It uses TCP, (or other connection oriented transport)
Can use UDP as well
TCP port 389 un-encrypted
TCP port 636 over SSL
TCP port 389 over negotiated TLS (tunnelled)
5 Typical terminology
LDAP : Lightweight Directory Access Protocol
DN : Distinguish Name
RDN : Relative Distinuished Name
DIT : Directory Information Tree
LDIF : LDAP Data Interchange Format
OID : Object Identifier
SASL : S authentication S L ?
DSA : Directory System Agents (X.500 servers)
5.1 Typical keys
These are the typical keys in a DIT, typically from the top down.
dc = domain component
cn = common name
ou = organizational unit
mail = email address
sn = surname
5.2 Suffix
A suffix is a branch or subtree whose entire contents are treated as a unit for admin purposes. Allows for splitting up the dit across multiple servers.
The top level tree root is called the root suffix
6 LDAP Resources
Five main online resources for LDAP are:
- ldap.com
- ldapwiki.com
- openldap.org
- itzgeek (from lab7 installation notes)
- openldap admin guide
7 Directory Structure (DIT)
7.1 DIT (Directory Information Tree)
- A single tree, with a single root.
- Hierarchical
- distributed across 1 or more servers
- Entries consist of a set of attributes
- each attribute has one or more values
- Each entry has a unique DN. ( Distinguished Name )
- Each unique DN is formed by combining its RDN, one or more attributes of the entry itself, and the RDN of each of the superior entries up to the root of the DIT. An analogy: if named.conf is the RDN, then /etc/named.conf is DN
A DN may change over the lifetime of the entry, for instance when entries are moved within a tree, from one department to another.
Below is an excerpt of a entry, when represented in the LDIF format (LDAP Data Interchange Format, LDIF):
dn: cn=John Doe,dc=zintis,dc=ops cn: John Doe givenName: John sn: Doe telephoneNumber: +1 888 555 6789 telephoneNumber: +1 888 555 1232 mail: john@example.com manager: cn=Barbara Doe,dc=example,dc=com objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top
dn is the distinguished name, i.e. cn=John Doe,dc=zintis,dc=ops
rdn is John doe, the relative distinguished name
"dn" is neither an attribute nor a part of the entry.
7.1.1 tree structure always on display
Every dn is also uniquely identified in the tree structure by the order you specify the dn. You trace from the dn, back up through the tree struture to the "top" which is the root of the tree. Rememeber that it is an upside-down tree.
7.2 Object Classes
I could try using, or adding, an attribute to an entry. Let's say people
that are registered to attend a conference will each get a polo shirt. I
could try to add and attribute:
ShirtSize: XL
But ldap would complain about that being an Object class violation". Therefore I must first define that attribute somewhere. The place where all attributes are defined, and the rules for attribute types are defined, is called a schema.
7.3 Schema
The set of rules that define the available attributes that you can use. Schemas have certain pre-defined standard attributes,
ou: organizational unit
cn: …
And user defined attributes
ShirtSize:
These attributes are defined under a set of object classes. Put another way, Attributes of the directory server are defined under object classes
Therefore, if you want to use an attribute that is defined in the directory server, you must also specify the object class of the attribute.
Have to mention which object class defines an attribute along with the attribute.
For example: The ojbect class that defines the attribute "ou" is "organizational unit:" would look like this:
dn: ou=engineering,dc=zintis,dc=ops objectClass: organizationalunit ou: engineering
You could not just do this. It would give you an error:
dn: ou=engineering,dc=zintis,dc=ops ou: engineering
7.4 Attributes:
ou
is an attribute of the domain, "dc=zintis,dc=ops"
To see all attributes, you could run slapcat
(but that also dumps
all entries which is obviously overkill unless your directory is very small.
Better to look at the schema. Can think of the schema as a template too.
7.5 path to schema
/etc/openldap/schema
The file core.schema
is included in the slapd.conf
file.
Every attriute that I define for the entries in my ldap server must match
something in this core.schema file. You can add other, additional schemas
but they must be mentioned in the slapd.conf file.
Opening up /etc/openldap/schema/core.schema
you can see the definitions
of the objectClasses. For instance, searching for organizationalUnit
will show you this:
objectclass ( 2.5.6.5 NAME 'organizationalUnit' DESC 'RFC2256: an organizational unit' SUP top STRUCTURAL MUST ou MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
That shows us that ou
is a MUST have. If you are going to use this
object class, you must have at least the ou attribute specified.
If you are going to use this object class, you also have the optional "MAY" attributes, ilke address, telephone number, etc..
7.6 Subtrees (a.k.a. subsuffix)
(not covered in OPS335) A server holds a subtree starting from a specific entry, eg. dc=zintis,dc=ops and its children
Servers may hold reference to other servers, so an attempt to access ou=department,dc=zintis,dc=ops could return a referral or continution reference to a server that holds that part of the tree.
Recursive lookups are called "chaining" were the server does the lookup of the related server, on behalf of the client. usually the server just returns the address of the other server to the client and it is up to the client to query the next server.
8 LDIF
LDAP Data Interchange Format
LDIF:
- represents LDAP enteries in text, human readable format
- allows easy modification of data
8.1 LDIF struture
It is a key-value database, implementing an upside down tree. i.e. root at the top.
Keys start the line followed by a colon space, then the value.
key: value
key: value
one key: value per line.
key: value (you need the <space> after the colon.)
- Multiple lines can be used to provide long values for attribute by beginning
the extra lines with a single space. LDAP will join these when processing the entry.
- Sequencing of items in LDIF
The order the items appear in your LDIF file must be laid out following the DIT structure, i.e. top down.
- Items separated by a blank line
Entries in the DT can have multiple key: value attributes. They are each separated by a blank line.
- List child items after their parent items
otherwise it does not make sense as where would the child go?
- Attributes or object classes must exist in the schema
Before adding a key: value pair that key must be defined in the schema which also defines the type of value, and ranges the value can have.
- DN (Distinguished name comes first)
For each item in the LDIF file, the first line must be the DN. The DN uniquely identifies a directory object within the directory object's tree. The DN mu st contain the common name (CN) of the directory object.
8.2 LDIF as input to commands
LDIF is used to represent ldap data, but also and interestingly LDIF is used as input by LDAP commands to allow adds and edits of LDAP directory data.
So your interaction with an LDAP directory DIT is going to be via LDIF files.
LDIF can describe any entry within an LDAP system, as well as any changes or modifications to the system. i.e. DIT. Changes to the LDAP DIT are simply written within .ldif files with arbitrary names, and then "applied" to the ldap dit with one of several management commands that read data from this file
- ldbmcat converts ldbm database to ldif
- ldif2ldbm coverts ldif back to ldbm database
9 OpenLDAP Components
OpenLDAP has three components
- slapd - the LDAP daemon
- libraries implementing the LDAP protocol
- OpenLDAP client software
10 OpenLDAP client
OpenLDAP provides not only a server, but also a client, openldap-clients This package includes the following command line utilities
- ldapadd: Adds entries to an LDAP directory either from a file or from standard input.
- ldapmodify: Modifies entries in an LDAP directory [ ldapmodify -a is identical to ldapadd. ]
- ldapcompare: Compares a given attribute with an LDAP directory entry
- ldapdelete: Deletes entries from an LDAP directory
- ldapexop: Performs extended LDAP operations
- ldapmodrdn: Modifies the RDN value of an LDAP directory entry
- ldappasswd: Is a password utility for an LDAP user
- ldapsearch: Is an LDAP directory search tool
- ldapurl: Is an LDAP URL formatting tool
- ldapwhoami: Performs a whoami operation on an LDAP server
There are also several GUI LDAP clients. Use at your own risk.
10.1 slapadd vs ldapadd
slapadd adds users in bulk. Your slapd(8) should not be running when you do this to ensure consistency of the database. Also slapadd may not provide naming or schema checks.
Therefore, it is advisable to use ldapadd when adding new entries into an existing directory.
- ldapadd
ldapadd adds users to an LDAP directory one at a time, with full control over options. ldapadd uses input either from a file or from standard input.
- ldapmodify: Modifies entries in an LDAP directory [ ldapmodify -a is identical to ldapadd. ]
- slapadd
usr/sbin/slapadd [-b suffix] [-c] [-d debug-level] [-f slapd.conf] [-F confdir] [-g] [-j lineno] [-l ldif-file] [-n dbnum] [-o option[=value]] [-q] [-s] [-S SID] [-u] [-v] [-w]
Slapadd is used to add entries specified in LDAP Directory Interchange Format (LDIF) to a slapd(8) database. It opens the given database determined by the database number or suffix and adds entries corresponding to the provided LDIF to the database. Databases configured as subordinate of this one are also updated, unless -g is specified. The LDIF input is read from standard input or the specified file.
All files eventually created by slapadd will belong to the identity slapadd is run as, so make sure you either run slapadd with the same identity slapd(8) will be run as (see option -u in slapd(8)), or change file ownership before running slapd(8).
11 OpenLDAP Operations
11.1 Credentials
- ldapadd -v -f jane.ldif -D cn="ldaproot,dc=andrew,dc=ops" -W
- ldapadd -v -f jane.ldif -D -x cn="ldaproot,dc=andrew,dc=ops" -W
Credentials are always needed, so you will always see -D and -w or -W in every Openldap command.
-D bind a.k.a. authentication user and tree root (top level) the credentials are for a specific user in the DIT, with a distinguished name (dn) at the top of the domain.
-w password will use simple authentication and need the password (seneca99ldap)
-W prompt for password
-x use simple authentication instead of SASL
-f apply the ldif entries from a file (jane.ldif in this case)
-v verbose
11.2 Generating an ldif file from user entry in /etc/passwd
To add a use to an ldap directory, you want that user to have the same password as the Linux password. OpenLDAP comes with tools for doing this, called "migratepasswd.pl" (in the /usr/share/migrationtools directory)
First, pull out the line from /etc/passwd for the user in question.
grep -w zintis /etc/passwd > /root/zintispasswd.entry
Then use the migration tool to genearte that user's ldif file.
cd /usr/share/migrationtools migrate_passwd.pl /root/zintispasswd.entry /root/zintisldap.ldif less /root/zintisldap.ldif
11.3 ldapadd
- ldapadd: Adds entries to an LDAP directory either from a file or from standard input.
- ldapmodify: Modifies entries in an LDAP directory [ ldapmodify -a is identical to ldapadd. ]
- ldapadd is a symbolic link to ldapmodify -a, and it is used to read a user's
ldif file and create an entry in the LDAP DIT for that user.
ldapadd -x -v -D cn="ldaproot,dc=andrew,dc=ops" -W -f zintisldap.ldif=
Credentials are always needed, so you will always see -D and -w or -W in every Openldap command.
-D bind a.k.a. authentication user and tree root (top level) the credentials are for a specific user in the DIT, with a distinguished name (dn) at the top of the domain.
-w password will use simple authentication and need the password (seneca99ldap)
-W prompt for password
-x Use simple authentication instead of SASL
-f the file that as the user info in the LDIF format.
- the distinguished name, dn, of the ldap administrator is dn: cn=ldaproot,dc=andrew,dc=ops
ldapadd -x -W -D "cn=ldaproot,dc=andrew,dc=ops" -f usertoadd.ldif
The order of options does not matter, except that file has to follow -f and the dn has to follow -D.
11.3.1 Listing Entries to Add to the DIT
The most basic method of defining new entries to add to LDAP is to simply list the entries in their entirety, exactly as they would typically displayed using LDAP tools. This starts with the DN (distinguished name) where the entry will be created, after the dn: indicator:
dn: ou=newgroup,dc=example,dc=com
In the line above, we reference a few key-value pairs in order to construct the DN for our new entry.
- : <space> for attribute values
When setting attribute values, you must use the colon and space.
- = when referencing attributes/values
When referencing attributes/values, an equal sign should be used instead.
In the simplest LDIF format for adding entries to a DIT, the rest of the entry is simply written out using this format beneath the DN definition. The necessary objectClass declarations and attributes must be set to construct a valid entry. For example, to create an organizational unit to contain the entries for the employees of our organization, we could use this
dn: ou=People,dc=example,dc=com "dc ~ domain component" objectClass: organizationalUnit ou: People
You can add multiple entries in a single file. Each entry must be separated by at least one completely blank line:
dn: ou=People,dc=example,dc=com objectClass: organizationalUnit ou: People
As you can see, this LDIF format mirrors almost exactly the format you would see when querying an LDAP tree for entries with this information. You can pretty much just write what you’d like the entry to contain verbatim.
11.4 Changetype: add"
Now if you are making several modifications within the same LDIF file, or even some mods as well as additions, OpenLDAP offers "Changetype: Add"
So, we could be modifying several entries, and adding a new entry.
It looks much like above where we were just adding new entries, but we just
add the line changetype: add
directly below the dn: specification.
Let's say your directory information tree, DIT, already has ou=People,dc=worldtour2020,dc=com Then adding like this:
dn: uid=roadie22,ou=People,dc=worldtour2020,dc=com changetype: add objectClass: inetOrgPerson description: Roadie Dude. Roadie is a contracted roadie for our North America leg of this world tour. cn: Roadie-No.22 sn: Smith uid: roadie22
11.5 BIND (AUTHENTICATE)
Most every authentication looks the same:
-D "cn=ldaproot,dc=andrew,dc=ops" -W -D "cn=admin,dc=acme,dc=com" -W -D "cn=netops,dc=cisco,dc=com" -W
This first one is the bind of the user ldaproot in the andrew.ops tree with a prompted password (-W)
The "D" refers to a Bind "dn". The distinguised name that is used to bind you to the directory.
11.6 DELETE
To delete an entry from an DIT, the process only needs the unique dn. So it is fairly easy. For instance, if we wanted to remove the ou=othergroup entry from our DIT, our LDIF file, rm-group.ldif, would only need to contain:
dn: ou=othergroup,dc=example,dc=com changetype: delete
To actually do the deletion:
ldapmodify -x -D "cn=admin,dc=example,dc=com" -W -f rm-group.ldif
11.7 ldapmodify
If you specify changetype and ommit the -a flag, then it is a true modifiy type. So if we make changes to certain fields in the .ldif file for a user, we can apply those changes in the DIT database with:
ldapmodify -x -D "cn=ldaproot,dc=andrew,dc=ops" -W -f modifyfile.ldif
-D …. -W are credentials -x use simple authentication vs SASL -f ldif file that has entries such as this:
dn: entryDN changetype: modify add: attribute attribute: value... - replace: attribute attribute: newValue... - delete: attribute [attribute: value] ...
11.7.1 Example from ops
root@vm4~[835]$ # Pre change ldapsearch -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john # extended LDIF # # LDAPv3 # base <dc=andrew,dc=ops> with scope subtree # filter: uid=john # requesting: ALL # # john, People, andrew.ops dn: uid=john,ou=People,dc=andrew,dc=ops objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: john uid: john uidNumber: 9999 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash gecos: John Someone shadowLastChange: 17058 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 userPassword:: e1NTSEF9TDkvTEUzM2tHY3h4L1FxSUZWMm0waENqeGplYURKQ04= ------------------------------------------------------------------- root@vm4~[841]$ cat changejohn.ldif cat changejohn.ldif dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify replace: cn cn: John Baldry ------------------------------------------------------------------- root@vm4~[842]$ ldapmodify -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -f changejohn.ldif modifying entry "uid=john,ou=People,dc=andrew,dc=ops" ------------------------------------------------------------------- root@vm4~[843]$ ldapsearch -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john # extended LDIF # # LDAPv3 # base <dc=andrew,dc=ops> with scope subtree # filter: uid=john # requesting: ALL # # john, People, andrew.ops dn: uid=john,ou=People,dc=andrew,dc=ops objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount uid: john uidNumber: 9999 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash gecos: John Someone shadowLastChange: 17058 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 userPassword:: e1NTSEF9TDkvTEUzM2tHY3h4L1FxSUZWMm0waENqeGplYURKQ04= cn: John Baldry # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 ------------------------------------------------------------------- root@vm4~[844]$ cat changejohn.ldif dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify replace: cn cn: John Baldry root@vm4~[845]$ vi changejohn.ldif root@vm4~[846]$ !c cat changejohn.ldif dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify replace: gecos gecos: John Long Baldry ------------------------------------------------------------------- root@vm4~[847]$ ldapmodify -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -f changejohn.ldif modifying entry "uid=john,ou=People,dc=andrew,dc=ops" root@vm4~[848]$ ldapsearch -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john # extended LDIF # # LDAPv3 # base <dc=andrew,dc=ops> with scope subtree # filter: uid=john # requesting: ALL # # john, People, andrew.ops dn: uid=john,ou=People,dc=andrew,dc=ops objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount uid: john uidNumber: 9999 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash shadowLastChange: 17058 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 userPassword:: e1NTSEF9TDkvTEUzM2tHY3h4L1FxSUZWMm0waENqeGplYURKQ04= cn: John Baldry gecos: John Long Baldry # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 ------------------------------------------------------------------- root@vm4~[849]$ cat changejohn.ldif dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify replace: gecos gecos: John Long Baldry ------------------------------------------------------------------- root@vm4~[850]$
11.8 history commands using ldapmodify from lab 7 OPS335
Can use the same ldif file repeatedly, just be editing it and re-applying the new edits with the ldapmodify command. So for example, you can have an editing window open to changejohn.ldif then writing every change, one at a time with each change applied from another windowo that has the following two commands, repeated over and over, until the changes are done.
ldapmodify -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -f changejohn.ldif ldapsearch -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john
Similarily for another user, say, "jane"
ldapmodify -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -f changejane.ldif ldapsearch -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=jane
ldapmodify -x -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -f changejane.ldif
11.9 Default host and port
These two are the same, while local host and port 389 are the defaults. ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john ldapsearch -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops uid=john
11.10 Sample change ldif files:
- replace and existing attribute:
dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify replace: gecos gecos: John Long Baldry
- Add a new attribute:
dn: uid=john,ou=People,dc=andrew,dc=ops changetype: modify add: roomNumber roomNumber: 1729
- Delete an attribute
dn: uid=john,ou=People,dc=andrew,dc=ops delete: title title: Grand Poobah
add: jpegPhoto
jpegPhoto:<
delete: description
- ldapmodify example changing a password
So if you are changing a password for user John, AND you have already chnaged the password entry in the file john.ldif, you could use the command:
ldapmodify -x -D "cn=ldaproot,dc=andrew,dc=ops" -W -H ldap:// -f john.ldif
The man page on ldapmodify provides a good examples, duplicated here:
Assuming that the file /tmp/entrymods exists and has the contents: dn: cn=Modify Me,dc=example,dc=com changetype: modify replace: mail mail: modme@example.com - add: title title: Grand Poobah - add: jpegPhoto jpegPhoto:< file:///tmp/modme.jpeg - delete: description - the command: ldapmodify -f /tmp/entrymods will replace the contents of the "Modify Me" entry's mail attribute with the value "modme@example.com", add a title of "Grand Poobah", and the contents of the file "/tmp/modme.jpeg" as a jpegPhoto, and completely remove the description attribute. : Assuming that the file /tmp/newentry exists and has the contents: dn: cn=Barbara Jensen,dc=example,dc=com objectClass: person cn: Barbara Jensen cn: Babs Jensen sn: Jensen title: the world's most famous mythical manager mail: bjensen@example.com uid: bjensen the command: ldapadd -f /tmp/newentry will add a new entry for Babs Jensen, using the values from the file /tmp/newentry. Assuming that the file /tmp/entrymods exists and has the contents: dn: cn=Barbara Jensen,dc=example,dc=com changetype: delete the command: ldapmodify -f /tmp/entrymods will remove Babs Jensen's entry.
11.11 ldappasswd
ldappasswd -s password123 -W -D "cn=ldaproot,dc=andrew,dc=ops" -x "uid=john,ou=people,dc=andrew,dc=ops"
-x username for which the password is changed -s specify the password for the username -D Distinguished name to bind (authenticate) to the LDAP server
11.12 ldapsearch
ldapsearch -x -h localhost -p 389 -D cn="Manager,dc=acme,dc=com" -W -b dc=acme,dc=com objectClass=*
-h the host where you want to search (the defaul is localhost)
-p the port 389[default] over ldap, 636 over SSL-ldap, 389 over TLS
-D is the "binding" or authentication to the server. so specify the user, and its hierarchy? This is referred to as the "bind dn" is that what cn="…." is?
-W is not a password, but asking to be prompted for a password
-b is the search base dn." It is the place where you wish to start the search. If you are using an ldif file that has the base distinguished name clearly indluded as part of the add/modify, you won't need to specify -b.
finally "objectClass=*" is the filter you want to search for.
11.12.1 Searching with objectClass = *
This is a convenient way of listing everything in an ldap database as everything in an ldap directory has an objectClass attribute, so making that * will match everything.
ldapsearch -D cn="Manager,dc=acme,dc=com" -b dc=acme,dc=com objectclass=*
11.12.2 ldapsearch anonymously.
Typically some organizations require you to have a proper login, but some organizations allow anonymous searches. Depends on the company and what is being searched.
ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" -W -b dc=andrew,dc=obs objectClass=* ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" -W -b dc=andrew,dc=obs objectclass=* -W -b dc=andrew,dc=ops objectclass=*
- h localhost -p 389 /* these are the defaults so optional
- D cn="ldaproot,dc=andrew,dc=ops" # known as the Bind cn because it is the authentiction piece
- W /* prompt for a password vs -w <secrtpass>
- b dc=andrew,dc=obs # know as the base
- objectclass=* # the filter object. i.e. search entries where the objectclass=* which would result in searches for EVERYTHING
/* as every directory entry must have an objectclass
- -h localhost and -p 389 are defaults so they can be omitted.
The search becomes:
ldapsearch -D cn="ldaproot,dc=andrew,dc=ops" -W -b dc=andrew,dc=ops objectclass=* # extended LDIF # # LDAPv3 # base <dc=andrew,dc=obs> with scope subtree # filter: objectClass=* # requesting: ALL #
If things go right:
# search result search: 2 result: 0 Success # numResponses: 9 # numEntries: 8
If things do NOT go right.
# search result search: 2 result: 32 No such object # numResponses: 1
11.13 ldapsearch and grep vs slapcat and grep
The following example shows that the results of these two operations are the same, even though the way they were queried are very different:
root@vm4~[798]$ ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" -w seneca99ldap -b dc=andrew,dc=ops objectClass=* | grep "dn:" dn: dc=andrew,dc=ops dn: cn=ldaproot,dc=andrew,dc=ops dn: ou=People,dc=andrew,dc=ops dn: ou=Group,dc=andrew,dc=ops dn: uid=john,ou=People,dc=andrew,dc=ops dn: uid=zintis,ou=People,dc=andrew,dc=ops dn: uid=jane,ou=People,dc=andrew,dc=ops dn: uid=guest,ou=People,dc=andrew,dc=ops dn: uid=deleteme,ou=People,dc=andrew,dc=ops root@vm4~[799]$ slapcat | grep "dn:" 5e8397f1 The first database does not allow slapcat; using the first available one (2) dn: dc=andrew,dc=ops dn: cn=ldaproot,dc=andrew,dc=ops dn: ou=People,dc=andrew,dc=ops dn: ou=Group,dc=andrew,dc=ops dn: uid=john,ou=People,dc=andrew,dc=ops dn: uid=zintis,ou=People,dc=andrew,dc=ops dn: uid=jane,ou=People,dc=andrew,dc=ops dn: uid=guest,ou=People,dc=andrew,dc=ops dn: uid=deleteme,ou=People,dc=andrew,dc=ops root@vm4~[800]$
11.14 UNBIND
"Binding means authentication." So the unbind operation simply abandons any outstanding operations and closes the connection. Think of it "logoff".
It has no response. The name is of historical origin, and is NOT the opposite Bind.
Using Linux commandline ldapxxx commands are one-offs and you don't need to unbind, or rather every command finishes by undbinding. So you need to bind again at each new command.
12 LDAP URI Scheme
LDAP URI (uniform resource identified) scheme exists. Clients support it to a varying level. ldap://host:port/DN?attributes?scope?filter?extensions
- host is the FQDN or IP address of the LDAP server to search.
- port is the network port (default port 389) of the LDAP server.
- DN is the distinguished name to use as the search base.
- attributes is a comma-separated list of attributes to retrieve.
- scope specifies the search scope and can be "base" (the default), "one" or "sub".
- filter is a search filter. For example, (objectClass=*) as defined in RFC 4515.
- extensions are extensions to the LDAP URL format.
For example, ldap://ldap.example.com/cn="John Doe,dc=example,dc=com" refers to all user attributes in John Doe's entry in ldap.example.com, while "ldap:///dc=example,dc=com??sub?(givenName=John)" searches for the entry in the default server (note the triple slash, omitting the host, and the double question mark, omitting the attributes). As in other URLs, special characters must be percent-encoded.
There is a similar non-standard ldaps URI scheme for LDAP over SSL. This should not be confused with LDAP with TLS, which is achieved using the StartTLS operation using the standard ldap scheme.
13 SASL
From ldapwiki.com and I quote: Simple Authentication and Security Layer (SASL) is a framework for Authentication and data Security Layer that can provide data integrity, data confidentiality, and other services for Internet Protocols
SASL allows Authentication Method to be decoupled from application protocols, in theory allowing any Authentication Method supported by SASL to be used in any application protocol that uses SASL.
Authentication Methods may also support Delegation. They may also provide a data Security Layer offering data integrity and data confidentiality services.
DIGEST-MD5 provides an example of mechanisms which can provide a data Security Layer.
The original SASL specification RFC 2222 while at Carnegie Mellon University. In 2006 that document was made obsolete by RFC 4422, but a number of specific SASL Mechanisms are described in other specifications. [2]
As SASL Mechanisms are External to the Protocol, they may be referred to as EXTERNAL SASL Mechanism even though the SASL Mechanism may reside on and be done on by the same server.
Generic Operation [1]# The basic operation of SASL is straightforward. The server provides a list of supported authentication mechanisms, and then the client determines which of the supported authentication mechanisms will be used (based on the client’s capabilities and security requirements. Protocols that contain SASL support include:
LDAP (Internet Standard Lightweight Directory Access Protocol)
SMTP (Internet Standard Simple Message Transfer Protocol)
POP3 (Internet Standard Post Office Protocol v3)
IMAP (Internet Standard Internet Mail Access Protocol)
XMPP: Extensible Messaging and Presence Protocol
Isode's SOM (Switch Operations and Management) Protocol
To be used with SASL, a new authentication mechanism needs to be registered, and any authentication mechanism specific capabilities need to be agreed upon.
14 Examples from lab 7, Seneca OPS335
14.1 ldapusers.ldif
dn: uid=zintis,ou=People,dc=andrew,dc=ops uid: zintis cn: zintis sn: zintis mail: zintis@zintis.ops objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount objectClass: top objectClass: shadowAccount userPassword: {crypt}$6$mjRyTHR5$ARM0BM7g1dPc422iHK3BGVHqcXVty0FETrE6yj/N47sudpjivy0ExxSNpvzW. shadowLastChange: 18348 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/bash uidNumber: 10000 gidNumber: 10000 homeDirectory: /home/zintis
14.2 slapcat output from original directory
slapcat 5e80f53b The first database does not allow slapcat; using the first available one (2) dn: dc=andrew,dc=ops dc: andrew objectClass: top objectClass: domain structuralObjectClass: domain entryUUID: 0192e632-da18-1038-83ca-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313201201Z entryCSN: 20190313201201.126862Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190313201201Z dn: cn=ldaproot,dc=andrew,dc=ops objectClass: organizationalRole cn: ldaproot description: LDAP Manager structuralObjectClass: organizationalRole entryUUID: 019a13f8-da18-1038-83cb-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313201201Z entryCSN: 20190313201201.174170Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190313201201Z dn: ou=People,dc=andrew,dc=ops objectClass: organizationalUnit ou: People structuralObjectClass: organizationalUnit entryUUID: 01a1a870-da18-1038-83cc-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313201201Z entryCSN: 20190313201201.223848Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190313201201Z dn: ou=Group,dc=andrew,dc=ops objectClass: organizationalUnit ou: Group structuralObjectClass: organizationalUnit entryUUID: 01ac22f0-da18-1038-83cd-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313201201Z entryCSN: 20190313201201.292521Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190313201201Z dn: uid=john,ou=People,dc=andrew,dc=ops objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: john uid: john uidNumber: 9999 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash gecos: John Someone shadowLastChange: 17058 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 structuralObjectClass: account entryUUID: bfa78756-da1b-1038-83d1-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313203848Z userPassword:: e1NTSEF9a0ljTGtXdVkxNXBQL0labDN3TklBaE5MSm94cWU4ZVQ= entryCSN: 20190709215232.858989Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190709215232Z
14.3 Adding user zintis to directory:
This ldapusers.ldif file had an error that shows up with error: "no global superior knowledge"
root@vm4~[604]$ ldapadd -v -f ldapusers.ldif -D cn="ldaproot,dc=zintis,dc=ops" -W ldap_initialize( <DEFAULT> ) Enter LDAP Password: seneca99ldap add uid: zintis add cn: zintis add sn: zintis add mail: zintis@zintis.ops add objectClass: person organizationalPerson inetOrgPerson posixAccount top shadowAccount add userPassword: {crypt}$6$mjRyTHR5$ARM0hiRWKGdBM7g1dPc422i4Ut9TQ7HKty0FETrE6yj/NxudpjitlrhkNpvzW. add shadowLastChange: 18348 add shadowMin: 0 add shadowMax: 99999 add shadowWarning: 7 add loginShell: /bin/bash add uidNumber: 10000 add gidNumber: 10000 add homeDirectory: /home/zintis adding new entry "uid=zintis,ou=People,dc=zintis,dc=op"s ldap_add: Server is unwilling to perform (53) additional info: no global superior knowledge root@vm4~[604]$
The error above occurs because we were trying to add entries specified for the zintis.ops tree, where the tree was actually andrew.ops.
Fix was to correct the config file in : /usr/share/migrationtools/migrate-passwd.pl so that the migratepasswd step would generate ldif data correctly (i.e. dc=andrew,dc=ops)
14.4 Error "no global superior knowledge"
This specific error means that slapd doesn't know where to put the new entry. This typically means that you have not defined an appropriate database, or you have made a typo in the higher in the tree. With newer systems (ones using cn=config instead of slapd.conf), you would typically first add a new database or modify an existing database entry using ldapadd or ldapmodify.
For example, let's say you are trying to add
"uid=zintis,ou=People,dc=zintis,dc=ops"
But you are in a tree with dc=zint,dc=ops slapd cannot find the root
tree dc=zint,dc=ops so it says "No superior knowledge".
14.5 Adding three users to ldap
useradd zintis -u 10000 useradd -c "Jane Greystoke" jane -u 10001 useradd -c "Andrew's Guests" guest -u 10002 if user jane already exists, delete her with userdel jane also chown her mailbox with chown jane /var/spool/mail/jane And delete /var/spool/mail/andrew grep -w zintis /etc/passwd > /root/zintis.entry grep -w Jane /etc/passwd > /root/jane.entry grep -w Andrew /etc/passwd > /root/guest.entry /usr/share/migrationtools/migrate_passwd.pl /root/zintis.entry /root/zintis.ldif /usr/share/migrationtools/migrate_passwd.pl /root/jane.entry /root/jane.ldif /usr/share/migrationtools/migrate_passwd.pl /root/guest.entry /root/guest.ldif ldapadd -v -f ldapusers.ldif -D cn="ldaproot,dc=andrew,dc=ops" -W ldapadd -v -f jane.ldif -D cn="ldaproot,dc=andrew,dc=ops" -W ldapadd -v -f guest.ldif -D cn="ldaproot,dc=andrew,dc=ops" -W
14.6 Changing an existing user's password
slapcat shows user John as:
dn: uid=john,ou=People,dc=andrew,dc=ops objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: john uid: john uidNumber: 9999 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash gecos: John Someone shadowLastChange: 17058 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 structuralObjectClass: account entryUUID: bfa78756-da1b-1038-83d1-ef40d5fa4d01 creatorsName: cn=ldaproot,dc=andrew,dc=ops createTimestamp: 20190313203848Z userPassword:: e1NTSEF9a0ljTGtXdVkxNXBQL0labDN3TklBaE5MSm94cWU4ZVQ= entryCSN: 20190709215232.858989Z#000000#000#000000 modifiersName: cn=ldaproot,dc=andrew,dc=ops modifyTimestamp: 20190709215232Z
14.6.1 Change John's password with ldapppasswd
ldappasswd -s Jan1sparole -W -D "cn=ldaproot,dc=andrew,dc=ops" -x "uid=john,ou=people,dc=andrew,dc=ops"
14.6.2 Confirm the change with ldapsearch
ldapsearch -h localhost -p 389 -D cn="ldaproot,dc=andrew,dc=ops" -W -b dc=andrew,dc=ops uid=john
15 ldap client
To let a VM authenticate to an ldap server.
15.1 Install the necessary LDAP client packages on the client machine.
This is PAM the "Pluggable Authentication Module" and NSS the "Name Service Switch"
yum install -y openldap-clients nss-pam-ldapd Since CentOS8 does not see nss-pam-ldap I did the following:
First: dnf provides nss-pam-ldapd Then, based on the above this: dnf install -y nss-pam-ldapd-0.9.9-3.el8.x8664
15.2 About nss-pam-ldapd
From arthurdejong.org: This is nss-pam-ldapd which provides a Name Service Switch (NSS, nsswitch) module that allows your LDAP server to provide user account, group, host name, alias, netgroup, and basically any other information that you would normally get from /etc flat files or NIS. It also provides a Pluggable Authentication Module (PAM) to do identity and authentication management with an LDAP server on unix systems.
This is implemented using thin NSS and PAM modules which delegate to a dedicated service (nslcd) that queries the LDAP server with persistent connections, authentication, attribute translation, etc.
The NSS module was originally a fork of nssldap with some structural design improvements. The most important features of nss-pam-ldapd are:
- light and simple NSS and PAM libraries
- avoid loading LDAP and SSL libraries in all programs
- separation between NSS, PAM and LDAP code
- fewer connections to the LDAP server
- better debugging possibilities
- better performance
- See the documentation section for more detai
16 Configuring LDAP Authentication on CentOS 8
From tylers guides I have dnf installed nss-pam-ldapd, and nss ? which one?
I have edited /etc/nslcd.conf according to tyler's website
I skipped the TLS section.
And I have enbled and started nslcd
I have authselect ready to go, after running these commands as root with the goal of replacing the SSSD related text with NSLCD equivalent in the relevant files.
root@vm1/etc[1038]$ tar cf /root/pre-ldap-config.tar nsswitch.conf pam.d root@vm1/etc[1039]$ date Mon Mar 30 18:52:43 EDT 2020
authselect select custom/nslcd –force Profile "custom/nslcd" was selected. The following nsswitch maps are overwritten by the profile:
- passwd
- group
- netgroup
- automount
- services
Make sure that NSLCD service is configured and enabled. See NSLCD documentation for more information.
16.1 Centos7 only (I think: )
Configure the client VM to use LDAP To add the client machine to LDAP server for single sign-on. Replace “192.168.1.10” with your LDAP server’s IP address or hostname.
authconfig –enableldap –enableldapauth –ldapserver=192.168.1.10 –ldapbasedn="dc=itzgeek,dc=local" –enablemkhomedir –update
Restart the LDAP client service. O.K, so this will make this VM defer logins to the LDAP server rather than looking in its own /etc/passwd file ??? That would mean that the users defined in the ldap server would require a local prescence on this VM, including home directory, and entry in /etc/passwds. I guess this is just centralizing the passwords themselves I guess?? Confirm this!
systemctl restart nslcd To verify LDAP Login, use the getent command to get the LDAP entries from the LDAP server.
getent passwd raj
Output:
raj:x:9999:100:Raj [Admin (at) ITzGeek]:/home/raj:/bin/bash Screenshot:
OpenLDAP Server Configuration on CentOS 7 - Verify LDAP Login OpenLDAP Server Configuration on CentOS 7 – Verify LDAP Login
To verify the LDAP, log in using the LDAP user “raj” on the client machine. Like this:
16.2 LDAP Youtube Videos:
These two videos explain LDAP nicely. Worth the 40 minutes of watching.
17 Appendix 1 LDAP Response codes:
Easiest just to look them up.
Result Code Name | Code |
---|---|
success | 0 |
operationsError | 1 |
protocolError | 2 |
timeLimitExceeded | 3 |
sizeLimitExceeded | 4 |
compareFalse | 5 |
compareTrue | 6 |
authMethodNotSupported | 7 |
strongerAuthRequired | 8 |
referral | 10 |
adminLimitExceeded | 11 |
unavailableCriticalExtension | 12 |
confidentialityRequired | 13 |
saslBindInProgress | 14 |
noSuchAttribute | 16 |
undefinedAttributeType | 17 |
inappropriateMatching | 18 |
constraintViolation | 19 |
attributeOrValueExists | 20 |
invalidAttributeSyntax | 21 |
noSuchObject | 32 |
aliasProblem | 33 |
invalidDNSyntax | 34 |
isLeaf | 35 |
aliasDereferencingProblem | 36 |
inappropriateAuthentication | 48 |
invalidCredentials | 49 |
insufficientAccessRights | 50 |
busy | 51 |
unavailable | 52 |
unwillingToPerform | 53 |
loopDetect | 54 |
sortControlMissing | 60 |
offsetRangeError | 61 |
namingViolation | 64 |
objectClassViolation | 65 |
notAllowedOnNonLeaf | 66 |
notAllowedOnRDN | 67 |
entryAlreadyExists | 68 |
objectClassModsProhibited | 69 |
resultsTooLarge | 70 |
affectsMultipleDSAs | 71 |
virtualListViewError | or |
other | 80 |
serverDown | 81 |
localError | 82 |
encodingError | 83 |
decodingError | 84 |
timeout | 85 |
authUnknown | 86 |
filterError | 87 |
userCanceled | 88 |
paramError | 89 |
noMemory | 90 |
connectError | 91 |
notSupported | 92 |
controlNotFound | 93 |
noResultsReturned | 94 |
moreResultsToReturn | 95 |
clientLoop | 96 |
referralLimitExceeded | 97 |
invalidResponse | 100 |
ambiguousResponse | 101 |
tlsNotSupported | 112 |
intermediateResponse | 113 |
unknownType | 114 |
canceled | 118 |
noSuchOperation | 119 |
tooLate | 120 |
cannotCancel | 121 |
assertionFailed | 122 |
authorizationDenied | 123 |
e-syncRefreshRequired | 4096 |
noOperation | 16654 |
18 Files / Directories
From my vm4 CentOS8 guest I have:
- /root/ldapusers.entry
- /root/ldapusers.ldif
- ~/bin/backup-ldap-config.bash
- /etc/openldap