Centos openldap installation¶
- Title:
Centos ldap installation/configuration
- Author:
Douglas O’Leary <dkoleary@olearycomputers.com>
- Description:
Notes/links for installation of ldap on centos
- Disclaimer:
Standard: Use the information that follows at your own risk. If you screw up a system, don’t blame it on me…
Overview:¶
There are a number of good tutorials out there on getting openldap installed, running, and authenticating. This isn’t a tutorial; but, a checklist of steps that I’ve been able to repeat a number of times.
Three important lessons learned from this exercise:
Most of the tutorials on the net start with Edit the slapd.conf.bak file. Problem is, rhel6/centos6 don’t supply that file - at least not where all the tutorials say it should be. It’s supplied as /usr/share/openldap-servers/slapd.conf.obsolete. In case, for whatever reason, redhat stops supplying that file at all, it’s included at the tail end of this doc.
All of the tutorials say Thou shalt not edit the ldif files under /etc/openldap/slap.d. Well, turns out you can. (1) slapd has to be off and (2) you have to be very careful, though, as a mistake will prevent your ldap server from starting. I was going that route to get the server going in the first place when I finally found the slapd.conf.obsolete file.
And the big one: By default, there are two main and mutually exclusive methods of grouping people in ldap. The classes are posixgroup and groupofnames. Rfc2307bis bridges that mutual exclusivity but, for reasons with which I’m unfamiliar, it’s been deleted by the IETF. I have a much more detailed discussion of the issue at http://www.olearycomputers.com/ll/ldap/openldap_groups.html There seemingly is no way to enable rfc2307bis schema after the directory’s built as it replaces the nis.schema and you can’t delete a schema after it’s enabled. Since rfc2307bis provides additional options and flexibility, from my perspective, there’s no reason not to use rfc2307bis, so I’m suggesting that it be enabled from the start. This guide will demonstrate how to do that, including how to configure authentication to take advantage of it.
Alot of the process was taken from this site which is an excellent tutorial; walking the reader through stages installation and configuration. Excellent job; it was very helpful.
This checklist covers installation and configuration of an ldap server for my company. Replace domains and IPs as needed. It also covers configuring ldap authentication on clients both legacy and sssd. For reasons that I haven’t explored yet, one client insists on legacy authentication even for rhel6 systems so my goal was to figure out how to support that.
So, short version: following these steps will get you a functioning openldap server with the following:
Rfc2307bis schema to enable groupofnames and posixaccount compatibility.
Memberof module and overlay to enable memberof syntax and searches.
Basic ACLs to cover the shadow passwords.
Ppolicy module and overlay to enable password aging and expiration.
The ability to configure other linux systems to authenticate against the server.
Good luck; let me know if there’s anything that’s unclear or mistaken.
Creating ldap directory server:¶
Install required packages:
openldap-servers
openldap-clients
migrationtools
perl-LDAP # req for the ldap wrapper script.
Edit /etc/sysconfig/ldap; ensure ldap, ldapi, and ldaps are enabled. We’ll disable ldap (unsecure) later.
ldapi will be used for directory configuration updates
ldaps will be used for normal operations
ldap will be used for verification of initial set up.
Update firewall rules to allow port 636 (ldaps). If using /etc/sysconfig/iptables
Add two lines to file:
-A INPUT -m state --state NEW -m udp -p udp --dport 636 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 636 -j ACCEPT
service iptables restart
If going w/rfc2307bis:
Download the rfc2307bis schema:
cd /etc/openldap/schema wget http://www.grotan.com/ldap/rfc2307bis.schema
Comment out uidnumber and gidnumber OIDs in /etc/openldap/schema/rfc2307bis.scema to avoid duplication errors. These are the first two entries, so easy to find. Comment the entire stanza, not just the attributetype line.
Copy, edit initial splad.conf file:
/usr/share/openldap-servers/slapd.conf.obsolete -> /etc/openldap/slapd.oci.conf
If going with rfc2307bis
Remove nis.schema and add rfc2307bis schema using the same syntax.
In the indices section of the database definition, remove memberUID from the indecies as it doesnt’ exist anymore.
Change:
Manager -> admin
my-domain -> oci
Add rootpw in the bdb section below the rootdn. Use
slappasswd
to get a hash of the password and use that. Unencrypted passwords are bad, m’kay?
Edit ldap.conf,
update BASE and URI
Leave ldap (port 389) enabled for the time being - it’s blocked by the firewall so it’s local only.
Create startup ldif files:
# Root entry dn: dc=oci,dc=com objectclass: dcObject objectclass: organization o: OLeary Computers dc: oci # Admin DN dn: cn=admin,dc=oci,dc=com objectclass: organizationalRole cn: admin # Base DN for users dn: ou=users,dc=oci,dc=com changetype: add objectclass: top objectclass: organizationalUnit ou: users # Base DN for groups dn: ou=groups,dc=oci,dc=com changetype: add objectclass: top objectclass: organizationalUnit ou: groups
Initialize slapd.d config:
rm -fr /etc/openldap/slapd.d/* /var/lib/ldap/*
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
`` echo “” | slapadd -f /etc/openldap/slapd.oci.conf``
slaptest -f /etc/openldap/slapd.oci.conf -F /etc/openldap/slapd.d
Initialize directory entries:
slapadd -l /root/working/ldap/oci.com.ldif
slapadd -l /root/working/ldap/admin.oci.com.ldif
chown -R ldap:ldap /var/lib/ldap /etc/openldap/slapd.d
Start up slapd and verify:
service slapd start
Verify with
ldapsearch -x -b 'dc=oci,dc=com'
Add users and groups then verify:
ldapadd -x -D "cn=admin,dc=oci,dc=com" -w ${pwd} -f /root/working/ldap/users.oci.com.ldif
ldapadd -x -D "cn=admin,dc=oci,dc=com" -w ${pwd} -f /root/working/ldap/groups.oci.com.ldif
ldapsearch -x -b 'dc=oci,dc=com'
NOTE: db:config is set up to allow uid:gid 0:0 (root:root) only, based on access to lines in the original slapd.oci.conf. cn=admin,dc=oci,dc=com is root for db:bdb. Theoretically, I could set up (os) root to have access to db:bdb too.
Update defaults in migrate_common.ph, create test user and ldif files:
vi /usr/share/migrationtools/migrate_common.ph
People -> users
Group -> groups
Update DEFAULT_MAIL_DOMAIN
Update DEFAULT_BASE
groupadd -g 100000 qwer
useradd -u 100000 -g qwer qwer
passwd qwer
grep qwer /etc/passwd | /usr/share/migrationtools/migrate_passwd.pl - qwer.passwd.ldif
grep qwer /etc/group | /usr/share/migrationtools/migrate_group.pl - qwer.group.ldif
If using rfc2307bis, update qwer.group.ldif to include
objectclass: groupofnames
member: cn=admin,dc=oci,dc=com
# cat qwer.group.ldif dn: cn=qwer,ou=groups,dc=oci,dc=com objectClass: posixGroup objectclass: groupofnames objectClass: top cn: qwer userPassword: {crypt}x gidNumber: 100000 member: cn=admin,dc=oci,dc=com
Add test user to directory, verify, then delete him from the system.
ldapadd -x -D "cn=admin,dc=oci,dc=com" -w "${pwd}" -f ./qwer.group.ldif
ldapadd -x -D "cn=admin,dc=oci,dc=com" -w "${pwd}" -f ./qwer.passwd.ldif
ldapsearch -LLL -x -b 'dc=oci,dc=com'
userdel -r qwer
Certificates:
Update certificate definitions in directory:
# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config \* | \ grep -i ^olctlscert SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 olcTLSCertificateFile: "OpenLDAP Server" olcTLSCertificateKeyFile: /etc/openldap/certs/password # cat /root/working/ldap/add.certificate.conf.ldif dn: cn=config changetype: modify replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/pki/tls/certs/slapdcert.pem - replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/pki/tls/certs/slapdkey.pem - # ldapmodify -Y EXTERNAL -H ldapi:/// \ -f /root/working/ldap/add.certificate.conf.ldif [[snip]] # ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config \* | \ grep -i ^olctlscert SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 olcTLSCertificateFile: /etc/pki/tls/certs/slapdcert.pem olcTLSCertificateKeyFile: /etc/pki/tls/certs/slapdkey.pem
Generate server key and cert request:
openssl req -new -nodes -keyout \ /etc/pki/tls/private/ldapsvr.oci.com.key \ -out /etc/pki/tls/ldapsvr.oci.com.csr
Get the cert signed. The author of the tutorial also has steps for generating your own Certificate Authority so you can sign your certs w/o having to go through verisign. The locally signed certs obviously aren’t as trustworthy as ones from the major vendors; but, they work for this purpose. His checkist is available at: http://spectlog.com/content/Create_Certificate_Authority_(CA)_instead_of_using_self-signed_Certificates
I have one, too, but I think his is more recent. Mine was taken right from the openssl book and doesn’t reflect the directory structure that comes w/rhel6. My page, if you’re interested, is at http://www.olearycomputers.com/ll/misc_openssl_ca.html
Obtain the signed cert:
scp caauth:/etc/pki/CA/certs/ldapsvr.olearycomputers.com.crt /tmp
Retrieve and update CA cert:
# pwd /etc/pki/tls # scp caauth:/etc/pki/CA/cacert.pem certs # hash=$(openssl x509 -noout -hash -in certs/cacert.pem ) # echo ${hash} aa65d400 # ln -s /etc/pki/tls/certs/cacert.pem /etc/pki/tls/certs/${hash}.0 # ll certs/${hash}.0 lrwxrwxrwx. 1 root root 29 Jan 5 08:39 certs/aa65d400.0 -> /etc/pki/tls/certs/cacert.pem # openssl verify /tmp/ldapsvr.olearycomputers.com.crt /tmp/ldapsvr.olearycomputers.com.crt: OK
Copy newly created keys into the place:
# cp /etc/pki/tls/private/ldapsvr.oci.com.key \ /etc/pki/tls/certs/slapdkey.pem # cp /tmp/ldapsvr.olearycomputers.com.crt \ /etc/pki/tls/certs/slapdcert.pem # openssl verify /etc/pki/tls/certs/slapdcert.pem /etc/pki/tls/certs/slapdcert.pem: OK # chown root:ldap /etc/pki/tls/certs/slapdcert.pem \ /etc/pki/tls/certs/slapdkey.pem # chmod 750 /etc/pki/tls/certs/slapdkey.pem
Disable ldap (port 389):
Set SLAPD_LDAP=no in /etc/sysconfig/ldap; restart slapd
Update firewall rules, if needed.
Set TLS_REQCERT allow in /etc/openldap/ldap.conf. Temporary measure while I figure out what’s up with the certificates. allow enables the sesssion to continue if there’s no cert or a bad one is provided. I have verified, via wireshark, that the data is, in fact, encrypted. If someone knows why this isn’t working, a tip would be appreciated.
In /etc/openldap/ldap.conf, remove or replace ldap uri with ldaps. ldaps should be the only one left.
Verify output from
ldapsearch -x -b dc=oci,dc=com
Since ldap is disabled and cli switches don’t allow for ldapi, this is going through port 636. Use wireshark on the ldap server to verify port and encryption.
Cert lessons learned:
The host used in the URI must match the cn used in the signed cert. If it doesn’t, you’ll get bind errors unless tls_reqcert is set to allow (basically, use certs that can’t be authenticated).
tls_cacert (caps in ldap.conf, lower case in authentication files) can specify the name of the CA pem file directly. You can also use tls_cacertdir; but, the contents of that must be set in a specific way. Short version: if you’re not sepcifying the cacert retrieval in the authconfig line, specify the file directly with ldap_tls_cacert = /etc/openldap/cacerts/cacert.pem (for instance)
ACLs: protect shadow password:
Create access.ldif:
# cat access1.ldif ## BDB access control list dn: olcDatabase={2}bdb,cn=config changetype: modify replace: olcAccess olcAccess: {0}to attrs=userpassword by self write by anonymous auth by * none olcAccess: {1}to attrs=shadowlastchange by self write by * none olcAccess: {2}to * by self write by * read
Apply it:
# ldapmodify -Y EXTERNAL -H ldapi:/// -f /root/working/ldap/access.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={2}bdb,cn=config"
To delete, use:
## BDB access control list dn: olcDatabase={2}bdb,cn=config changetype: modify delete: olcAccess olcAccess: {0}
The syntax is incredibly touchy. It took way longer than it should to get those two simple processes down.
If using rfc2307bis, Enable memberof module/overlay:
This seems to have zero functionality if not using the rfc2307bis schema.
Create memberof ldif to add module and overlay:
dn: cn=module,cn=config cn: module objectClass: olcModuleList objectclass: top olcModuleLoad: memberof.la olcModulePath: /usr/lib64/openldap dn: olcOverlay=memberof,olcDatabase={2}bdb,cn=config objectclass: olcconfig objectclass: olcMemberOf objectclass: olcoverlayconfig objectclass: top olcoverlay: memberof
Add it to the cn=config:
ldapadd -Y EXTERNAL -H ldapi:/// -f ./memberof.ldif
I wasn’t able to retrieve memberof searches until I added yet another group and then they all started working. To me, this implies that the memberof functionality is indexed somehow and wasn’t re-indexed until I added another group. I would think there’d be some way of forcing that outside of adding a group; but, no information on that yet.
Enable password policy module and overlay:
Enable module and install overlay:
# cat ppolicy_module_overlay.ldif dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModuleLoad: ppolicy olcModulePath: /usr/lib64/openldap dn: olcOverlay=ppolicy,olcDatabase={2}bdb,cn=config objectClass: olcPPolicyConfig olcOverlay: ppolicy olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=com # olcPPolicyUseLockout: TRUE # olcPPolicyHashCleartext: TRUE # ldapadd -Y EXTERNAL -H ldapi:/// -f ./ppolicy_module_overlay.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=module,cn=config" adding new entry "olcOverlay=ppolicy,olcDatabase={2}bdb,cn=config"
Define a password policy. A fairly generic one that defines the following is listed below:
password attribute is userPassword
Password history is 8
Minimum password length is 8
3 bad passwords in 15 minutes before account is locked
Passwords must change after adminsitrative update.
Password max age 90 days
Password expiration warning set to 7 days.
# cat policies.oci.com.ldif dn: ou=policies,dc=oci,dc=com objectClass: organizationalUnit objectClass: top ou: policies dn: cn=default,ou=policies,dc=oci,dc=com cn: default objectClass: top objectClass: device objectClass: pwdPolicyChecker objectClass: pwdPolicy pwdAttribute: userPassword pwdInHistory: 8 pwdMinLength: 8 pwdMaxFailure: 3 pwdFailureCountInterval: 900 pwdCheckQuality: 1 pwdMustChange: TRUE pwdGraceAuthNLimit: 0 pwdMaxAge: 7776000 pwdExpireWarning: 604800 pwdLockoutDuration: 300 pwdLockout: TRUE
Add the policy:
# ldapadd -xD ${rootdn} -w "${rootpw}" -f ./policies.oci.com.ldif adding new entry "ou=policies,dc=oci,dc=com" adding new entry "cn=default,ou=policies,dc=oci,dc=com"
Legacy authentication:¶
NOTE1: I haven’t tried this on a rhel5 (or earlier) box yet; works on rhel6.
NOTE2: I also haven’t had a chance to test the legacy authentication against the rfc2307bis schema yet. For sssd, I had to ensure it was aware that I was using rfc2307bis and tell it the attribute which defines group membership.
NOTE3: I just reinstalled everything and am having issues with the sssd again, go figure. I’ll post notes regarding what I find when I get a solution; but, for the moment, take the info that follows with a grain of salt.
Install required packages:
yum -y install openldap-clients nss-pam-ldapd
Set FORCELEGACY=yes in /etc/sysconfig/authconfig
Run
authconfig
:authconfig --enableldap --enableldapauth \ --ldapserver=ldaps://ldapsvr.olearycomputers.com \ --ldapbasedn="dc=oci,dc=com" --enablemkhomedir \ --ldaploadcacert=ftp://192.168.122.1/pub/CA/cacert.pem --update
enableldap, enableldapauth, ldapbasedn are self explanatory
ldapserver must match the cn used in the signed cert. If it doesn’t, you’ll get bind errors.
enablemkhomedir adds the appropriate entry to /etc/pam.d/system-auth to automatically create home directories upon access. Verify proper settings.
ldaploadcacert defines the url from which to get the Certificate Authority’s (not the ldap server’s) public key. It will use the proper commands so that tls_cacertdir entries are honored.
Verify output from
ldapsearch -x -b dc=oci,dc=com
Verify:
authentication works:
getent passwd qwer
ssh/mkhomedir work by accessing account.
ssh -l qwer client1
sssd authentication:¶
NOTE: pretty much the same thing minus the forcelegacy entry in /etc/sysconfig/authconfig and you don’t need nss-pam-ldapd…
Install required packages:
yum -y install openldap-clients
Run
authconfig
:authconfig --enableldap --enableldapauth \ --ldapserver=ldaps://ldapsvr.olearycomputers.com \ --ldapbasedn="dc=oci,dc=com" --enablemkhomedir \ --ldaploadcacert=ftp://192.168.122.1/pub/CA/cacert.pem --update
enableldap, enableldapauth, ldapbasedn are self explanatory
ldapserver must match the cn used in the signed cert. If it doesn’t, you’ll get bind errors.
enablemkhomedir adds the appropriate entry to /etc/pam.d/system-auth to automatically create home directories upon access. Verify proper settings.
ldaploadcacert defines the url from which to get the Certificate Authority’s (not the ldap server’s) public key. It will use the proper commands so that tls_cacertdir entries are honored.
Organize /etc/sssd/sssd.conf. Not really required, but it’ll make long term support much easier. I put the sssd stanza at the top, aligned the equals in the domain/default, and groups the entries. A listing is below.
Add rfc2307bis related entries to domain/default:
ldap_schema = rfc2307bis
ldap_group_member = member
If required, add
ldap_tls_reqcert = allow
until I figure out those doubly damned certs…Verify output from
ldapsearch -x -b dc=oci,dc=com
Verify:
authentication works:
getent passwd qwer
ssh/mkhomedir work by accessing account.
ssh -l qwer client1
sssd.conf file:
# cat sssd.conf [sssd] services = nss, pam config_file_version = 2 domains = default [domain/default] id_provider = ldap auth_provider = ldap chpass_provider = ldap cache_credentials = True ldap_search_base = dc=oci,dc=com ldap_schema = rfc2307bis ldap_group_member = member ldap_uri = ldaps://ldapsvr.olearycomputers.com ldap_tls_cacertdir = /etc/openldap/cacerts ldap_tls_reqcert = allow krb5_realm = EXAMPLE.COM krb5_server = kerberos.example.com [[empty sections snipped]]
Summary:¶
That should do it. Next step would be to add users, configure which users can access which systems and add anything else you may be looking for from your ldap server.
Original slapd.conf.{bak,obsolete}:¶
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/duaconf.schema
include /etc/openldap/schema/dyngroup.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/java.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/ppolicy.schema
include /etc/openldap/schema/collective.schema
# Allow LDAPv2 client connections. This is NOT the default.
allow bind_v2
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral ldap://root.openldap.org
pidfile /var/run/openldap/slapd.pid
argsfile /var/run/openldap/slapd.args
# Load dynamic backend modules
# - modulepath is architecture dependent value (32/64-bit system)
# - back_sql.la overlay requires openldap-server-sql package
# - dyngroup.la and dynlist.la cannot be used at the same time
# modulepath /usr/lib/openldap
# modulepath /usr/lib64/openldap
# moduleload accesslog.la
# moduleload auditlog.la
# moduleload back_sql.la
# moduleload chain.la
# moduleload collect.la
# moduleload constraint.la
# moduleload dds.la
# moduleload deref.la
# moduleload dyngroup.la
# moduleload dynlist.la
# moduleload memberof.la
# moduleload pbind.la
# moduleload pcache.la
# moduleload ppolicy.la
# moduleload refint.la
# moduleload retcode.la
# moduleload rwm.la
# moduleload seqmod.la
# moduleload smbk5pwd.la
# moduleload sssvlv.la
# moduleload syncprov.la
# moduleload translucent.la
# moduleload unique.la
# moduleload valsort.la
# The next three lines allow use of TLS for encrypting connections using a
# dummy test certificate which you can generate by running
# /usr/libexec/openldap/generate-server-cert.sh. Your client software may balk
# at self-signed certificates, however.
TLSCACertificatePath /etc/openldap/certs
TLSCertificateFile "\"OpenLDAP Server\""
TLSCertificateKeyFile /etc/openldap/certs/password
# Sample security restrictions
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64
# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
# enable on-the-fly configuration (cn=config)
database config
access to *
by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
by * none
# enable server status monitoring (cn=monitor)
database monitor
access to *
by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
by dn.exact="cn=Manager,dc=my-domain,dc=com" read
by * none
#######################################################################
# database definitions
#######################################################################
database bdb
suffix "dc=my-domain,dc=com"
checkpoint 1024 15
rootdn "cn=Manager,dc=my-domain,dc=com"
# Cleartext passwords, especially for the rootdn, should
# be avoided. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
# rootpw secret
# rootpw {crypt}ijFYNcSNctBYg
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory /var/lib/ldap
# Indices to maintain for this database
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub
# Replicas of this database
#replogfile /var/lib/ldap/openldap-master-replog
#replica host=ldap-1.example.com:389 starttls=critical
# bindmethod=sasl saslmech=GSSAPI
# authcId=host/ldap-master.example.com@EXAMPLE.COM