Overview
OpenShift provides a fairly simple and straightforward authentication provider for use with LDAP setups. It has one major limitation, however: it can only connect to a single LDAP server. This can be problematic if that LDAP server becomes unavailable for any reason. When this happens, end-users get very unhappy.
Enter SSSD. Originally designed to manage local and remote authentication to the host OS, it can now be configured to provide identity, authentication and authorization services to web services like OpenShift as well. It provides a multitude of advantages over the built-in LDAP provider; in particular it has the ability to connect to any number of failover LDAP servers as well as to cache authentication attempts in case it can no longer reach any of those servers.
These advantages don’t come without a cost, of course: the setup of this configuration is somewhat more advanced, so I’m writing up this guide to help you get it set up. Rather than adding a few lines to the master-config.yml in OpenShift and calling it a day, we are going to need to set up a separate authentication server that OpenShift will talk to. This guide will describe how to do it on a dedicated physical or virtual machine, but the concepts should also be applicable to loading up such a setup in a container as well. (And in the future, I will be looking into whether we could build such a static container right into OpenShift, but for now this document will have to suffice.) For this guide, I will use the term VM to refer to either type of machine, simply because it’s shorter to type and read.
This separate authentication server will be called the “authenticating proxy” from here on out and describes a solution that will provide a specialized httpd server that will handle the authentication challenge and return the results to the OpenShift Server. See the OpenShift documentation for security considerations around the use of an authenticating proxy.
Formatting Notes
- If you see something in italics within a source-code block below, you should replace it with the appropriate value for your environment.
- Source-code blocks with a leading ‘#’ character indicates a command that must be executed as the “root” user, either by logging in as root or using the sudo command.
- Source-code blocks with a leading ‘$’ character indicates a command that may be executed by any user (privileged or otherwise). These commands are generally for testing purposes.
Prerequisites
You will need to know the following information about your LDAP server to follow the directions below:
- Is the directory server powered by FreeIPA, Active Directory or another LDAP solution?
- What is the URI for the LDAP server? e.g. ldap.example.com
- Where is the CA certificate for the LDAP server?
- Does the LDAP server correspond to RFC 2307 or RFC2307bis for user-groups?
Prepare VMs:
- proxy.example.com: A VM to use as the authenticating proxy. This machine must have at least SSSD 1.12.0 available, which means a fairly recent operating system. In these examples, I will be using a clean install of Red Hat Enterprise Linux 7.2 Server.
- openshift.example.com: A VM to use to run OpenShift
(These machines *can* be configured to run on the same system, but for the purposes of this tutorial, I am keeping them separate)
Phase 1: Certificate Generation
In order to ensure that communication between the authenticating proxy and OpenShift is trustworthy, we need to create a set of TLS certificates that we will use during the other phases of this setup. For the purposes of this demo, we will start by using the auto-generated certificates created as part of running
# openshift start \
--public-master=https://openshift.example.com:8443 \
--write-config=/etc/origin/
Among other things, this will generate /etc/origin/master/ca.{cert|key}
. We will use this signing certificate to generate keys to use on the authenticating proxy.
# mkdir -p /etc/origin/proxy/
# oadm ca create-server-cert \
--cert='/etc/origin/proxy/proxy.example.com.crt' \
--key='/etc/origin/proxy/proxy.example.com.key' \
--hostnames=proxy.example.com,1.2.3.4 \
--signer-cert=/etc/origin/master/ca.crt \
--signer-key='/etc/origin/master/ca.key' \
--signer-serial='/etc/origin/master/ca.serial.txt'
For the hostnames, ensure that any hostnames and interface IP addresses that might need to access the proxy are listed, otherwise the HTTPS connection will fail.
Next, we will generate the API client certificate that the authenticating proxy will use to prove its identity to OpenShift (this is necessary so that malicious users cannot impersonate the proxy and send fake identities). First, we will create a new CA to sign this client certificate.
# oadm ca create-signer-cert \
--cert='/etc/origin/proxy/proxyca.crt' \
--key='/etc/origin/proxy/proxyca.key' \
--name='openshift-proxy-signer@`date +%s`
' \
--serial='/etc/origin/proxy/proxyca.serial.txt'
(The date +%s
in that block is used to make the signer unique. You can use any name you prefer, however.)
# oadm create-api-client-config \
--certificate-authority='/etc/origin/proxy/proxyca.crt' \
--client-dir='/etc/origin/proxy' \
--signer-cert='/etc/origin/proxy/proxyca.crt' \
--signer-key='/etc/origin/proxy/proxyca.key' \
--signer-serial='/etc/origin/proxy/proxyca.serial.txt' \
--user='system:proxy'
# cat /etc/origin/proxy/system\:proxy.crt \
/etc/origin/proxy/system\:proxy.key \
> /etc/origin/proxy/authproxy.pem
Phase 2: Authenticating Proxy Setup
Step 1: Copy certificates
From openshift.example.com, securely copy the necessary certificates to the proxy machine:
# scp /etc/origin/proxy/master/ca.crt \
root@proxy.example.com:/etc/pki/CA/certs/
# scp /etc/origin/proxy/proxy.example.com.crt \
/etc/origin/proxy/authproxy.pem \
root@proxy.example.com:/etc/pki/tls/certs/
# scp /etc/origin/proxy/proxy.example.com.key \
root@proxy.example.com:/etc/pki/tls/private/
Step 2: SSSD Configuration
Install a new VM with a recent operating system (in order to use the mod_identity_lookup module later, it will need to be running SSSD 1.12.0 or later). In these examples, I will be using a clean install of Red Hat Enterprise Linux 7.2 Server.
First thing is to install all of the necessary dependencies:
# yum install -y sssd \
sssd-dbus \
realmd \
httpd \
mod_session \
mod_ssl \
mod_authnz_pam
This will give us the SSSD and the web server components we will need. The first step here will be to set up SSSD to authenticate this VM against the LDAP server. If the LDAP server in question is a FreeIPA or Active Directory environment, then realmd can be used to join this machine to the domain. This is the easiest way to get up and running.
realm join ldap.example.com
If you aren’t running a domain, then your best option is to use the authconfig tool (or follow the many other tutorials on the internet for configuring SSSD for identity and authentication).
# authconfig --update --enablesssd --enablesssdauth \
--ldapserver=ldap.example.com \
--enableldaptls \
--ldaploadcert=http://ldap.example.com/ca.crt
This should create /etc/sssd/sssd.conf with most of the appropriate settings. (Note: RHEL 7 appears to have a bug wherein authconfig does not create the /etc/openldap/cacerts directory, so you may need to create it manually before running the above command.)
If you are interested in using SSSD to manage failover situations for LDAP, this can be configured simply by adding additional entries in /etc/sssd/sssd.conf
on the ldap_uri
line. Systems enrolled with FreeIPA will automatically handle failover using DNS SRV records.
Finally, restart SSSD to make sure that all of the changes are applied properly:
$ systemctl restart sssd.service
Now, test that the user information can be retrieved properly:
$ getent passwd <username>
username:*:12345:12345:Example User:/home/username:/usr/bin/bash
At this point, it is wise to attempt to log into the VM as an LDAP user and confirm that the authentication is properly set up. This can be done via the local console or a remote service such as SSH. (Later, you can modify your /etc/pam.d files to disallow this access if you prefer.) If this fails, consult the SSSD troubleshooting guide.
Step 3: Apache Configuration
Now that we have the authentication pieces in place, we need to set up Apache to talk to SSSD. First, we will create a PAM stack file for use with Apache. Create the /etc/pam.d/openshift file and add the following contents:
auth required pam_sss.so
account required pam_sss.so
This will tell PAM (the pluggable authentication module) that when an authentication request is issued for the “openshift” stack, it should use pam_sss.so to determine authentication and access-control.
Next we will configure the Apache httpd.conf. (Taken from the OpenShift documentation and modified for SSSD.) For this tutorial, we’re only going to set up the challenge authentication (useful for logging in with oc login
and similar automated tools). A future entry in this series will describe setup to use the web console.
First, create the new file openshift-proxy.conf
in /etc/httpd/conf.d (substituting the correct hostnames where indicated):
LoadModule request_module modules/mod_request.so
LoadModule lookup_identity_module modules/mod_lookup_identity.so
# Nothing needs to be served over HTTP. This virtual host simply redirects to
# HTTPS.
<VirtualHost *:80>
DocumentRoot /var/www/html
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R,L]
</VirtualHost>
<VirtualHost *:443>
# This needs to match the certificates you generated. See the CN and X509v3
# Subject Alternative Name in the output of:
# openssl x509 -text -in /etc/pki/tls/certs/proxy.example.com.crt
ServerName proxy.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/proxy.example.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/proxy.example.com.key
SSLCACertificateFile /etc/pki/CA/certs/ca.crt
# Send logs to a specific location to make them easier to find
ErrorLog logs/proxy_error_log
TransferLog logs/proxy_access_log
LogLevel warn
SSLProxyEngine on
SSLProxyCACertificateFile /etc/pki/CA/certs/ca.crt
# It's critical to enforce client certificates on the Master. Otherwise
# requests could spoof the X-Remote-User header by accessing the Master's
# /oauth/authorize endpoint directly.
SSLProxyMachineCertificateFile /etc/pki/tls/certs/authproxy.pem
# Send all requests to the console
RewriteEngine On
RewriteRule ^/console(.*)$ https://%{HTTP_HOST}:8443/console$1 [R,L]
# In order to using the challenging-proxy an X-Csrf-Token must be present.
RewriteCond %{REQUEST_URI} ^/challenging-proxy
RewriteCond %{HTTP:X-Csrf-Token} ^$ [NC]
RewriteRule ^.* - [F,L]
<Location /challenging-proxy/oauth/authorize>
# Insert your backend server name/ip here.
ProxyPass https://openshift.example.com:8443/oauth/authorize
AuthType Basic
AuthBasicProvider PAM
AuthPAMService openshift
Require valid-user
</Location>
<ProxyMatch /oauth/authorize>
AuthName openshift
RequestHeader set X-Remote-User %{REMOTE_USER}s env=REMOTE_USER
</ProxyMatch>
</VirtualHost>
RequestHeader unset X-Remote-User
Then we need to tell SELinux that it’s acceptable for Apache to contact the PAM subsystem, so we set a boolean:
# setsebool -P allow_httpd_mod_auth_pam on
At this point, we can start up Apache.
# systemctl start httpd.service
Phase 3: OpenShift Configuration
This describes how to set up an OpenShift server from scratch in an “all in one” configuration. For more complicated (and interesting) setups, consult the official OpenShift documentation.
First, we need to modify the default configuration to use the new identity provider we just created. We’ll start by modifying the /etc/origin/master/master-config.yaml
file. Scan through it and locate the identityProviders section and replace it with:
identityProviders:
- name: any_provider_name
challenge: true
login: false
mappingMethod: claim
provider:
apiVersion: v1
kind: RequestHeaderIdentityProvider
challengeURL: "https://proxy.example.com/challenging-proxy/oauth/authorize?${query}"
clientCA: /etc/origin/master/proxy/proxyca.crt
headers:
- X-Remote-User
Now we can start openshift with the updated configuration:
# openshift start \
--public-master=https://openshift.example.com:8443 \
--master-config=/etc/origin/master/master-config.yaml \
--node-config=/etc/origin/node-node1.example.com/node-config.yaml
Now you can test logins with
oc login https://openshift.example.com:8443
It should now be possible to log in with only valid LDAP credentials. Stay tuned for further entries in this series where I will teach you how to set up a “login” provider for authenticating the web console, how to retrieve extended user attributes like email address and full name from LDAP, and also how to set up automatic single-sign-on for users in a FreeIPA or Active Directory domain.
Updates 2016-05-27: There were some mistakes in the httpd.conf as originally written that made it difficult to set up Part 2. They have been retroactively corrected. Additionally, I’ve moved the incomplete configuration of extended attributes out of this entry and will reintroduce them in a further entry in this series.