Authent

Kerberos authentication for Keystone (OpenStack)

By Gauvain Pocentek, Cloud Consultant @Objectif Libre

This blogpost describes how you can improve OpenStack Keystone authentication security, thanks to Kerberos/

Intended audience: OpenStack administrators, already familiar with Keystone deployment and concepts.

Keystone is the OpenStack component responsible for user authentication on a cloud platform. Default and standard authentication requires sending login and password to Keystone, using an API call. User passwords are often stored in plain text in unencrypted authentication files. Which is not secure. Even if the password is prompted when sourcing an RC file (such as the one you can download from the Horizon GUI), it still resides in the shell environment.

Keystone can rely on external systems to validate user credentials. Once the user has been authenticated, Keystone generates a token as usual, and this token is used to communicate with all the OpenStack APIs.

Let’s see now how you can configure Keystone to allow users to authenticate with their Kerberos ticket instead of the usual login/password.

Pre-requisites

This blog assumes that you have a working Keystone installation, and a working LDAP-backed Kerberos server (this could be a manually installed server, a freeIPA server, an Active Directory server, or whatever tool provides both LDAP and Kerberos services). Installing and understanding these services is out of scope for this article.

We use the following information in the examples:

  • Kerberos realm: OL.CORP
  • Keystone domain name: olcorp
  • Kerberos admin and kdc servers: kerberos.ol.corp
  • Keystone base URL: https://ks-krb.ol.corp:5000
  • Test user login: user1

Let’s configure

The following steps are needed to make the Kerberos authentication work:

  • Add a kerberos principal and generate a keytab file for the httpd server exposing Keystone: the kerberos authentication is actually done by the web server, not Keystone itself
  • Configure httpd to support the kerberos authentication on a specific URL, to support both password and kerberos-based authentication
  • Enable LDAP domain support in Keystone
  • Configure Keystone’s [auth] section for kerberos

Kerberos setup

The httpd server running the Keystone WSGI script needs to be kerberized. This means creating a principal for the service, and an associated keytab file. How you do that depends on the Kerberos service you use.

The following example works with an MIT Kerberos server:

# kadmin.local
kadmin.local: addprinc -randkey HTTP/ks-krb.ol.corp
kadmin.local: ktadd -k /tmp/http.keytab HTTP/ks-krb.ol.corp

Upload the /tmp/http.keytab file to the Keystone server (in /etc/apache2 or /etc/httpd for example). It will be used later, in the httpd configuration file.

Enable LDAP authentication on Keystone

In this example we use a dedicated domain for LDAP authentication, for multiple reasons:

  • The default domain hosting the system users can stay unmodified
  • We can still use basic username/password authentication for the cloud admin
  • No need to add system users to the LDAP directory
  • It’s easy to add new domains, each connected to its own directory

To enable the multi-domain configuration, modify the following settings in keystone.conf:

[identity]
domain_specific_drivers_enabled = True
domain_config_dir = /etc/keystone/domains

The /etc/keystone/domains/ folder will contain the definition of authentication back-ends for the domains.

The olcorp domain settings are definied in /etc/keystone/domains/keystone.olcorp.conf. Make sure to respect the keystone.DOMAIN_NAME.conf format for the file name otherwise Keystone will not find the settings:

[identity]
driver = ldap

[ldap]
url = ldaps://ldap.ol.corp
suffix = dc=ol,dc=corp
user = cn=keystone,ou=apps,dc=ol,dc=corp
password = s3cr3t
...

You can refer to the Keystone documentation for a complete description of this configuration file.

Restart Keystone and make sure everything works:

$ sudo systemctl restart apache2  # or httpd
$ . adminrc  # login as cloud admin
$ openstack domain create olcorp
$ PROJECT_ID=$(openstack project create --domain olcorp test -f value -c id)
$ USER_ID=$(openstack user show user1 -f value -c id)
$ openstack role add --user $USER_ID --project $PROJECT_ID _member_

You should be able to login as an LDAP user on Keystone (and horizon) in the olcorp domain.

Enable Kerberos authentication on httpd

The httpd / mod_wsgi setup for Keystone will be modified to expose 2 base URLs:

  • On /: standard login/password authentication
  • On /krb/: kerberos authentication

Only the /krb/v3/auth/tokens location needs to be kerberized, as this is the only authentication endpoint for Keystone.

Update the WSGI configuration file (for example /etc/apache2/sites-enabled/wsgi-keystone.conf):

<VirtualHost *:5000>
    ...
    WSGIScriptAlias /krb /usr/bin/keystone-wsgi-public
    WSGIScriptAlias / /usr/bin/keystone-wsgi-public
    ...

    <Location "/krb/v3/auth/tokens">
        LogLevel debug
        AuthType              Kerberos
        AuthName              "Kerberos Login"
        KrbMethodNegotiate    On
        KrbMethodK5Passwd     Off
        KrbServiceName        HTTP
        KrbAuthRealms         OL.CORP
        Krb5KeyTab            /path/to/http.keytab
        KrbVerifyKDC          Off
        KrbLocalUserMapping   On
        KrbAuthoritative      On
        Require valid-user
        SetEnv REMOTE_DOMAIN olcorp
    </Location>
</VirtualHost>

When httpd validates a user’s credentials, a REMOTE_USER environment variable containing the user login is sent to Keystone. The additional REMOTE_DOMAIN variable is set to help Keystone find the user information in the correct domain.

Make sure that Keystone supports this behaviour by adding the kerberos auth method in keystone.conf:

[auth]
methods = external,password,token,oauth1,kerberos

Restart httpd to apply all the changes:

$ sudo systemctl restart apache2  # or httpd

Test the authentication

You should still be able to authenticate using your login and password:

$ source keystonerc  # downloaded from horizon for example
$ openstack token issue

But you can also use a kerberos authentication (note the OS_AUTH_URL variable):

$ kinit
Password for user1@OL.CORP:
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user1@OL.CORP
$ export OS_AUTH_URL=https://ks-krb.ol.corp:5000/krb/v3
$ export OS_AUTH_TYPE=v3kerberos
$ export OS_PROJECT_DOMAIN_ID=17957a91111c44378b08c1f0c58b9e60
$ export OS_PROJECT_NAME=test
$ export OS_IDENTITY_API_VERSION=3
$ openstack token issue -f value -c id
gAAAAABahuuzhdSxSL2vgD99umDKU3Kd_6HQuoahfGm...

Conclusion

Kerberos authentication is common and secure, and setting up Keystone to use it is quite straightforward.

If you are already using Kerberos, you should consider it for you OpenStack users authentication as well.