Friday, May 20, 2016

Keystone and WebSSO: Using Active Directory Federation Services with OpenStack Keystone

In this post we walk the reader through the following configuration:
  •     Keystone as Service Provider (with Shibboleth Apache Module)
  •     AD FS as Identity Provider
  •     Active Directory as storage for users


First of all I would like to say many thanks to Boris Bobrov (breton). This article was created with his help.

Introduction to Active Directory Federation Services

Active Directory Federation Services (AD FS) is a standards-based service that allows the secure sharing of identity information between trusted business partners (known as a federation) across an extranet. When a user needs to access a Web application from one of its federation partners, the user's own organization is responsible for authenticating the user and providing identity information in the form of "claims" to the partner that hosts the Web application. The hosting partner uses its trust policy to map the incoming claims to claims that are understood by its Web application, which uses the claims to make authorization decisions.
AD FS is Microsoft's implementation of the WS-Federation Passive Requestor Profile protocol (passive indicates that the client requirements are just a cookie- and JavaScript-enabled Web browser). AD FS implements the standards based WS-Federation protocol and Security Assertion Markup Language (SAML).
The SAML specification defines three roles: the Principal (typically a user), the Identity Provider (IdP), and the Service Provider (SP). In the use case addressed by SAML, the Principal requests a service from the Service Provider. The Service Provider requests and obtains an identity assertion from the Identity Provider. On the basis of this assertion, the Service Provider can make an access control decision – in other words it can decide whether to perform some service for the connected Principal.


Keystone should be running under Apache behind SSL. AD FS requires Keystone urls to be https.

  • For devstack use following configuration in your local.conf:

  • For manual configuration:
    • Generate certificates:
sudo mkdir /etc/apache2/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt
    • Copy httpd/wsgi-keystone.conf to /etc/apache2/sites-available/keystone.conf
    • Enable SSL. Add to virtualhost in keystone.conf:
ServerName your_domain.comSSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
    • Enable keystone:
sudo a2ensite keystone
    • Enable Apache ssl module:
sudo a2enmod ssl
    • Restart Apache:
sudo service apache2 restart
Configuring Keystone Service Provider  
Service Provider (SP) - is a system entity that provides services to principals or other system entities, in this case, OpenStack Identity is the Service Provider.

This approach to federation supports keystone as a Service Provider, consuming identity properties issued by an external Identity Provider - SAML assertions.
Federated users are not mirrored in the keystone identity backend (for example, using the SQL driver). The external Identity Provider is responsible for authenticating users, and communicates the result of authentication to keystone using identity properties. Keystone maps these values to keystone user groups and assignments created in keystone.
  1. Enable saml2 authentication method. Make changes in /etc/keystone/keystone.conf:
methods = external,password,token,oauth1,saml2

remote_id_attribute = Shib-Identity-Provider
trusted_dashboard = http://<devstack ip>/dashboard/auth/websso/
  1. Install Shibboleth:
sudo apt-get install libapache2-mod-shib2
  1. Configure your Keystone virtual host and adjust the config to properly handle SAML2 workflow. Append the following lines to the end of the file:
<Location /Shibboleth.sso>
SetHandler shib

<LocationMatch /v3/OS-FEDERATION/identity_providers/.*?/protocols/saml2/auth>
ShibRequestSetting requireSession 1
AuthType shibboleth
ShibExportAssertion Off
Require valid-user
  1. Configure attributes. Shibboleth provides the capability for an IdP to release additional user information to an SP at authentication time. The user information is presented as name-value pairs known as attributes. For this POC we will use custom attribute for user name.  To decode attribute ‘username’ edit the /etc/shibboleth/attribute-map.xml file to add the attributes:
<Attribute name="username" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" id="username">
   <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
  1. Edit the /etc/shibboleth/shibboleth2.xml file to add the Keystone IdP entityID and MetadataProvider:
<ApplicationDefaults entityID="https://<devstack ip>:5000/">
  <SSO entityID="">
Ensure that in shibboleth2.xml <Sessions> has
Here is a full shibboleth2.xml for reference:
  1. Restart Apache:
sudo service apache2 restart
  1. Enable shibboleth module:
sudo a2enmod shib2
Configuring Active Directory Federation Services

Install IIS

  1. Open Server Manager.
  2. Under Manage menu, select Add Roles and Features:
  1. Select Role-based or Feature-based Installation:
  1. Select the appropriate server (local is selected by default).
  2. Select Web Server (IIS):
  1. No additional features are needed for IIS, so click Next:
  1. Click Next.
  2. Customize your installation of IIS, or accept the default settings that have already been selected for you, and then click Next:
  1. Click Install.

Install Active Directory

  1. In Windows Server Manager select “Manage” -> “Add Roles and Features”:
  1. The wizard will appear. Click Next.
  2. Select “Role-based or feature-based installation” and click Next.
  3. Select your server and click Next.
  4. From the Server Roles page place a check mark in the box next to Active Directory Domain Services. A notice will appear explaining additional roles services or features are also required to install domain services, click Add Features
  1. Review and select optional features to install during the AD DS installation by placing a check in the box next to any desired features. Once done click Next.
  2. Review the information on the AD DS tab and click Next.
  3. Review the installation and click Install.
Once the AD DS role is installed the server will need to be configured for your domain.
  1. Open the Notifications Pane by selecting the Notifications icon from the top of the Server Manager. From the notification regarding configuring AD DS click Promote this server to a domain controller.
  1. From the Deployment Configuration tab select Add a new forest from the radial options menu. Insert your root domain name into the Root domain name field.
  1. Enter DSRM password.
  2. Review the warning on the DNS Options tab and select Next.
  1. Confirm or enter a NetBIOS name and click Next.
  2. Configure the location of the SYSVOL, Log files, and Database folders and click Next.
  3. Review the configuration options and click Next.
  4. The system will check to ensure all necessary prerequisites are installed on the system prior to moving forward. If the system passes these checks you will proceed by clicking Install. The server will automatically be rebooted once the installation completes.

Install Certificate Authority:

  1. Open Server Manager – Manage – Add Roles and Features.
  2. Choose : Active Directory Certificate Services. Choose Next:
  1. Choose : Certification Authority, Certification Authority Web Enrollment:
  1. Finish installation.
  2. To Configure Active Directory Certificate Services choose the Exclamation Mark on the Flag
  1. Choose Next
  1. Choose Certificate Authority and Certification Authority Web Enrollment
  1. Choose Enterprise.
  2. Choose Root CA.
  3. Create a new Private key
  1. Have default with 2048 key Character length key.
  2. Click Next
  1. By Default Certificate is valid for 5 years , Don’t make any changes on it , Click next and finish configuration.
  2. Open “mmc”.
  3. File -> “Add/Remove Snap-in”.
  4. Add “Certificate Template” -> “OK”.
  5. Select “Web Server” template. Right click -> “Properties”.
  6. In “Security” tab grant permission to enroll certificate for your user
  1. Click “OK” and close mmc

Enroll Certificate

  1. Open “mmc”.
  2. File -> “Add/Remove Snap-in”.
  3. Select “Certificates” and click Add:
  1. New window will appear. Select “Computer account” and click Next.
  2. Select “Local Computer” and click “Finish”.
  3. Click OK.
  4. In list of certificate Right click on Personal -> View -> Options
  1. Select “Certificate purpose” and click OK.
  2. Right click on  “Server Authentication” -> All tasks -> Request new certificate
  1. Next -> Next -> Select “Web Server” and click on link below to provide more information
  1. After you provide information you will able to enroll certificate.

Active Directory Federation Services

  1. Open DNS manager
  2. Create new host (“feds” in our case”)
  1. Open Server Manager – Manage – Add Roles and Features.
  2. Select “Role-based or feature-based installation” and click Next.
  3. Select your server and click Next.
  4. Check “Active Directory Federation Services” and finish installation.
  5. You should see a yellow exclamation point at the top right to let you know there is additional configuration requirements. Click “Run the AD FS Management snap-in”
  1. You’ll then get the ADFS Snap in to finish configuring. Click “ADFS Federation Server Configuration Wizard”
  2. Select “Create New Federation Service” and hit next.
  3. You should be able to select certificate that we just created - select it and click Next.
  4. Enter credentials for user and finish configuration.
  5. To verify open IE and type : -it should show metadata.

Post-installation configuration

  1. Create Trust Relationship in AD FS:
  • In AD FS Management right click on “Trust Relationships”, select “Add Relying Party Trust”. A wizard will appear. Press “start”
  • Import cloud Metadata. It is accessible by https://<devstack ip>:5000/Shibboleth.sso/Metadata. Either import it via URL or download and import as file. It will say that some of the content was skipped
  • Configure other screens as needed
  1. Edit claim rules:
  • In “Relying Party Trusts” right-click your trust and select “Edit ClaimRules…”
  • On tab “Issuance Transform Rules” press “Add Rule…”
  • In the opened wizard select “Send LDAP attributes as Claims” and press next
  • Select AD or your specific Attribute Store
  • Use “User-Principal-Name” as LDAP Attribute and “username” as an Outgoing Claim and save
  1. Create “/etc/keystone/sso_callback_template.html” (use a template from official keystone docs)

Configuring Federation in Keystone

New users will not be added to the Identity backend, but the Identity Service requires group-based role assignments to authorize federated users. The federation mapping function will map the user into local Identity Service groups objects, and hence to local role assignments.
Thus, it is required to create the necessary Identity Service groups that correspond to the Identity Provider’s groups; additionally, these groups should be assigned roles on one or more projects or domains.
  1. To use “openstack” CLI you need to switch it to using v3 API. Do this:
    • Copy openrc:
    cp openrc openrc.v3
    • Edit openrc.v3 and
      • add there this line:
    • change OS_AUTH_URL to point to v3.
  2. Create an identity provider (idp_1 is an id. Use any you like):
openstack identity provider create idp_1
  1. Create a mapping.  Mapping is a set of rules that tells keystone which group or project or domain the user belongs to. For this POC lets put the user to a static group.  Create a group:
openstack group create --domain default remote_people
it was created with id 0e85a08dad294ad9b6aa9ebb7a969caa,
  1. Create a mapping. Let’s use this one:
       "local": [
               "user": {
                   "name": "{0}",
                   "domain": {"name": "Default"}            
               "group": {              
                   "id": "0e85a08dad294ad9b6aa9ebb7a969caa"
       "remote": [
               "type": "username"          
  1. Save it to a file "mapping.json" and run:
openstack mapping create --rules mapping.json my_mapping
  1. Create a federation protocol for the mapping and identity provider we created above:
openstack federation protocol create --identity-provider idp_1 --mapping my_mapping saml2
Remember the ids we used here:
  • federation protocol: “saml2”
  • identity provider: “idp_1”
  1. Set remote-id of your idp:
openstack identity provider set --remote-id \
'' idp_1

Configuring Horizon

  1. Create /etc/apache2/sites-available.horizon.conf:
<VirtualHost *:80>
     WSGIScriptAlias /dashboard /opt/horizon/openstack_dashboard/wsgi/horizon.wsgi
WSGIDaemonProcess horizon user=xusha group=xusha processes=3 threads=10 home=/opt/horizon display-name=%{GROUP}
WSGIApplicationGroup %{GLOBAL}

WSGIProcessGroup horizon

DocumentRoot /opt/horizon/.blackhole/
Alias /dashboard/media /opt/horizon/openstack_dashboard/static
Alias /dashboard/static /opt/horizon/static

RedirectMatch "^/$" "/dashboard/"

<Directory />
    Options FollowSymLinks
    AllowOverride None

<Directory /opt/horizon/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    # Apache 2.4 uses mod_authz_host for access control now (instead of
    #  "Allow")
    <IfVersion < 2.4>
        Order allow,deny
        Allow from all
    <IfVersion >= 2.4>
        Require all granted
<IfVersion >= 2.4>
  ErrorLogFormat "%{cu}t %M"
ErrorLog /var/log/apache2/horizon_error.log
LogLevel warn
CustomLog /var/log/apache2/horizon_access.log combined

WSGISocketPrefix /var/run/apache2
  1. Add to /etc/apache2/sites-available.keystone.conf:
<LocationMatch /v3/auth/OS-FEDERATION/identity_providers/.*?/protocols/saml2/websso>
ShibRequestSetting requireSession 1
AuthType shibboleth
ShibExportAssertion Off
Require valid-user

<Location /v3/auth/OS-FEDERATION/websso/saml2>
ShibRequestSetting requireSession 1
AuthType shibboleth
ShibExportAssertion Off
Require valid-user
  1. Set variables in horizon/openstack_dashboard/local/
LOGIN_URL = WEBROOT + 'auth/login/'
LOGOUT_URL = WEBROOT + 'auth/logout/'
 "identity": 3,
  ("credentials", _("Keystone Credentials")),
  ("saml2", _("Security Assertion Markup Language"))    
OPENSTACK_KEYSTONE_URL = "https://<devstack ip>:5000/v3"
  1. Modify /etc/keystone.keystone.conf:
sso_callback_template = /etc/keystone/sso_callback_template.html
  1. Copy sso_callback_template.html to the /etc/keystone:
cp /opt/stack/keystone/etc/sso_callback_template.html /etc/keystone
  1. Enable horizon, restart Apache:
sudo a2ensite horizon
sudo service apache2 restart

Logging in to Horizon

  1. You will have dropdown list with websso_choices:
  1. Select "Security Assertion Markup Language" and you will be redirected to AD FS login page:
  1. Enter credentials:


  1. If the windows pc from which the user logs in is already in the same windows domain, would he still go through the SSO ADFS login page. I am looking for automatic login from the corporate windows login. The federated SSO, use case for cross domain is what is explained here. If in case the user is already in the same domain and he wants to login to keystone, I wanted user to directly gets access without having him to enter the credentials.

    If we have to write our own web application using Keystone REST API (e.g. custom horizon web management app) and wanted to use AD to seamless integration with the WEB app with option to use Federated authentication using SML2 flow when required.

    We wanted to support both scenarios of local deployment as private cloud and/or deployed as public cloud where Federation is required.

    1. Imocha, I think it is just about ADFS configuration. In my article I use Windows machine only as server, but if you use Windows machine as a client - you can configure ADFS to do not ask credentials but authenticate using windows authentication.

  2. Can you re-check picture this topic?