= Setting Up Institutional IDP = OpenLDAP provides an LDAP directory service that is flexible and well-supported. In this lab, we will also demonstrate how to encrypt connections to OpenLDAP using STARTTLS. == Setting the Hostname and FQDN == Remember this VM is a clone of your pc.instX.ws.learn.ac.lk. Therefore you have to change some settings in order to make this vm unique. === Setting up hostname === - Login to the vm. change to root user {{{ $sudo su }}} - Give your password - Edit /etc/hostname {{{ #nano /etc/hostname }}} * Change '''pc''' to '''idp''' * Save and Exit - also edit /etc/hosts file to change 127.0.0.1 pc."your domain".ws.ac.lk pc to 127.0.0.1 idp."your domain".ws.learn.ac.lk idp === IP Set up === Edit /etc/network/interfaces files to include your IP addresses in your pc - Login to the vm. change to root user {{{ $sudo su }}} - Give your password - Edit /etc/network/interfaces {{{ #vi /etc/network/interfaces }}} - Find the following line {{{ iface eth0 inet dhcp }}} '''Note''': "eth0" is the name of your virtual interface. It could also be something like "enp0s3". If so you will use that instead of eth0 - Change it to {{{ #iface eth0 inet dhcp }}} - Add the following lines (Get your ldap IP Address from [wiki:ipallocation iptable]) {{{ iface eth0 inet static address "Your ldap IP address" netmask 255.255.255.0 network 192.248.6.0 broadcast 192.248.6.255 gateway 192.248.6.254 dns-nameservers 192.248.1.161 dns-search yourdmain }}} When you completed the IP settings of of VM, restart the vm and then login to confirm correct IP settings. Before you get started, make sure you set up your server so that it correctly resolves its hostname to fully qualified domain name (FQDN). This will be necessary in order for your 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: '''"your domain".ws.learn.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. === 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.'your domain'.ws.learn.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='your domain'dc=ws,dc=learn,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='your domain'dc=ws,dc=learn,dc=ac,dc=lk dn: cn=admin,dc='your domain'dc=ws,dc=learn,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, 'your domain'.ws.learn.ac.lk dn:ou=group,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk description:learn groups objectClass:top objectClass:organizationalUnit ou:group # adm staf, group, 'your domain'.ws.learn.ac.lk dn:cn=adm,ou=group,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk cn:adm description:System Admin Staff gidNumber:1000 objectClass:posixGroup objectClass:top # acadamic staf, group, 'your domain'.ws.learn.ac.lk dn:cn=acd,ou=group,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk cn:acd description:Acadamic Staff gidNumber:2000 objectClass:posixGroup objectClass:top # students, group, 'your domain'.ws.learn.ac.lk dn:cn=std,ou=group,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk cn:std description:Students gidNumber:5000 objectClass:posixGroup objectClass:top # servers, 'your domain'.ws.learn.ac.lk dn:ou=servers,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk description:servers objectClass:top objectClass:organizationalUnit ou:servers # idp, servers, 'your domain'.ws.learn.ac.lk dn:cn=idp,ou=servers,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk cn:idp description:Identity Server ipHostNumber:192.248.6.XX objectClass:top objectClass:device objectClass:ipHost objectClass:simpleSecurityObject userPassword:{crypt}idpldap # people, 'your domain'.ws.learnac.lk dn:ou=people,dc='your domain',dc=ws,dc=learn,dc=ac,dc=lk description:inst users objectClass:top objectClass:organizationalUnit ou:people # testme, people, 'your domain'.ws.learn.ac.lk dn:uid=testme,ou=people,dc='your domain',dc=ws,dc=learn,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='your domain'dc=ws,dc=learn,dc=ac,dc=lk" -W -Z -f initial.ldif }}} == LDAP Bind == {{{ ldapsearch -H ldap:// -x -D "cn=admin,dc='your domain'dc=ws,dc=learn,dc=ac,dc=lk" -W -Z -b "dc='your domain'dc=ws,dc=learn,dc=ac,dc=lk" }}} Note that Clear-Text userPassword enconded in '''base64''' == Deleting ldap entity == {{{ ldapdelete -H ldap:// "uid=user,ou=people,dc='your domain'dc=ws,dc=learn,dc=ac,dc=lk" -D "cn=admin,dc='your domain'dc=ws,dc=learn,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='your domain'dc=ws,dc=learn,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='your domain'dc=ws,dc=learn,dc=ac,dc=lk')); $servers->setValue('login','bind_id','cn=admin,dc='your domain'dc=ws,dc=learn,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@'your domain'.ws.learn.ac.lk DocumentRoot /var/www/html ServerName idp.'your domain'.ws.learn.ac.lk Redirect permanent /phpldapadmin https://'your domain'.ws.learn.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@'your domain'.ws.learn.ac.lk ServerName idp.'your domain'.ws.learn.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.'your domain'.'ws.learn.ac.lk/phpldapadmin/'' Enter your apache password first and then ldap admin password