Friday, December 24, 2010

Configuring OpenLDAP with SSL/TLS on Debian

It is recommended that communication between clients and ldap server be encrypted. Before we enable encryption for ldap server we need SSL private key and certificate signed by certificate authority. Have a look at OpenSSL Certificates. Suppose here are your files: ldap.dev.local-key.pem and ldap.dev.local-cert.pem.

Server

  1. Install CA certificate:
    cp ~/ca/demoCA/cacert.pem /etc/ssl/certs/
    chmod go+r /etc/ssl/certs/cacert.pem
    
  2. Copy ldap key and certificate files to /etc/ldap/ssl
    mkdir /etc/ldap/ssl/
    cp ~/ca/ldap.dev.local-*.pem /etc/ldap/ssl/
    
  3. Secure certificates:
    ldap1:~# chown -R root:openldap /etc/ldap/ssl
    ldap1:~# chmod -R o-rwx /etc/ldap/ssl
    
  4. Enable ldaps protocol (file /etc/default/slapd)
    LAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
    
  5. Create tls configuration file (tls-config.ldif):
    dn: cn=config
    add: olcTLSCACertificateFile
    olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
    -
    add: olcTLSCertificateFile
    olcTLSCertificateFile: /etc/ldap/ssl/ldap.dev.local-cert.pem
    -
    add: olcTLSCertificateKeyFile
    olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.dev.local-key.pem
    
  6. Apply it:
    ldapmodify -QY EXTERNAL -H ldapi:/// -f tls-config.ldif
    
  7. Restart slapd:
    /etc/init.d/slapd restart
    
  8. Ensure started:
    netstat -tunlp | grep slapd
    tcp        0      0 0.0.0.0:636             0.0.0.0:*               LISTEN      2462/slapd      
    tcp        0      0 127.0.0.1:389           0.0.0.0:*               LISTEN      2462/slapd  
    

Client

  1. Install ldap-utils package:
    apt-get install ldap-utils
    
  2. Configure (file /etc/ldap/ldap.conf)
    BASE    dc=dev,dc=local
    URI     ldaps://ldap.dev.local
    
    TLS_CACERT /etc/ssl/certs/cacert.pem
    TLS_REQCERT demand
    
  3. Ensure working:
    ldapsearch -x
    
  4. Have a look at server log file, the communication must go through port 636 now
    ldap1 slapd[2462]: conn=1005 fd=15 ACCEPT from IP=192.168.10.8:38344 (IP=0.0.0.0:636)
    ldap1 slapd[2462]: conn=1005 fd=15 TLS established tls_ssf=128 ssf=128
    ldap1 slapd[2462]: conn=1005 op=0 BIND dn="" method=128
    ldap1 slapd[2462]: conn=1005 op=0 RESULT tag=97 err=0 text=
    ldap1 slapd[2462]: conn=1005 op=1 SRCH base="dc=dev,dc=local" scope=2 deref=0 filter="(objectClass=*)"
    ldap1 slapd[2462]: conn=1005 op=1 SEARCH RESULT tag=101 err=0 nentries=6 text=
    ldap1 slapd[2462]: conn=1005 op=2 UNBIND
    ldap1 slapd[2462]: conn=1005 fd=15 closed
    

How to create Certificates using OpenSSL

In order to create a new certificate you basically need to follow two steps: (a) create certificate request, (b) sign request by certificate authority. Since for step (b) you need certificate authority please have a look at previous post that details it.

Certificate Request

The process of creating a certificate request is the same as for certificate authority, except it is important to set valid Common Name that should be a FQDN (e.g. ldap1.dev.local) for the server that this request it for (the name that the client will access your host remotely).
ldap1:~/ca# openssl req -new -nodes -keyout newreq.pem -out newreq.pem
Generating a 2048 bit RSA private key
.....................+++
....................................+++
writing new private key to 'newreq.pem'
...
Country Name (2 letter code) [UA]:
State or Province Name (full name) [LV]:
Locality Name (eg, city) []:Lviv
Organization Name (eg, company) [XYZ Co]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:ldap1.dev.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Sign Request

Here we are going to sign the client certificate request by our certificate authority:
ldap1:~/ca# /usr/lib/ssl/misc/CA.sh -sign
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem: *******
Check that the request matches the signature
Signature ok
Certificate Details:
...       
Certificate is to be certified until XXX (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Certificate:
    ...
Signed certificate is in newcert.pem
There are two important files we created: newreq.pem and newcert.pem. Consider rename those file to match the service they are created for, e.g. ldap1-key.pem and ldap1-cert.pem. You can combine them into a single file:
cat newreq.pem newcert.pem > new.pem

How to create Certificate Authority using OpenSSL

The Certificate Authority (CA) is used to verify the authenticity of a certificate. Start by installing openssl package:
apt-get install openssl

Create Private Certificate Authority

  1. OpenSSL (version 0.9.8) is installed to path /usr/lib/ssl. The CA.sh script is not in search path, we are going to add it for just current session.
    export PATH=$PATH:/usr/lib/ssl/misc
    
  2. Let customize a bit configuration file (/usr/lib/ssl/openssl.cnf) that is used for certificate creation, but first make a backup copy. Make the following changes:
    ...
    [ req ]
    default_bits    = 2048
    ...
    [ req_distinguished_name ]
    countryName_default             = UA
    stateOrProvinceName_default     = LV
    0.organizationName_default      = XYZ Co
    ...
    
  3. Create a directory for all certificates (it can be any directory, we will create in home):
    mkdir ~/ca && cd ~/ca
    
  4. Answer few questions (hit enter to create a new when prompted for CA filename):
    ldap1:~/ca# CA.sh -newca
    CA certificate filename (or enter to create)
    
    Making CA certificate ...
    Generating a 2048 bit RSA private key
    ............+++
    ........+++
    writing new private key to './demoCA/private/./cakey.pem'
    Enter PEM pass phrase: **************
    Verifying - Enter PEM pass phrase: **************
    ...
    Country Name (2 letter code) [UA]:
    State or Province Name (full name) [LV]:
    Locality Name (eg, city) []:Lviv
    Organization Name (eg, company) [XYZ Co]:
    Organizational Unit Name (eg, section) []:
    Common Name (eg, YOUR name) []:XYZ Root CA
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    Using configuration from /usr/lib/ssl/openssl.cnf
    Enter pass phrase for ./demoCA/private/./cakey.pem: *****
    Check that the request matches the signature
    Signature ok
    Certificate Details:
    ...
    Write out database with 1 new entries
    Data Base Updated
    
  5. Secure Certificate Authority:
    chmod -R go-rwx ~/ca
    
Your Certificate Authority file is cacert.pem (it is located in ~/ca/demoCA directory).

Thursday, December 23, 2010

How to create a new user in OpenLDAP

We are going create a new account for John Smith. Here are few simple steps:
  1. We need create a template for a new user account jsmith (file add-user.ldif):
    # User primary group
    dn: cn=jsmith,ou=groups,dc=dev,dc=local
    cn: jsmith
    objectClass: top
    objectClass: posixGroup
    gidNumber: 10000
    
    # User account
    dn: uid=jsmith,ou=people,dc=dev,dc=local
    cn: John Smith
    givenName: John
    sn: Smith
    uid: jsmith
    uidNumber: 10000
    gidNumber: 10000
    homeDirectory: /home/jsmith
    mail: jsmith@dev.local
    objectClass: top
    objectClass: posixAccount
    objectClass: shadowAccount
    objectClass: inetOrgPerson
    objectClass: organizationalPerson
    objectClass: person
    loginShell: /bin/bash
    userPassword: {CRYPT}*
    
  2. Load user to ldap:
    ldapadd -cxWD cn=admin,dc=dev,dc=local -f add-user.ldif
    
    or if you are authenticated by Kerberos:
    ldapadd -f add-user.ldif
    
  3. Try to find it:
    ldapsearch -x uid=jsmith
    
  4. Set user password (consider store user password in kerberos instead):
    ldappasswd -xWD cn=admin,dc=dev,dc=local -S uid=jsmith,ou=people,dc=dev,dc=local
    
Read more about openldap here.

Debian OpenLDAP

OpenLDAP is a free, open source implementation of the Lightweight Directory Access Protocol (LDAP).

Install OpenLDAP Server

  1. Ensure the host name is FQDN:
    ldap1:~# hostname 
    ldap1.dev.local
    
    If it is not, issue the following:
    echo "ldap1.dev.local" > /etc/hostname
    hostname -F /etc/hostname
    
  2. Install necessary packages (during a package configuration phase set admin password and accept all default options):
    apt-get -y install rsyslog slapd ldap-utils
    
  3. Setup system-wide defaults for LDAP clients (file /etc/ldap/ldap.conf):
    BASE    dc=dev,dc=local
    URI     ldap://ldap1.dev.local
    
  4. Disable ipv6 support for slapd (file /etc/default/slapd):
    # Additional options to pass to slapd
    SLAPD_OPTIONS="-4"
    
    Restart slapd:
    /etc/init.d/slapd restart
    netstat -tunlp | grep slapd
    
    Output:
    tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      1557/slapd
    

Logging

  1. Create a file that enable ldap logging (file log-stats.ldif):
    # Enable LDAP logging
    dn: cn=config
    changetype: modify
    replace: olcLogLevel
    olcLogLevel: stats
    
  2. ... disable ldap logging (file log-none.ldif):
    # Disable LDAP logging
    dn: cn=config
    changetype: modify
    replace: olcLogLevel
    olcLogLevel: none
    
  3. And here is a command (changes are applied immediately, no need to restart slapd):
    ldapmodify -QY EXTERNAL -H ldapi:/// -f log-stats.ldif
    

What to index

  1. Create indexes to match the actual filter terms used in search queries. Read more here. We are going to add the following indexes: uid, cn. So here is our index file (file db-index.ldif):
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    add: olcDbIndex
    olcDbIndex: uid eq
    -
    add: olcDbIndex
    olcDbIndex: cn eq
    -
    add: olcDbIndex
    olcDbIndex: ou eq
    -
    add: olcDbIndex
    olcDbIndex: dc eq
    -
    add: olcDbIndex
    olcDbIndex: uniqueMember eq
    -
    add: olcDbIndex
    olcDbIndex: uidNumber eq
    -
    add: olcDbIndex
    olcDbIndex: gidNumber eq
    
    Apply changes:
    ldapmodify -QY EXTERNAL -H ldapi:/// -f db-index.ldif
    

Reindex database

  1. Here is a simple script to reindex database (file /usr/local/sbin/slap-reindex). You do not need to run it often, that is depends how big is your database and how many changes occur, consider run it monthly:
    #!/bin/sh
    /etc/init.d/slapd stop > /dev/null
    su openldap -c "slapindex"
    /etc/init.d/slapd start > /dev/null
    

Simple tree structure

  1. Here is our simple structure:
    dev.local
    |--people
    `--groups
    
  2. It correspond to the following (file init-tree.ldif):
    dn: ou=people,dc=dev,dc=local
    ou: people
    objectClass: organizationalUnit
    
    dn: ou=groups,dc=dev,dc=local
    ou: groups
    objectClass: organizationalUnit
    
  3. Add it to ldap:
    ldapadd -cxWD cn=admin,dc=dev,dc=local -f init-tree.ldif
    
  4. Test if we can find it:
    ldapsearch -x ou=people
    
    Here is search result:
    # extended LDIF
    #
    # LDAPv3
    # base  (default) with scope subtree
    # filter: ou=people
    # requesting: ALL
    #
    
    # people, dev.local
    dn: ou=people,dc=dev,dc=local
    ou: people
    objectClass: organizationalUnit
    
    # search result
    search: 2
    result: 0 Success
    
    # numResponses: 2
    # numEntries: 1