Skip to main content

LDAP TLS/SSL Config for the Shibboleth IdP Explained

Many Shibboleth IdP adopters use LDAP as an authentication provider and an attribute source. There is always the question of "do we need to configure TLS/SSL for the IdP's connection to the LDAP server(s)?" My response is "always," because we need to protect the user's credentials even in the most trusted network. My question back to the client is, "Why wouldn't you?" Often the response is somewhere between "we've tried and we got it to work once, but then it broke sometime" and "we could never get it to work." My goal with this post is to take the mystery out of configuring the IdP to use TLS when connecting to an LDAP Server. It should be noted that all of these concepts apply to things like CAS Server as well.

TLS Connection Types

The IdP supports two TLS connection types. The first is straight TLS, and is usually called SSL in the IdP configs, etc. This is generally what we think about when we think of SSL (now deprecated) and TLS. With straight TLS (or SSL), the LDAP Server has a dedicated port for the TLS connection. Usually, it is TCP/636. A typical connection config in conf/ldap.properties would look like: 

## Connection properties ##
idp.authn.LDAP.ldapURL                         = ldaps://ldap.organization.edu:636
idp.authn.LDAP.useStartTLS                     = false
idp.authn.LDAP.useSSL                          = true

The ldapURL protocol is changed to "ldaps" and the port set to ":636". useStartTLS is set to "false" and useSSL is set to "true".

The second connection type is called StartTLS. With StartTLS, the connection starts out as clear text communication over the standard port (TCP/389). The client tells the LDAP Server to convert the session to a secure TLS connection, and TLS negotiation starts up like it does under a standard TLS-only connection. Personally, I like StartTLS because you can use the same TCP port for both clear text and secured traffic. It makes firewall rules much easier, but alas, because it requires protocol enhancements to the widely adopted spectrum of Internet services, it didn't gain much traffic... But many LDAP servers do support it. The config looks something like:

## Connection properties ##
idp.authn.LDAP.ldapURL                         = ldap://ldap.organization.edu:389
idp.authn.LDAP.useStartTLS                     = true
idp.authn.LDAP.useSSL                          = false

The ldapURL protocol is "ldap" and the port set to ":389", or just left off altogether. useStartTLS is set to "true" and useSSL is set to "false".

Trust Types

So now that we have told the IdP's LDAP client​ to use TLS, when it connects the LDAP server is going to present one or more X.509 certificates. The server's certificate is used to identify the server and contains additional information about the certificates validity period. Unless the certificate is self-signed, the certificate also has a signer that is used to link to another certificate. These additional certificates form a chain back to a certificate authority's (CA) root certificate. Windows, browsers and even the Oracle JVM come with a set of trusted root CAs pre-installed. The IdP's LDAP client usually needs to be told what certificate to trust. This can either be the server's certificate or the CA that signed the server certificate's root certificate. I prefer to use the CA root cert since that allows the LDAP Server Admin to revoke, renew, etc the LDAP server cert without affecting the IdP... as long as the CA does not change its root certificate.

Either way, sometimes getting these certificates from the LDAP Admin can be difficult. So here's an easy way to get them.. use OpenSSL: 

openssl s_client -connect ldap.organization.edu:636 -showcerts

This will dump a bunch of stuff, but what we are concerned about are the big blocks of text that start and end with "-----". Each one of those blocks is a certificates in PEM format. The first one will usually be the server certificate. The last one is usually the root. You can tell a root certificate because the issuer and the "s:" and "i:" values before it are the same. If the LDAP server uses a self-signed certificate, then there will just be one entry and the "s:" and "i:" will be the same. Here's an example of the root cert response currently used by standard InCommon certs:

   s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----

Which ever certificate style you want to use, grab the appropriate block. Be sure to include the "-----" lines at the beginning and end of the block. Save it to a file. Next, you need to tell the IdP where the file is stored. By default, the IdP will look in "%{idp.home}/credentials/ldap-server.crt". I would recommend placing the file there. Maybe you want to change the name, particularly if you are using a root. You can change the path by changing trustCertificates in "conf/ldap.properties".

## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
#idp.authn.LDAP.sslConfig                       = certificateTrust
## If using certificateTrust above, set to the trusted certificate's path
idp.authn.LDAP.trustCertificates                = %{idp.home}/credentials/ldap-server.crt
## If using keyStoreTrust above, set to the truststore path
idp.authn.LDAP.trustStore                       = %{idp.home}/credentials/ldap-server.truststore

You maybe noticing the trustStore property. Well that's the method that uses the Java Keystore technology that I blame for stumping many TLS/SSL configurers. If you want to use that method, go for it, but I'm not going to tell you how, because using the PEM file is way, way easier than anything with the keystore. Just trust me... If you do want to self-inflict pain and use the keystore method (against my advice) you'll want to uncomment the  sslConfig property and set it to "keyStoreTrust" and point the trustStore property to that keystore.

Hopefully, you can see that configuring the Shibboleth IdP (or CAS Server 4.1+)'s LDAP connection to use TLS is very straight forward and will only take you a few minutes of effort.

John Gasper

John Gasper

Software Architect
John Gasper is a wonderful mix of Identity and Access Management (IAM) consultant and DevOps implementer. By day, he is implementing, configuring, or advising on one of the many open source IAM applications including CAS Server, Shibboleth, Grouper, SimpleSAMLphp, 389 Directory Server, and occasionally on a closed source applications like Microsoft Active Directory and Active Directory Federation Services. By night, John tries to automate the world of IT using tools, such as Docker, Jenkins, and Kubernetes. He has experience with cloud providers including Amazon Web Services (AWS), Google Cloud Platform, and Microsoft Azure. Before joining Unicon in 2013, he worked in IT at Eastern Washington University covering multiple facets of IT including Banner development and administration, Active Directory administration, and pretty much everything in between. They even let him write code for Cisco IP Phone applications