Chapter 4. Configuring Red Hat OpenStack Platform for Federation

The following nodes require an assigned Fully-Qualified Domain Name (FQDN):

  • The host running the Dashboard (horizon).
  • The host running the Identity Service (keystone), referenced in this guide as $FED_KEYSTONE_HOST. Note that more than one host will run a service in a high-availability environment, so the IP address is not a host address but rather the IP address bound to the service.
  • The host running RH-SSO.
  • The host running IdM.

The Red Hat OpenStack Platform director deployment does not configure DNS or assign FQDNs to the nodes, however, the authentication protocols (and TLS) require the use of FQDNs.

4.1. Retrieving the IP address

In Red Hat OpenStack Platform, there is one common public IP address for all OpenStack services, separated by port number. To determine the public IP address of the overcloud services, use the openstack endpoint list command:

(overcloud) [stack@director ~]$ openstack endpoint list -c "Service Name" -c Interface -c URL | grep public

| swift        | public    | http://10.0.0.101:8080/v1/AUTH_%(tenant_id)s |
| panko        | public    | http://10.0.0.101:8977                       |
| nova         | public    | http://10.0.0.101:8774/v2.1                  |
| glance       | public    | http://10.0.0.101:9292                       |
| neutron      | public    | http://10.0.0.101:9696                       |
| keystone     | public    | http://10.0.0.101:5000                       |
| cinderv2     | public    | http://10.0.0.101:8776/v2/%(tenant_id)s      |
| placement    | public    | http://10.0.0.101:8778/placement             |
| cinderv3     | public    | http://10.0.0.101:8776/v3/%(tenant_id)s      |
| heat         | public    | http://10.0.0.101:8004/v1/%(tenant_id)s      |
| heat-cfn     | public    | http://10.0.0.101:8000/v1                    |
| gnocchi      | public    | http://10.0.0.101:8041                       |
| aodh         | public    | http://10.0.0.101:8042                       |
| cinderv3     | public    | http://10.0.0.101:8776/v3/%(tenant_id)s      |

4.2. Setting the host variables and naming the host

You must determine the IP address and port to use. In this example, the IP address is 10.0.0.101 and the port is 13000.

  1. Confirm this value in overcloudrc:

    export OS_AUTH_URL=https://10.0.0.101:13000/v2.0
  2. Assign the IP address a fully qualified domain name (FQDN), and write it to the /etc/hosts file. This example uses overcloud.localdomain:

    10.0.0.101 overcloud.localdomain # FQDN of the external VIP
    Note

    Although Red Hat OpenStack Platform director configures the hosts files on the overcloud nodes, you might need to add the host entry on any external hosts that participate.

  3. Set the $FED_KEYSTONE_HOST and $FED_KEYSTONE_HTTPS_PORT in the fed_variables file. This example uses the same values:

    FED_KEYSTONE_HOST="overcloud.localdomain"
    FED_KEYSTONE_HTTPS_PORT=13000

Because Mellon runs on the Apache server that hosts Identity service (keystone), the Mellon host:port and keystone host:port values must match.

Note

If you run the hostname command on one of the Controller nodes, is output is similar to controller-0.localdomain. This is an internal cluster name, not its public name. Use the public IP address instead.

4.3. Installing helper files

You must install the helper files as part of the configuration.

4.4. Setting your deployment variables

The file fed_variables contains variables specific to your federation deployment. These variables are referenced in this guide as well as in the configure-federation helper script. Each site-specific federation variable is prefixed with FED_. Ensure that every FED_ variable in fed_variables is provided a value.

4.5. Copying the helper files

You must have the configuration file and variable files on controller-0 to continue.

  • Copy the configure-federation and the edited fed_variables from the ~/stack home directory on undercloud-0 to the ~/heat-admin home directory on controller-0:
$ scp configure-federation fed_variables heat-admin@controller-0:/home/heat-admin
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation copy-helper-to-controller

4.6. Initializing the working environments

  1. On the undercloud node, as the stack user, create the fed_deployment directory. This location is the file stash:

    $ su - stack
    $ mkdir fed_deployment
    Note

    You can use the configure-federation script to perform the previous step:

    $ ./configure-federation initialize
  2. Use SSH to connect to controller-0, and create the ~/fed_deployment directory as the head-admin user. This location is the file stash:

    $ ssh heat-admin@controller-0
    $ mkdir fed_deployment
    Note

    You can use the configure-federation script to perform the previous step. From the controller-0 node:

    $ ./configure-federation initialize

4.7. Installing mod_auth_mellon

You must install the mod_auth_mellon on each controller in your environment.

  • On each controller, run the following:

    $ ssh heat-admin@controller-n # replace n with controller number
    $ sudo dnf install mod_auth_mellon

4.8. Adding the RH-SSO FQDN to each Controller

Ensure that every controller is reachable by its fully-qualified domain name (FQDN).

  • The mellon service runs on each Controller node and connects to the RH-SSO IdP. If the FQDN of the RH-SSO IdP is not resolvable through DNS, manually add the FQDN to the /etc/hosts file on all controller nodes after the Heat Hosts section:

    $ ssh heat-admin@controller-n
    $ sudo vi /etc/hosts
    
    # Add this line (substituting the variables) before this line:
    # HEAT_HOSTS_START - Do not edit manually within this section!
    ...
    # HEAT_HOSTS_END
    $FED_RHSSO_IP_ADDR $FED_RHSSO_FQDN

4.9. Installing and configuring Mellon on the Controller node

The keycloak-httpd-client-install tool performs many of the steps needed to configure mod_auth_mellon and have it authenticate against the RH-SSO IdP. Run the keycloak-httpd-client-install tool on the node where mellon runs. In this example, mellon runs on the overcloud controllers protecting the Identity service (keystone).

Note

Red Hat OpenStack Platform is a high availability deployment with multiple overcloud Controller nodes, each running identical copies. As a result, you must replicate the mellon configuration on each Controller node. To do this, install and configure mellon on controller-0, and collect the configuration files that the keycloak-httpd-client-install tool created into a tar file. Use Object Storage (swift) to copy the archive to each Controller and unarchive the files there.

  • Run the RH-SSO client installation:

      $ ssh heat-admin@controller-0
      $ dnf -y install keycloak-httpd-client-install
      $ sudo keycloak-httpd-client-install \
       --client-originate-method registration \
       --mellon-https-port $FED_KEYSTONE_HTTPS_PORT \
       --mellon-hostname $FED_KEYSTONE_HOST  \
       --mellon-root /v3 \
       --keycloak-server-url $FED_RHSSO_URL  \
       --keycloak-admin-password  $FED_RHSSO_ADMIN_PASSWORD \
       --app-name v3 \
       --keycloak-realm $FED_RHSSO_REALM \
       -l "/v3/auth/OS-FEDERATION/websso/mapped" \
       -l "/v3/auth/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/websso" \
       -l "/v3/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/auth"
    Note

    You can use the configure-federation script to perform the above step: $ ./configure-federation client-install

After the client RPM installation, you should see output similar to this:

  [Step  1] Connect to Keycloak Server
  [Step  2] Create Directories
  [Step  3] Set up template environment
  [Step  4] Set up Service Provider X509 Certificates
  [Step  5] Build Mellon httpd config file
  [Step  6] Build Mellon SP metadata file
  [Step  7] Query realms from Keycloak server
  [Step  8] Create realm on Keycloak server
  [Step  9] Query realm clients from Keycloak server
  [Step 10] Get new initial access token
  [Step 11] Creating new client using registration service
  [Step 12] Enable saml.force.post.binding
  [Step 13] Add group attribute mapper to client
  [Step 14] Add Redirect URIs to client
  [Step 15] Retrieve IdP metadata from Keycloak server
  [Step 16] Completed Successfully

4.10. Editing the Mellon configuration

During the IdP-assertion-to-Keystone mapping phase, your groups must be in a semicolon separated list. Use the following procedure to configure mellon so that when it receives multiple values for an attribute, it combines them into a semicolon-separated single value.

Procedure

  1. Open the v3_mellon_keycloak_openstack.conf configuration file for editing:
$ vi /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/v3_mellon_keycloak_openstack.conf
  1. Add the MellonMergeEnvVars parameter to the <Location /v3> block:

      <Location /v3>
          ...
          MellonMergeEnvVars On ";"
      </Location>

4.11. Creating an archive of the generated configuration files

To replicate the mellon configuration on all Controller nodes, create an archive of the files to install on each Controller node. Store the archive in the ~/fed_deployment subdirectory.

  1. Create the compressed archive:

    mkdir fed_deployment && cd fed_deployment
    tar -czvf rhsso_config.tar.gz \
      --exclude '*.orig' \
      --exclude '*~' \
      /var/lib/config-data/puppet-generated/keystone/etc/httpd/federation \
      /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/v3_mellon_keycloak_openstack.conf
Note

You can use the configure-federation script to perform the previous step:

$ ./configure-federation create-sp-archive

4.12. Retrieving the Mellon configuration archive

  • On the undercloud-0 node, retrieve the archive you created and extract the files so that you can access the data as needed in subsequent steps.

    $ scp heat-admin@controller-0:/home/heat-admin/fed_deployment/rhsso_config.tar.gz ~/fed_deployment
    $ tar -C fed_deployment -xvf fed_deployment/rhsso_config.tar.gz
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation fetch-sp-archive

4.13. Preventing Puppet from deleting unmanaged HTTPD files

By default, the Puppet Apache module purges any files in Apache configuration directories that it does not manage. This prevents Apache from operating against the configuration that Puppet enforces. However, this conflicts with the manual configuration of mellon in the HTTPD configuration directories. The Apache Puppet apache::purge_configs flag is enabled by default, which directs Puppet to delete files that belong to the mod_auth_mellon RPM. Puppet also deletes the configuration files that keycloak-httpd-client-install generates. Until Puppet controls the mellon files, disable the apache::purge_configs flag.

Note

Disabling the apache::purge_configs flag opens the Controller nodes to vulnerabilities. Re-enable it when Puppet adds support managing mellon.

To override the apache::purge_configs flag, create a Puppet file that contains the override, and add the override file to the list of Puppet files you use when you run the overcloud_deploy.sh script.

  1. Create the fed_deployment/puppet_override_apache.yaml environment file and add the following content:

      parameter_defaults:
        ControllerExtraConfig:
          apache::purge_configs: false
  2. Add puppet_override_apache.yaml as the last environment file in the overcloud_deploy.sh script:

    ...
      -e /home/stack/fed_deployment/puppet_override_apache.yaml \
      --log-file overcloud_deployment_14.log &> overcloud_install.log
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation puppet-override-apache

4.14. Configuring Identity service (keystone) for federation

Keystone domains require extra configuration. However if the keystone Puppet module is enabled, it can perform this extra configuration step.

  • In on of the Puppet YAML files, add the following:

    keystone::using_domain_config: true

Set the following values in /etc/keystone/keystone.conf to enable federation.

auth:methods
A list of allowed authentication methods. By default the list is: ['external', 'password', 'token', 'oauth1']. You must enable SAML by using the mapped method. Additionally, the external method must be excluded. Set the value to the following: password,token,oauth1,mapped.
federation:trusted_dashboard
A list of trusted dashboard hosts. Before accepting a Single Sign-On request to return a token, the origin host must be a member of this list. You can use use this configuration option multiple times for different values. You must set this to use web-based SSO flows. For this deployment the value is: https://$FED_KEYSTONE_HOST/dashboard/auth/websso/ The host is $FED_KEYSTONE_HOST because Red Hat OpenStack Platform director co-locates both keystone and horizon on the same host. If horizon runs on a different host to keystone, you must adjust accordingly.
federation:sso_callback_template
The absolute path to an HTML file that is used as a Single Sign-On callback handler This page redirects the user from the Identity service back to a trusted dashboard host by form encoding a token in a POST request. The default value is sufficient for most deployments.
federation:remote_id_attribute

The value that is used to obtain the entity ID of the Identity provider. For mod_auth_mellon, use Mellon_IDP. Set this value in the mellon configuration file using the Mellon IDP directive.

  • Create the fed_deployment/puppet_override_keystone.yaml file with the following content:

    parameter_defaults:
      controllerExtraConfig:
        keystone::using_domain_config: true
        keystone::config::keystone_config:
          identity/domain_configurations_from_database:
            value: true
          auth/methods:
            value: external,password,token,oauth1,mapped
          federation/trusted_dashboard:
            value: https://$FED_KEYSTONE_HOST/dashboard/auth/websso/
          federation/sso_callback_template:
            value: /etc/keystone/sso_callback_template.html
          federation/remote_id_attribute:
            value: MELLON_IDP
  • Append the created environment file at the end of the overcloud_deploy.sh script.

    ...
    -e /home/stack/fed_deployment/puppet_override_keystone.yaml \
    --log-file overcloud_deployment_14.log &> overcloud_install.log
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation puppet-override-keystone

4.15. Deploying the Mellon configuration archive

  • Use Object Storage (swift) artifacts to install the mellon configuration files on each Controller node.

    $ source ~/stackrc
    $ upload-swift-artifacts -f fed_deployment/rhsso_config.tar.gz
Note

You can use the configure-federation script to perform the above step: `./configure-federation deploy-mellon-configuration `

4.16. Redeploying the overcloud

  • To apply the changes from the Puppet YAML configuration files and Object Storage artifacts, run the deploy command:

    ./overcloud_deploy.sh

Important: When you make additional changes to the Controller nodes by re-running Puppet, the overcloud_deploy.sh script might overwrite previous configurations. Do not apply the Puppet configuration after this procedure to avoid losing manual edits that you make to the configuration files on the overcloud Controller nodes.

4.17. Use proxy persistence for the Identity service (keystone) on each Controller

When mod_auth_mellon establishes a session, it cannot share its state information across multiple servers. Because the high number of redirections used by SAML involves state information, the same server must process all transactions. Therefore, you must configure HAProxy to direct each client’s requests to the same server each time.

There are two way that HAProxy can bind a client to the same server:

Affinity
Use affinity when information from a layer below the application layer is used to pin a client request to a single server.
Persistence
Use persistence when the application layer information binds a client to a single server sticky session. Persistence is much more accurate than affinity. Use the following procedure to implement persistence.

The HAProxy cookie directive names a cookie and its parameters for persistence. The HAProxy server directive has a cookie option that sets the value of the cookie to the name of the server. If an incoming request does not have a cookie identifying the back-end server, then HAProxy selects a server based on its configured balancing algorithm.

Procedure

  1. To enable persistence in the keystone_public block of the /var/lib/config-data/puppet-generated/haproxy/etc/haproxy/haproxy.cfg configuration file, add the following line:

    cookie SERVERID insert indirect nocache

    This setting states that SERVERID is the name of the persistence cookie.

  2. Edit each server line and add cookie <server-name> as an additional option:

    server controller-0 cookie controller-0
    server controller-1 cookie controller-1

4.18. Creating federated resources

Create the Identity service (keystone) targets, users, and groups for consumption by the identity provider (IdP).

Procedure

  1. Source the overcloudrc file on the undercloud as the stack user, and run the following commands:

    $ openstack domain create federated_domain
    $ openstack project create  --domain federated_domain federated_project
    $ openstack group create federated_users --domain federated_domain
    $ openstack role add --group federated_users --group-domain federated_domain --domain federated_domain _member_
    $ openstack role add --group federated_users --group-domain federated_domain --project federated_project _member_
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation create-federated-resources

4.19. Creating the Identity provider in Red Hat OpenStack Platform

The IdP must be registered in the Identity service (keystone), which creates a binding between the entityID in the SAML assertion and the name of the IdP in the Identity service.

Procedure

  1. Locate the entityID of the RH-SSO IdP, which is located in the IdP metadata. The IdP metadata is stored in the /var/lib/config-data/puppet-generated/keystone/etc/httpd/federation/v3_keycloak_$FED_RHSSO_REALM_idp_metadata.xml file. You can also find the IdP metadata in the fed_deployment/var/lib/config-data/puppet-generated/keystone/etc/httpd/federation/v3_keycloak_$FED_RHSSO_REALM_idp_metadata.xml file.
  2. Note the value of the entityID attribute, which is in the IdP metadata file within the <EntityDescriptor> element. Assign the $FED_IDP_ENTITY_ID variable this value.
  3. Name your IdP rhsso, which is assigned to the variable $FED_OPENSTACK_IDP_NAME:

    $ openstack identity provider create --remote-id $FED_IDP_ENTITY_ID $FED_OPENSTACK_IDP_NAME
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation openstack-create-idp

4.20. Create the Mapping File and Upload to Keystone

Keystone performs a mapping to match the IdP’s SAML assertion into a format that keystone can understand. The mapping is performed by keystone’s mapping engine and is based on a set of mapping rules that are bound to the IdP.

  1. These are the mapping rules used in this example (as described in the introduction):

    [
        {
            "local": [
                {
                    "user": {
                        "name": "{0}"
                    },
                    "group": {
                        "domain": {
                            "name": "federated_domain"
                        },
                        "name": "federated_users"
                    }
                }
            ],
            "remote": [
                {
                    "type": "MELLON_NAME_ID"
                },
                {
                    "type": "MELLON_groups",
                    "any_one_of": ["openstack-users"]
                }
            ]
        }
    ]

This mapping file contains only one rule. Rules are divided into two parts: local and remote. The mapping engine works by iterating over the list of rules until one matches, and then executing it. A rule is considered a match only if all the conditions in the remote part of the rule match. In this example the remote conditions specify:

  1. The assertion must contain a value called MELLON_NAME_ID.
  2. The assertion must contain a values called MELLON_groups and at least one of the groups in the group list must be openstack-users.

If the rule matches, then:

  1. The keystone user name will be assigned the value from MELLON_NAME_ID.
  2. The user will be assigned to the keystone group federated_users in the federated_domain domain.

In summary, if the IdP successfully authenticates the user, and the IdP asserts that user belongs to the group openstack-users, then keystone will allow that user to access OpenStack with the privileges bound to the federated_users group in keystone.

4.20.1. Create the mapping

  1. To create the mapping in keystone, create a file containing the mapping rules and then upload it into keystone, giving it a reference name. Create the mapping file in the fed_deployment directory (for example, in fed_deployment/mapping_${FED_OPENSTACK_IDP_NAME}_saml2.json), and assign the name $FED_OPENSTACK_MAPPING_NAME to the mapping rules. For example:

    $ openstack mapping create --rules fed_deployment/mapping_rhsso_saml2.json $FED_OPENSTACK_MAPPING_NAME
Note

You can use the configure-federation script to perform the above procedure as two steps:

$ ./configure-federation create-mapping
$ ./configure-federation openstack-create-mapping
  • create-mapping - creates the mapping file.
  • openstack-create-mapping - performs the upload of the file.

4.21. Create a Keystone Federation Protocol

  1. Keystone uses the Mapped protocol to bind an IdP to a mapping. To establish this binding:

    $ openstack federation protocol create \
    --identity-provider $FED_OPENSTACK_IDP_NAME \
    --mapping $FED_OPENSTACK_MAPPING_NAME \
    mapped"
Note

You can use the configure-federation script to perform the above step: $ ./configure-federation openstack-create-protocol

4.22. Fully-Qualify the Keystone Settings

  1. On each controller node, edit /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/10-keystone_wsgi_main.conf to confirm that the ServerName directive inside the VirtualHost block includes the HTTPS scheme, the public hostname, and the public port. You must also enable the UseCanonicalName directive. For example:

    <VirtualHost>
      ServerName https:$FED_KEYSTONE_HOST:$FED_KEYSTONE_HTTPS_PORT
      UseCanonicalName On
      ...
    </VirtualHost>
Note

Be sure to substitute the $FED_ variables with the values specific to your deployment.

4.23. Configure Horizon to Use Federation

  1. On each controller node, edit /var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settings and make sure the following configuration values are set:

    OPENSTACK_KEYSTONE_URL = "https://$FED_KEYSTONE_HOST:$FED_KEYSTONE_HTTPS_PORT/v3"
    OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
    WEBSSO_ENABLED = True
    WEBSSO_INITIAL_CHOICE = "mapped"
    WEBSSO_CHOICES = (
        ("mapped", _("RH-SSO")),
        ("credentials", _("Keystone Credentials")),
    )
Note

Be sure to substitute the $FED_ variables with the values specific to your deployment.

4.24. Configure Horizon to Use the X-Forwarded-Proto HTTP Header

  1. On each controller node, edit /var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settings and uncomment the line:

    #SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
Note

You must restart a container for configuration changes to take effect.