OpenLDAP on CentOS7 with TLS/SSL RootCA and Client in SElinux mode

One side of your infrastructure has to be centralized.

This is where OpenLDAP comes in to play.

Eventually you would like to have a single user with the abilities to login into every system with the same credentials and
elevate to admin or other like super user account.

Well why not. Here I will explain is simple steps to follow how to do it.

I will just cover creation of OpenLDAP server with best possible level of security between server and client during authentication.

In another post I will link your OpenLDAP with sudo, which means exactly that what you need after all - super user rights for a basic luser on every system you want to manage remotely with magnificent and simple elevation.

Come on lets play.

1. Create Local CA for RootCA and LDAP Server Certificate

First of all lets practice one more time the basic of every eleet PKI CA infrastructure admin.

OpenSSL with CA and the steps to request certificate and its signing by "trusted" authority withing your own infrastructure.

We will need this to create CA, LDAP Server certificate and its private key.

The CA has to be present on LDAP server along with server cert and its key.

The CA has to be also present on LDAP client for proper authentication.

I know you do not often use certificates for authentication - but maybe this time it will get you a step closer to be a pro! :D

As always and usual some steps for you should be self explanatory so nea point of wasting bits here! ;]

We start with:

cp /etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf.ORIG  
cd /etc/pki/CA/  
touch index.txt  
echo '01' > serial.txt  

In the above index.txt will be used as a DB about the issues and revoked certs.

Serial is just incremental of the next CA activity regardless of an issue or a revoke of a cert.

Now prepare a config for your own eleet CA.

vi /etc/pki/tls/openssl.cnf  
[ CA_default ]

dir             = /etc/pki/CA           # Where everything is kept  
certs           = $dir/certs            # Where the issued certs are kept  
crl_dir         = $dir/crl              # Where the issued crl are kept  
database        = $dir/index.txt        # database index file.  
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $certs/cacert.pem     # The CA certificate  
serial          = $dir/serial.txt       # The current serial number  
crlnumber       = $dir/crlnumber        # the current crl number  
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL  
private_key     = $dir/private/cakey.pem # The private key

# For the CA policy
[ policy_match ]
countryName             = match  
stateOrProvinceName     = match  
organizationName        = match  
organizationalUnitName  = optional  
commonName              = supplied  
emailAddress            = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ signing_policy ]
countryName             = match  
stateOrProvinceName     = match  
organizationName        = match  
organizationalUnitName  = optional  
commonName              = supplied  
emailAddress            = optional

[ signing_req ]

When you are done, use your CA config file to actually create a trusted CA valid for 10 years!

With Password  
openssl req -config /etc/pki/tls/openssl.cnf -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 3650

Without Password - using no password in this article  
openssl req -config /etc/pki/tls/openssl.cnf -new -x509 -extensions v3_ca \  
-keyout private/cakey.pem -out certs/cacert.pem -nodes -days 3650

Be sure to give it read-only permission.

chmod 0400 private/cakey.pem  

Verify Your new CA, to see how long is valid for and that.

openssl x509 -in certs/cacert.pem -text -noout  

Now, since we got a Root CA its time to create an CSR for your OpenLDAP server.

Of course you will fill all fields appropriately because these will be required by the matching policy.
One of many but crucial is always your CN.

Create CSR for LDAP Server

openssl req -config /etc/pki/tls/openssl.cnf -newkey rsa:2048 -sha256 -nodes -out ldapcert.csr -outform PEM -keyout ldapkey.pem  

Sign CSR with new CA

openssl ca -config /etc/pki/tls/openssl.cnf -policy signing_policy -extensions signing_req -out ldapcert.pem -infiles ldapcert.csr  

Verify Your new CA

openssl x509 -in ldapcert.pem -text -noout  

In summary you got: ldapkey.pem and ldapcert.pem and your candy cacert.pem Root CA, which is all you need to move forward.

2. Install OpenLDAP Server

Lets install the OpenLDAP of our fav OS CentOS 7 with SElinux enabled.

yum update  
yum install epel-release  
yum install openldap-clients openldap-servers


setsebool -P allow_ypbind=0 authlogin_nsswitch_use_ldap=0

systemctl enable slapd.service  
systemctl start slapd.service

cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG

chown -R ldap:ldap /var/lib/ldap/  

Time for a comment - so you installed all prerequisites on server side and its time to generate sha512 hash for your master LDAP account as shown below.


cat ldaprootpasswd.ldif  
dn: olcDatabase={0}config,cn=config  
changetype: modify  
add: olcRootPW  

In the above example you use your generate sha512 to add it to your Directory Services for admin authentication.

With the below command you update the LDAP Directory Services

ldapadd -H ldapi:/// -f ldaprootpasswd.ldif


Being still in /etc/openldap/sldap.d/ run the below to import basic schema. I think nis.ldif is the most important but what ever.

for def in cosine.ldif nis.ldif inetorgperson.ldif; do ldapadd -H ldapi:/// -f /etc/openldap/schema/$def; done  

Now one of the many important steps.

Create your own domain, RootDN, access policy,

vi ldapdomain.ldif  
dn: olcDatabase={1}monitor,cn=config  
changetype: modify  
replace: olcAccess  
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=admins,dc=hextrim,dc=com" 

read by * none

dn: olcDatabase={2}hdb,cn=config  
changetype: modify  
replace: olcSuffix  
olcSuffix: dc=hextrim,dc=com

dn: olcDatabase={2}hdb,cn=config  
changetype: modify  
replace: olcRootDN  
olcRootDN: cn=admins,dc=hextrim,dc=com

dn: olcDatabase={2}hdb,cn=config  
changetype: modify  
add: olcRootPW  

dn: olcDatabase={2}hdb,cn=config  
changetype: modify  
add: olcAccess  
olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=admins,dc=hextrim,dc=com" write by anonymous auth by self write by * none  
olcAccess: {1}to dn.base="" by * read  
olcAccess: {2}to * by dn="cn=admins,dc=hextrim,dc=com" write by * read  

Now import it.

ldapmodify -H ldapi:/// -f ldapdomain.ldif  

Another of so many important steps is to create your baseDN and OU's.

vi baseldapdomain.ldif  
dn: dc=hextrim,dc=com  
objectClass: top  
objectClass: dcObject  
objectclass: organization  
dc: hextrim

dn: cn=admins,dc=hextrim,dc=com  
objectClass: organizationalRole  
cn: admins  
description: Directory Admins

dn: ou=users,dc=hextrim,dc=com  
objectClass: organizationalUnit  
ou: users

dn: ou=group,dc=hextrim,dc=com  
objectClass: organizationalUnit  
ou: group  

Now import it.

ldapadd -x -D cn=admins,dc=hextrim,dc=com -W -f baseldapdomain.ldif  

To further enable LDAPS - the TLS/SSL version of it you need to strictly follow the steps below.

Certainly you would prefer to use LDAPS over LDAP with just TLS. Don't you the real pro would do... ;]

cp /etc/pki/CA/certs/cacert.pem /etc/openldap/certs/  
cp /etc/pki/CA/ldapkey.pem /etc/openldap/certs/  
cp /etc/pki/CA/ldapcert.pem /etc/openldap/certs/

chown -R ldap:ldap /etc/openldap/certs/*.pem

[root@LDAP-SERVER slapd.d]# cat hextrimcerts.ldif
dn: cn=config  
changetype: modify  
replace: olcTLSCACertificateFile  
olcTLSCACertificateFile: /etc/openldap/certs/cacert.pem  
replace: olcTLSCertificateFile  
olcTLSCertificateFile: /etc/openldap/certs/ldapcert.pem  
replace: olcTLSCertificateKeyFile  
olcTLSCertificateKeyFile: /etc/openldap/certs/ldapkey.pem  

In the above hextrimcerts.ldif file we point the LDAP Attributes regarding TLS/SSL certificate location and later import them.

ldapmodify -Y EXTERNAL  -H ldapi:/// -f hextrimcerts.ldif  

Next, we want to use the most secured ciphers available for our secured communication!

[root@LDAP-SERVER slapd.d]# cat cipher.ldif
dn: cn=config  
changetype: modify  
replace: olcTLSCipherSuite


add: olcTLSProtocolMin  
olcTLSProtocolMin: 3.2 #use only TLSv1.2

ldapmodify -Y EXTERNAL -H ldapi:/// -f cipher.ldif  

After importing the ciphers we can still point the LDAP Server to the certs in slapd.conf file as follows.

vi /etc/openldap/slapd.conf  
TLSCACertificateFile /etc/openldap/certs/cacert.pem  
TLSCertificateFile /etc/openldap/certs/ldapcert.pem  
TLSCertificateKeyFile /etc/openldap/certs/ldapkey.pem  

We may now also decide [after all imports done] if we want to use only ldaps:/// or maybe still ldapi:/// or maybe even add there

ldap:/// to for communication with clients. I only use ldapi and ldaps!

vi /etc/sysconfing/sldap  
SLAPD_URLS="ldapi:/// ldaps:///"


Now let's test our config file.

slaptest -f /etc/openldap/slapd.conf

systemctl restart slapd  
systemctl status slapd  

All looks good.

It's time to prepare for Client setup.

Let's create out master admin account which we will later use to access every Linux system we have deployed within out infrastructure.

slaptest -u

cat /etc/passwd

adduser admin  

Here again a sha512 for our new admin.


Now, its time to create admin user specific policy.

vi admin.ldif  
[root@LDAP-SERVER slapd.d]# cat admin.ldif
dn: uid=admin,ou=users,dc=hextrim,dc=com  
objectClass: top  
objectClass: account  
objectClass: posixAccount  
objectClass: shadowAccount  
cn: admin  
uid: admin  
uidNumber: 1000  
gidNumber: 1000  
homeDirectory: /home/admin  
loginShell: /bin/bash  
gecos: admin  
shadowLastChange: 0  
shadowMax: -1 ####### If you leave this 0 you will end up with constant password change requests  
shadowWarning: 0

This is how you create user!  
ldapadd -x -W -D "cn=admins,dc=hextrim,dc=com" -f admin.ldif

This is how you delete user!  
ldapdelete -W -D "cn=admins,dc=hextrim,dc=com" "uid=admin,ou=users,dc=hextrim,dc=com"  

Your user may be also a member of your OU "group" which you created previously.

[root@LDAP-SERVER slapd.d]# cat admingroup.ldif
dn: cn=admins,ou=group,dc=hextrim,dc=com  
objectClass: top  
objectClass: posixGroup  
gidNumber: 1000  

Group Import.

ldapadd -x -W -D "cn=admins,dc=hextrim,dc=com" -f admingroup.ldif  

Verify if your user uid=admin actually exist on the server.

ldapsearch -x -W -D "cn=admins,dc=hextrim,dc=com" -b "uid=admin,ou=users,dc=hextrim,dc=com" "(objectclass=*)"  

All looks good.

Verify if ldap:// still works locally and if ldaps:// even works?

ldapsearch -H ldap:// -D "cn=admins,dc=hextrim,dc=com" -w -ZZ -d7  
ldapsearch -H ldaps:// -D "cn=admins,dc=hextrim,dc=com" -w -ZZ -d7  

Check what TLS attributes are set on your LDAP Directory.

ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config|grep TLS  

If you have issues with using LDAPS you may use gnutls-utils and openssl to test when your TLS/SSL problem is.

gnutls-cli-debug -p 636  
openssl s_client -connect localhost:636 -showcerts  

3. Client side - Finally!

yum update  
yum install openldap-clients nss-pam-ldapd  

Authconfig is use to pre-configure your linux system for ldap authentication by updating nss/ldap related files. (ldap.conf/nslcd.conf)

The example below enable ldap (not ldaps) pointing to my ldap server

authconfig --enableldap \  
--enableldapauth \ \
--ldapbasedn="dc=hextrim,dc=com" \
--enablemkhomedir \

authconfig --enablepamaccess --update

authconfig --test  

Note: running the above authconfig will generate /etc/pam.d/system-auth and /etc/pam.d/password-auth adding the following to both files:
auth sufficient use_first_pass

session optional umask=0077

If your client is SElinux enabled you will need to create a SElinux module and import it as follows to allow users to access their "roaming profiles" if you like in clients /home/ directory.

[root@LDAP-CLIENT ~]# vi mkhomedir.te
module mkhomedir 1.0;

require {  
        type unconfined_t;
        type oddjob_mkhomedir_exec_t;
        class file entrypoint;

#============= unconfined_t ==============
allow unconfined_t oddjob_mkhomedir_exec_t:file entrypoint;

[root@LDAP-CLIENT ~]# checkmodule -m -M -o mkhomedir.mod mkhomedir.te
[root@LDAP-CLIENT ~]# semodule_package -o mkhomedir.pp -m mkhomedir.mod

[root@LDAP-CLIENT ~]# semodule -i mkhomedir.pp 

When module on the client is imported we can copy the CA from Server to the Client using either SCP of basic copy and paste.

Copy RootCA to CLIENT.

scp cacert.pem to [root@CLIENT ~]# /etc/openldap/cacerts/cacert.pem  

Add the following lines to ldap.conf.
Remember that fields already been created when you ran authconfig.

[root@LDAP-CLIENT ~]# cat /etc/openldap/ldap.conf
TLS_CACERTFILE /etc/openldap/cacerts/cacert.pem

# Turning this off breaks GSSAPI used with krb5 when rdns = false


URI ldaps:// #### This was generated by authconf but I changed it to be ldaps!  
BASE dc=hextrim,dc=com #### These are generated by authconf don't edit them before  

Update your client nslcd.conf as follows

[root@LDAP-CLIENT ~]# cat /etc/nslcd.conf
uri ldaps:// ### authconf generated however changed to ldaps  
base dc=hextrim,dc=com ### authconf generated  
tls_reqcert allow  
tls_ciphers TLSv1  
ssl on  
tls_cacertdir /etc/openldap/cacerts  

Last very important step at client side is to enable PAM for SSH to use system-auth.
Add the line on the very top on the auth section.

[root@LDAP-CLIENT ~]# vi /etc/pam.d/sshd
auth       include      system-auth  

Now restart client nslcd service.

service nslcd restart  

You may also stop your client nslcd service (service nslcd stop) end enable debugging.

nslcd -d  

When the above is running instead you can try to authenticate over SSH to your client from any remote machine and see what possible errors you may getting.

If all is working correctly and proper TLS and SSL settings are in use you should authenticate like a charm.

Otherwise you may run queries from client to server over ldaps and see what TLS/SSL related problems are.

ldapsearch -v -H ldaps:// -D cn=admins,dc=hextrim,dc=com -W -x -b dc=hextrim,dc=com -d1  
ldapsearch -H ldaps:// -D "cn=admins,dc=hextrim,dc=com" -ZZ -d7

openssl s_client -connect -showcerts  


Another PoC achieved.

Soon I will come back with OpenLDAP with SUDO :> Stay tuned.

-- lo3k

Share this post:

by lo3k