= Setting Up Institutional IDP =
OpenLDAP provides an LDAP directory service that is flexible and well-supported. In this lab, we will demonstrate how to encrypt connections to OpenLDAP using STARTTLS.
== Setting the Hostname and FQDN ==
[wiki:ipallocation dilum added for ip table]
Before you get started, make sure you set up our server so that it correctly resolves its hostname and fully qualified domain name (FQDN). This will be necessary in order for our certificates to be validated by clients.
check FQDN by
{{{
hostname -f
}}}
== Install the OpenLDAP Server ==
If you do not already have OpenLDAP installed, now is the time to fix that. Update your server's local package index and install the software by typing:
{{{
sudo apt-get update
sudo apt-get install slapd ldap-utils
}}}
- Note: if your apt-get trying to use IPv6 and it does not get connected, you may add following flag at the of the apt-get command
{{{
-o Acquire::ForceIPv4=true
}}}
You will be asked to provide an LDAP administrative password. Feel free to skip the prompt, as we will be reconfiguring immediately after.
In order to access some additional prompts that we need, we'll reconfigure the package after installation. To do so, type:
{{{
sudo dpkg-reconfigure slapd
}}}
Answer the prompts appropriately, using the information below as a starting point:
- Omit OpenLDAP server configuration? '''No''' (we want an initial database and configuration)
- DNS domain name: '''inst.ac.lk''' (use the server's domain name, minus the hostname. This will be used to create the base entry for the information tree)
- Organization name: '''Example Inc''' (This will simply be added to the base entry as the name of your institute)
- Administrator password: '''[whatever you'd like]'''
- Confirm password: '''[must match the above]'''
- Database backend to use: '''HDB''' (out of the two choices, this has the most functionality)
- Do you want the database to be removed when slapd is purged? (your choice. Choose '''"Yes"''' to allow a completely clean removal, choose '''"No"''' to save your data even when the software is removed)
- Move old database? '''Yes'''
- Allow LDAPv2 protocol? '''No'''
== install the SSL Components ==
Once your OpenLDAP server is configured, we can go ahead and install the packages we'll use to encrypt our connection. The Ubuntu OpenLDAP package is compiled against the GnuTLS SSL libraries, so we will use GnuTLS to generate our SSL credentials:
{{{
sudo apt-get install gnutls-bin ssl-cert
}}}
With all of our tools installed, we can begin creating the certificates and keys needed to encrypt our connections.
=== Create the Certificate Templates ===
To encrypt our connections, we'll need to configure a certificate authority and use it to sign the keys for the LDAP server(s) in our infrastructure. So for our single server setup, we will need two sets of key/certificate pairs: one for the certificate authority itself and one that is associated with the LDAP service.
To create the certificates needed to represent these entities, we'll create some template files. These will contain the information that the certtool utility needs in order to create certificates with the appropriate properties.
Start by making a directory to store the template files:
{{{
sudo mkdir /etc/ssl/templates
}}}
=== Create the CA Template ===
Create the template for the certificate authority first. We'll call the file ca_server.conf. Create and open the file in your text editor:
{{{
sudo nano /etc/ssl/templates/ca_server.conf
}}}
We only need to provide a few pieces of information in order to successfully create a certificate authority. We need to specify that the certificate will be for a CA (certificate authority) by adding the ca option. We also need the cert_signing_key option to give the generated certificate the ability to sign additional certificates. We can set the cn to whatever descriptive name we'd like for our certificate authority:
{{{
cn = LDAP Server CA
ca
cert_signing_key
Save and close the file.
}}}
Save and close the file.
=== Create the LDAP Service Template ===
Next, we can create a template for our LDAP server certificate called ldap_server.conf. Create and open the file in your text editor with sudo privileges:
{{{
sudo nano /etc/ssl/templates/ldap_server.conf
}}}
Here, we'll provide a few different pieces of information. We'll provide the name of our organization and set the tls_www_server, encryption_key, and signing_key options so that our cert has the basic functionality it needs.
The cn in this template must match the FQDN of the LDAP server. If this value does not match, the client will reject the server's certificate. We will also set the expiration date for the certificate. We'll create a 10 year certificate to avoid having to manage frequent renewals:
'''ldapserver.conf'''
{{{
organization = "Name of your institution"
cn = idp.inst.ac.lk
tls_www_server
encryption_key
signing_key
expiration_days = 3652
}}}
Save and close the file when you're finished.
=== Create CA Key and Certificate ===
Now that we have our templates, we can create our two key/certificate pairs. We need to create the certificate authority's set first.
Use the certtool utility to generate a private key. The '''/etc/ssl/private''' directory is protected from non-root users and is the appropriate location to place the private keys we will be generating. We can generate a private key and write it to a file called ca_server.key within this directory by typing:
{{{
sudo certtool -p --outfile /etc/ssl/private/ca_server.key
}}}
Now, we can use the private key that we just generated and the template file we created in the last section to create the certificate authority certificate. We will write this to a file in the '''/etc/ssl/certs''' directory called ca_server.pem:
{{{
sudo certtool -s --load-privkey /etc/ssl/private/ca_server.key --template /etc/ssl/templates/ca_server.conf --outfile /etc/ssl/certs/ca_server.pem
}}}
We now have the private key and certificate pair for our certificate authority. We can use this to sign the key that will be used to actually encrypt the LDAP session.
=== Create LDAP Service Key and Certificate ===
Next, we need to generate a private key for our LDAP server. We will again put the generated key in the '''/etc/ssl/private''' directory for security purposes and will call the file ldap_server.key for clarity.
We can generate the appropriate key by typing:
{{{
sudo certtool -p --sec-param high --outfile /etc/ssl/private/ldap_server.key
}}}
Once we have the private key for the LDAP server, we have everything we need to generate a certificate for the server. We will need to pull in almost all of the components we've created thus far (the CA certificate and key, the LDAP server key, and the LDAP server template).
We will put the certificate in the '''/etc/ssl/certs''' directory and name it '''ldap_server.pem'''. The command we need is:
{{{
sudo certtool -c --load-privkey /etc/ssl/private/ldap_server.key --load-ca-certificate /etc/ssl/certs/ca_server.pem --load-ca-privkey /etc/ssl/private/ca_server.key --template /etc/ssl/templates/ldap_server.conf --outfile /etc/ssl/certs/ldap_server.pem
}}}
=== Give OpenLDAP Access to the LDAP Server Key ===
We now have all of the certificates and keys we need. However, currently, our OpenLDAP process will be unable to access its own key.
A group called ssl-cert already exists as the group-owner of the '''/etc/ssl/private''' directory. We can add the user our OpenLDAP process runs under (openldap) to this group:
{{{
sudo usermod -aG ssl-cert openldap
}}}
Now, our OpenLDAP user has access to the directory. We still need to give that group ownership of the '''ldap_server.key''' file though so that we can allow read access. Give the ssl-cert group ownership over that file by typing:
{{{
sudo chown :ssl-cert /etc/ssl/private/ldap_server.key
}}}
Now, give the ssl-cert group read access to the file:
{{{
sudo chmod 640 /etc/ssl/private/ldap_server.key
}}}
Our OpenSSL process can now access the key file properly.
Configure OpenLDAP to Use the Certificate and Keys
We have our files and have configured access to the components correctly. Now, we need to modify our OpenLDAP configuration to use the files we've made. We will do this by creating an LDIF file with our configuration changes and loading it into our LDAP instance.
Move to your home directory and open a file called '''addcerts.ldif'''. We will put our configuration changes in this file:
{{{
cd ~
nano addcerts.ldif
}}}
To make configuration changes, we need to target the cn=config entry of the configuration DIT. We need to specify that we are wanting to modify the attributes of the entry. Afterwards we need to add the olcTLSCACertificateFile, olcCertificateFile, and olcCertificateKeyFile attributes and set them to the correct file locations.
The end result will look like this:
'''addcerts.ldif'''
{{{
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/ca_server.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap_server.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap_server.key
}}}
Save and close the file when you are finished. Apply the changes to your OpenLDAP system using the ldapmodify command:
{{{
sudo ldapmodify -H ldapi:// -Y EXTERNAL -f addcerts.ldif
}}}
We can reload OpenLDAP to apply the changes:
{{{
sudo service slapd force-reload
}}}
Our clients can now be configured to encrypt their connections to the server over the conventional '''ldap://''' port by using STARTTLS.
== Setting up the Client Machines ==
In order to connect to the LDAP server and initiate a STARTTLS upgrade, the clients must have access to the certificate authority certificate and must request the upgrade.
On the OpenLDAP Server
If you are interacting with the OpenLDAP server from the server itself, you can set up the client utilities by copying the CA certificate and adjusting the client configuration file.
First, copy the CA certificate from the '''/etc/ssl/certs''' directory to a file within the '''/etc/ldap''' directory. We will call this file ca_certs.pem. This file can be used to store all of the CA certificates that clients on this machine may wish to access. For our purposes, this will only contain a single certificate:
{{{
sudo cp /etc/ssl/certs/ca_server.pem /etc/ldap/ca_certs.pem
}}}
Now, we can adjust the system-wide configuration file for the OpenLDAP utilities. Open up the configuration file in your text editor with sudo privileges:
{{{
sudo nano /etc/ldap/ldap.conf
}}}
Adjust the value of the '''TLS_CACERT''' option to point to the file we just created:
'''/etc/ldap/ldap.conf'''
{{{
TLS_CACERT /etc/ldap/ca_certs.pem
TLS_REQCERT allow
}}}
Save and close the file.
You should now be able to upgrade your connections to use STARTTLS by passing the '''-Z''' option when using the OpenLDAP utilities. You can force STARTTLS upgrade by passing it twice. Test this by typing:
{{{
ldapwhoami -H ldap:// -x -ZZ
}}}
This forces a STARTTLS upgrade. If this is successful, you should see:
{{{
STARTTLS success
anonymous
}}}
If you mis-configured something, you will likely see an error like this:
STARTTLS failure
{{{
ldap_start_tls: Connect error (-11)
additional info: (unknown error code)
}}}
== Force Connections to Use TLS ==
We've successfully configured our OpenLDAP server so that it can seamlessly upgrade normal LDAP connections to TLS through the STARTTLS process. However, this still allows unencrypted sessions, which may not be what you want.
We will use an LDIF file to make the changes. Create the LDIF file in your home directory of '''IDP'''. We will call it '''forcetls.ldif''':
{{{
nano forcetls.ldif
}}}
Inside, target the DN you want to force TLS on. In our case, this will be '''dn: olcDatabase={1}hdb,cn=config'''. We will set the changetype to "modify" and add the olcSecurity attribute. Set the value of the attribute to "'''tls=1'''" to force TLS for this DIT:
{{{
dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcSecurity
olcSecurity: tls=1
}}}
Save and close the file when you are finished.
To apply the change, type:
{{{
sudo ldapmodify -H ldapi:// -Y EXTERNAL -f forcetls.ldif
}}}
Reload the OpenLDAP service by typing:
{{{
sudo service slapd force-reload
}}}
Now, if you search the '''dc=inst,dc=ac,dc=lk''' DIT, you will be refused if you do not use the -Z option to initiate a STARTTLS upgrade:
{{{
ldapsearch -H ldap:// -x -b "dc=example,dc=com" -LLL dn
}}}
TLS required failure
{{{
Confidentiality required (13)
Additional information: TLS confidentiality required
}}}
We can demonstrate that STARTTLS connections still function correctly:
{{{
ldapsearch -H ldap:// -x -b "dc=example,dc=com" -LLL -Z dn
}}}
TLS required success
{{{
dn: dc=inst,dc=ac,dc=lk
dn: cn=admin,dc=inst,dc=ac,dc=lk
}}}
== Adding Initial Identity to your LDAP Directory Service ==
Having setup LDAP Server and Client connection using STARTTLS, it is time add initial identity to you directory service. This include adding user credential and attributes, group information, etc.
The LDAP Data Interchange Format (LDIF) is a standard plain text data interchange format for representing LDAP directory content and update requests. LDIF conveys directory content as a set of records, one record for each object (or entry). It also represents update requests, such as Add, Modify, Delete, and Rename, as a set of records, one record for each update request.
=== Creating initial LDIF ===
Open a new file named as initial.ldif using nano or vi editor. Then copy following ldif content and do necessary adjustments to match with you institute.
{{{
# group, inst.ac.lk
dn: ou=group,dc=inst,dc=ac,dc=lk
description: learn groups
objectClass: top
objectClass: organizationalUnit
ou: group
# adm staf, group, inst.ac.lk
dn: cn=adm,ou=group,dc=inst,dc=ac,dc=lk
cn: adm
description: System Admin Staff
gidNumber: 1000
objectClass: posixGroup
objectClass: top
# acadamic staf, group, inst.ac.lk
dn: cn=acd,ou=group,dc=inst,dc=ac,dc=lk
cn: acd
description: Acadamic Staff
gidNumber: 2000
objectClass: posixGroup
objectClass: top
# students, group, inst.ac.lk
dn: cn=std,ou=group,dc=inst,dc=ac,dc=lk
cn: bod
description: Students
gidNumber: 5000
objectClass: posixGroup
objectClass: top
# servers, inst.ac.lk
dn: ou=servers,dc=inst,dc=ac,dc=lk
description: inst servers that are LDAP clients
objectClass: top
objectClass: organizationalUnit
ou: servers
# idp, servers, inst.ac.lk
dn: cn=idp,ou=servers,dc=inst,dc=ac,dc=lk
cn: idp
description: Identity Server
ipHostNumber: 192.248.4.72
objectClass: top
objectClass: device
objectClass: ipHost
objectClass: simpleSecurityObject
userPassword: {crypt}idpldap
# irs, servers, inst.ac.lk
dn: cn=irs,ou=servers,dc=inst,dc=ac,dc=lk
cn: irs
description: IRS Server
ipHostNumber: 192.248.4.73
objectClass: top
objectClass: device
objectClass: ipHost
objectClass: simpleSecurityObject
userPassword: {crypt}irsldap
# people, inst.ac.lk
dn: ou=people,dc=inst,dc=ac,dc=lk
description: inst users
objectClass: top
objectClass: organizationalUnit
ou: people
# testme, people, inst.ac.lk
dn: uid=testme,ou=people,dc=inst,dc=ac,dc=lk
cn: Test Me
departmentNumber: LEARN
employeeNumber: 02
employeeType: Test Account
facsimileTelephoneNumber: 081 2003032
gecos: Test Me
gidNumber: 1000
givenName: Test Me
homeDirectory: /home/testme
homePhone: none
homePostalAddress: none
initials: T M
jpegPhoto: none
labeledURI: none
loginShell: /usr/local/bin/bash
mobile: none
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowExpire: 14940
shadowFlag: 134538484
shadowInactive: 0
shadowLastChange: 14483
shadowMax: 13100
shadowMin: 0
shadowWarning: 7
sn: Test
telephoneNumber: 3032
uid: testme
uidNumber: 1001
userPassword: testme
}}}
Note that user passwords are not encrypted (in clear text format).
=== Adding LDIF to LDAP ===
Use ldapadd command to add new entries to your LDAP server. You may need to enter LDAP admin password.
{{{
ldapadd -H ldap:// -x -D "cn=admin,dc=inst,dc=ac,dc=lk" -W -Z -f initial.ldif
}}}
== LDAP Bind ==
{{{
ldapsearch -H ldap:// -x -D "cn=admin,dc=inst,dc=ac,dc=lk" -W -Z -b "dc=inst,dc=ac,dc=lk"
}}}
Note that Clear-Text userPassword enconded in '''base64'''
== Deleting ldap entity ==
{{{
ldapdelete -H ldap:// "uid=user,ou=people,dc=inst,dc=ac,dc=lk" -D "cn=admin,dc=inst,dc=ac,dc=lk" -Z -W
}}}
== Setting LDAP Access Control ==
You can simply see the existing ACLs by
{{{
ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config 'olcDatabase={1}hdb'
}}}
Create new file named acc1.ldif with following modification to ACLs. This will provide your irs to read users passwords.
{{{
dn: olcDatabase={1}hdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by dn.children="ou=servers,dc=inst,dc=ac,dc=lk" read by * none
olcAccess: {1}to attrs=shadowLastChange by self write by * read
olcAccess: {2}to * by * read
}}}
Use following command to externally modify the ACLs
{{{
ldapmodify -Y EXTERNAL -H ldapi:/// -f acc1.ldif
}}}
== Install phpLDAPadmin to Manage LDAP with a Web Interface (Optional) ==
Although it is very possible to administer LDAP through the command line, most users will find it easier to use a web interface. We're going to install phpLDAPadmin, which provides this functionality, to help remove some of the friction of learning the LDAP tools.
The Ubuntu repositories contain the phpLDAPadmin package. You can install it by first login to your IDP and then typing:
{{{
sudo apt-get install phpldapadmin apache2-utils
}}}
Edit configuration file to make following adjustments
{{{
nano /etc/phpldapadmin/config.php
}}}
{{{
$servers->setValue('server','host','localhost');
$servers->setValue('server','base',array('dc=inst,dc=ac,dc=lk'));
$servers->setValue('login','bind_id','cn=admin,dc=inst,dc=ac,dc=lk');
$config->custom->appearance['hide_template_warning'] = true;
$servers->setValue('server','tls',true);
}}}
Create SSL Certificate for you apache web server
{{{
sudo mkdir /etc/apache2/ssl
}}}
Next, we can create the key and certificate in one movement by typing:
{{{
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt
}}}
=== Create a Password Authentication File ===
We also want to password protect our phpLDAPadmin location. Even though phpLDAPadmin has password authentication, this will provide an extra level of protection.
{{{
sudo htpasswd -c /etc/apache2/htpasswd testme
}}}
Then enter your password.
=== Secure Apache ===
The first thing we should do is enable the SSL module in Apache. We can do this by typing:
{{{
sudo a2enmod ssl
}}}
This will enable the module, allowing us to use it. We still need to configure Apache to take advantage of this though.
Currently, Apache is reading a file called 000-default.conf for regular, unencrypted HTTP connections. We need to tell it to redirect requests for our phpLDAPadmin interface to our HTTPS interface so that the connection is encrypted.
When we redirect traffic to use our SSL certificates, we'll also implement the password file to authenticate users. While we're modifying things, we'll also change the location of the phpLDAPadmin interface itself to minimize targeted attacks.
=== Configure the HTTP Virtual Host ===
Next, we need to modify our current Virtual Hosts file. Open it with root privileges in your editor:
{{{
sudo nano /etc/apache2/sites-enabled/000-default.conf
}}}
The changes we discussed will end up looking like this. Modify the items in bold with your own values:
{{{
ServerAdmin webmaster@inst.ac.lk
DocumentRoot /var/www/html
ServerName idp.inst.ac.lk
Redirect permanent /phpldapadmin https://idp.inst.ac.lk/phpldapadmin
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
}}}
=== Configure the HTTPS Virtual Host File ===
Apache includes a default SSL Virtual Host file. However, it is not enabled by default.
We can enable it by typing:
{{{
sudo a2ensite default-ssl.conf
}}}
This will link the file from the sites-available directory into the sites-enabled directory. We can edit this file now by typing:
{{{
sudo nano /etc/apache2/sites-enabled/default-ssl.conf
}}}
This file is a bit more involved than the last one, so we will only discuss the changes that we have to make. All of the changes below should go within the Virtual Host block in the file.
First of all, set the ServerName value to your server's domain name or IP address again and change the ServerAdmin directive as well:
{{{
ServerAdmin webmaster@inst.ac.lk
ServerName idp.inst.ac.lk
}}}
Next, we need to set the SSL certificate directives to point to the key and certificate that we created. The directives should already exist in your file, so just modify the files they point to:
{{{
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
}}}
The last thing we need to do is set up the location block that will implement our password protection for the entire phpLDAPadmin installation.
We do this by referencing the location where we are serving the phpLDAPadmin and setting up authentication using the file we generated. We will require anyone attempting to access this content to authenticate as a valid user:
{{{
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /etc/apache2/htpasswd
Require valid-user
}}}
Save and close the file when you are finished.
Restart Apache to implement all of the changes that we have made:
{{{
sudo service apache2 restart
}}}
We can now move on to the actual interface.
''https://idp.inst.ac.lk/phpldapadmin/''
Enter your apache password first and then ldap admin password