aboutsummaryrefslogtreecommitdiffstats
path: root/keystone-moon/doc/source/federation
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/doc/source/federation')
-rw-r--r--keystone-moon/doc/source/federation/mellon.rst122
-rw-r--r--keystone-moon/doc/source/federation/openidc.rst94
-rw-r--r--keystone-moon/doc/source/federation/shibboleth.rst279
-rw-r--r--keystone-moon/doc/source/federation/websso.rst239
4 files changed, 734 insertions, 0 deletions
diff --git a/keystone-moon/doc/source/federation/mellon.rst b/keystone-moon/doc/source/federation/mellon.rst
new file mode 100644
index 00000000..9c4675b7
--- /dev/null
+++ b/keystone-moon/doc/source/federation/mellon.rst
@@ -0,0 +1,122 @@
+:orphan:
+
+..
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+
+==============================
+Setup Mellon (mod_auth_mellon)
+==============================
+
+Configure Apache HTTPD for mod_auth_mellon
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Follow the steps outlined at: `Running Keystone in HTTPD`_.
+
+.. _`Running Keystone in HTTPD`: ../apache-httpd.html
+
+You'll also need to install the Apache module `mod_auth_mellon
+<https://github.com/UNINETT/mod_auth_mellon>`_. For example:
+
+.. code-block:: bash
+
+ $ apt-get install libapache2-mod-auth-mellon
+
+Configure your Keystone virtual host and adjust the config to properly handle SAML2 workflow:
+
+Add *WSGIScriptAlias* directive to your vhost configuration::
+
+ WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ /var/www/keystone/main/$1
+
+Make sure the *wsgi-keystone.conf* contains a *<Location>* directive for the Mellon module and
+a *<Location>* directive for each identity provider::
+
+ <Location /v3>
+ MellonEnable "info"
+ MellonSPPrivateKeyFile /etc/httpd/mellon/http_keystone.fqdn.key
+ MellonSPCertFile /etc/httpd/mellon/http_keystone.fqdn.cert
+ MellonSPMetadataFile /etc/httpd/mellon/http_keystone.fqdn.xml
+ MellonIdPMetadataFile /etc/httpd/mellon/idp-metadata.xml
+ MellonEndpointPath /v3/OS-FEDERATION/identity_providers/idp_1/protocols/saml2/auth/mellon
+ MellonIdP "IDP"
+ </Location>
+
+ <Location /v3/OS-FEDERATION/identity_providers/idp_1/protocols/saml2/auth>
+ AuthType "Mellon"
+ MellonEnable "auth"
+ </Location>
+
+.. NOTE::
+ * See below for information about how to generate the values for the
+ `MellonSPMetadataFile`, etc. directives.
+ * ``saml2`` may be different in your deployment, but do not use a wildcard value.
+ Otherwise *every* federated protocol will be handled by Mellon.
+ * ``idp_1`` has to be replaced with the name associated with the IdP in Keystone.
+ * You are advised to carefully examine `mod_auth_mellon Apache
+ configuration documentation
+ <https://github.com/UNINETT/mod_auth_mellon>`_
+
+Enable the Keystone virtual host, for example:
+
+.. code-block:: bash
+
+ $ a2ensite wsgi-keystone.conf
+
+Enable the ``ssl`` and ``auth_mellon`` modules, for example:
+
+.. code-block:: bash
+
+ $ a2enmod ssl
+ $ a2enmod auth_mellon
+
+Restart the Apache instance that is serving Keystone, for example:
+
+.. code-block:: bash
+
+ $ service apache2 restart
+
+Configuring the Mellon SP Metadata
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Mellon provides a script called ``mellon_create_metadata.sh`` which generates the
+values for the config directives `MellonSPPrivateKeyFile`, `MellonSPCertFile`,
+and `MellonSPMetadataFile`. It is run like this:
+
+.. code-block:: bash
+
+ $ mellon_create_metadata.sh http://keystone.fqdn:5000 \
+ http://keystone.fqdn:5000/v3/OS-FEDERATION/identity_providers/idp_1/protocols/saml2/auth/mellon
+
+The first parameter is used as the entity ID, a unique identifier for this
+Keystone SP. You do not have to use the URL, but it is an easy way to uniquely
+identify each Keystone SP. The second parameter is the full URL for the
+endpoint path corresponding to the parameter `MellonEndpointPath`.
+
+Fetch your Service Provider's Metadata file. This corresponds to the value of
+the `MellonIdPMetadataFile` directive above. For example:
+
+.. code-block:: bash
+
+ $ wget --cacert /path/to/ca.crt -O /etc/httpd/mellon/idp-metadata.xml \
+ https://idp.fqdn/idp/saml2/metadata
+
+Upload your Service Provider's Metadata file to your Identity Provider. This
+is the file used as the value of the `MellonSPMetadataFile` in the config,
+generated by the `mellon_create_metadata.sh` script. The IdP may provide a
+webpage where you can upload the file, or you may be required to submit the
+file using `wget` or `curl`. Please check your IdP documentation for details.
+
+Once you are done, restart the Apache instance that is serving Keystone, for example:
+
+.. code-block:: bash
+
+ $ service apache2 restart
diff --git a/keystone-moon/doc/source/federation/openidc.rst b/keystone-moon/doc/source/federation/openidc.rst
new file mode 100644
index 00000000..ece82d3a
--- /dev/null
+++ b/keystone-moon/doc/source/federation/openidc.rst
@@ -0,0 +1,94 @@
+:orphan:
+
+..
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+
+====================
+Setup OpenID Connect
+====================
+
+Configuring mod_auth_openidc
+============================
+
+Federate Keystone (SP) and an external IdP using OpenID Connect (`mod_auth_openidc`_)
+
+.. _`mod_auth_openidc`: https://github.com/pingidentity/mod_auth_openidc
+
+To install `mod_auth_openidc` on Ubuntu, perform the following:
+
+.. code-block:: bash
+
+ sudo apt-get install libapache2-mod-auth-openidc
+
+This module is available for other distributions (Fedora/CentOS/Red Hat) from:
+https://github.com/pingidentity/mod_auth_openidc/releases
+
+In the keystone Apache site file, add the following as a top level option, to
+load the `mod_auth_openidc` module:
+
+.. code-block:: xml
+
+ LoadModule auth_openidc_module /usr/lib/apache2/modules/mod_auth_openidc.so
+
+Also within the same file, locate the virtual host entry and add the following
+entries for OpenID Connect:
+
+.. code-block:: xml
+
+ <VirtualHost *:5000>
+
+ ...
+
+ OIDCClaimPrefix "OIDC-"
+ OIDCResponseType "id_token"
+ OIDCScope "openid email profile"
+ OIDCProviderMetadataURL <url_of_provider_metadata>
+ OIDCClientID <openid_client_id>
+ OIDCClientSecret <openid_client_secret>
+ OIDCCryptoPassphrase openstack
+ OIDCRedirectURI http://localhost:5000/v3/OS-FEDERATION/identity_providers/<idp_id>/protocols/oidc/auth/redirect
+
+ <LocationMatch /v3/OS-FEDERATION/identity_providers/.*?/protocols/oidc/auth>
+ AuthType openid-connect
+ Require valid-user
+ LogLevel debug
+ </LocationMatch>
+ </VirtualHost>
+
+Note an example of an `OIDCProviderMetadataURL` instance is: https://accounts.google.com/.well-known/openid-configuration
+If not using `OIDCProviderMetadataURL`, then the following attributes
+must be specified: `OIDCProviderIssuer`, `OIDCProviderAuthorizationEndpoint`,
+`OIDCProviderTokenEndpoint`, `OIDCProviderTokenEndpointAuth`,
+`OIDCProviderUserInfoEndpoint`, and `OIDCProviderJwksUri`
+
+Note, if using a mod_wsgi version less than 4.3.0, then the `OIDCClaimPrefix`
+must be specified to have only alphanumerics or a dash ("-"). This is because
+mod_wsgi blocks headers that do not fit this criteria. See http://modwsgi.readthedocs.org/en/latest/release-notes/version-4.3.0.html#bugs-fixed
+for more details
+
+Once you are done, restart your Apache daemon:
+
+.. code-block:: bash
+
+ $ service apache2 restart
+
+Tips
+====
+
+1. When creating a mapping, note that the 'remote' attributes will be prefixed,
+ with `HTTP_`, so for instance, if you set OIDCClaimPrefix to `OIDC-`, then a
+ typical remote value to check for is: `HTTP_OIDC_ISS`.
+
+2. Don't forget to add oidc as an [auth] plugin in keystone.conf, see `Step 2`_
+
+.. _`Step 2`: federation/federation.html
diff --git a/keystone-moon/doc/source/federation/shibboleth.rst b/keystone-moon/doc/source/federation/shibboleth.rst
new file mode 100644
index 00000000..d67cfa1a
--- /dev/null
+++ b/keystone-moon/doc/source/federation/shibboleth.rst
@@ -0,0 +1,279 @@
+:orphan:
+
+..
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+
+================
+Setup Shibboleth
+================
+
+Configure Apache HTTPD for mod_shibboleth
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Follow the steps outlined at: `Running Keystone in HTTPD`_.
+
+.. _`Running Keystone in HTTPD`: ../apache-httpd.html
+
+You'll also need to install `Shibboleth <https://wiki.shibboleth.net/confluence/display/SHIB2/Home>`_, for
+example:
+
+.. code-block:: bash
+
+ $ apt-get install libapache2-mod-shib2
+
+Configure your Keystone virtual host and adjust the config to properly handle SAML2 workflow:
+
+Add *WSGIScriptAlias* directive to your vhost configuration::
+
+ WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ /var/www/keystone/main/$1
+
+Make sure the *wsgi-keystone.conf* contains a *<Location>* directive for the Shibboleth module and
+a *<Location>* directive for each identity provider::
+
+ <Location /Shibboleth.sso>
+ SetHandler shib
+ </Location>
+
+ <Location /v3/OS-FEDERATION/identity_providers/idp_1/protocols/saml2/auth>
+ ShibRequestSetting requireSession 1
+ ShibRequestSetting applicationId idp_1
+ AuthType shibboleth
+ ShibRequireAll On
+ ShibRequireSession On
+ ShibExportAssertion Off
+ Require valid-user
+ </Location>
+
+.. NOTE::
+ * ``saml2`` may be different in your deployment, but do not use a wildcard value.
+ Otherwise *every* federated protocol will be handled by Shibboleth.
+ * ``idp_1`` has to be replaced with the name associated with the idp in Keystone.
+ The same name is used inside the shibboleth2.xml configuration file but they could
+ be different.
+ * The ``ShibRequireSession`` and ``ShibRequireAll`` rules are invalid in
+ Apache 2.4+ and should be dropped in that specific setup.
+ * You are advised to carefully examine `Shibboleth Apache configuration
+ documentation
+ <https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig>`_
+
+Enable the Keystone virtual host, for example:
+
+.. code-block:: bash
+
+ $ a2ensite wsgi-keystone.conf
+
+Enable the ``ssl`` and ``shib2`` modules, for example:
+
+.. code-block:: bash
+
+ $ a2enmod ssl
+ $ a2enmod shib2
+
+Restart Apache, for example:
+
+.. code-block:: bash
+
+ $ service apache2 restart
+
+Configuring shibboleth2.xml
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you have your Keystone vhost (virtual host) ready, it's then time to
+configure Shibboleth and upload your Metadata to the Identity Provider.
+
+If new certificates are required, they can be easily created by executing:
+
+.. code-block:: bash
+
+ $ shib-keygen -y <number of years>
+
+The newly created file will be stored under ``/etc/shibboleth/sp-key.pem``
+
+You should fetch your Service Provider's Metadata file. Typically this can be
+achieved by simply fetching a Metadata file, for example:
+
+.. code-block:: bash
+
+ $ wget --no-check-certificate -O <name of the file> https://service.example.org/Shibboleth.sso/Metadata
+
+Upload your Service Provider's Metadata file to your Identity Provider.
+This step depends on your Identity Provider choice and is not covered here.
+
+Configure your Service Provider by editing ``/etc/shibboleth/shibboleth2.xml``
+file. You are advised to examine `Shibboleth Service Provider Configuration documentation <https://wiki.shibboleth.net/confluence/display/SHIB2/Configuration>`_
+
+An example of your ``/etc/shibboleth/shibboleth2.xml`` may look like
+(The example shown below is for reference only, not to be used in a production
+environment):
+
+.. code-block:: xml
+
+ <!--
+ File configuration courtesy of http://testshib.org
+
+ More information:
+ https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPConfiguration
+ -->
+
+ <SPConfig xmlns="urn:mace:shibboleth:2.0:native:sp:config"
+ xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" clockSkew="1800 ">
+
+ <!-- The entityID is the name TestShib made for your SP. -->
+ <ApplicationDefaults entityID="https://<yourhosthere>/shibboleth">
+
+ <!--
+ You should use secure cookies if at all possible.
+ See cookieProps in this Wiki article.
+ -->
+ <!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPSessions -->
+ <Sessions lifetime="28800" timeout="3600" checkAddress="false"
+ relayState="ss:mem" handlerSSL="false">
+
+ <!-- Triggers a login request directly to the TestShib IdP. -->
+ <!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPServiceSSO -->
+ <SSO entityID="https://<idp-url>/idp/shibboleth" ECP="true">
+ SAML2 SAML1
+ </SSO>
+
+ <!-- SAML and local-only logout. -->
+ <!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPServiceLogout -->
+ <Logout>SAML2 Local</Logout>
+
+ <!--
+ Handlers allow you to interact with the SP and gather
+ more information. Try them out!
+ Attribute value s received by the SP through SAML
+ will be visible at:
+ http://<yourhosthere>/Shibboleth.sso/Session
+ -->
+
+ <!--
+ Extension service that generates "approximate" metadata
+ based on SP configuration.
+ -->
+ <Handler type="MetadataGenerator" Location="/Metadata"
+ signing="false"/>
+
+ <!-- Status reporting service. -->
+ <Handler type="Status" Location="/Status"
+ acl="127.0.0.1"/>
+
+ <!-- Session diagnostic service. -->
+ <Handler type="Session" Location="/Session"
+ showAttributeValues="true"/>
+ <!-- JSON feed of discovery information. -->
+ <Handler type="DiscoveryFeed" Location="/DiscoFeed"/>
+ </Sessions>
+
+ <!--
+ Error pages to display to yourself if
+ something goes horribly wrong.
+ -->
+ <Errors supportContact ="<admin_email_address>"
+ logoLocation="/shibboleth-sp/logo.jpg"
+ styleSheet="/shibboleth-sp/main.css"/>
+
+ <!--
+ Loads and trusts a metadata file that describes only one IdP
+ and how to communicate with it.
+ -->
+ <MetadataProvider type="XML" uri="<idp-metadata-file>"
+ backingFilePath="<local idp metadata>"
+ reloadInterval="180000" />
+
+ <!-- Attribute and trust options you shouldn't need to change. -->
+ <AttributeExtractor type="XML" validate="true"
+ path="attribute-map.xml"/>
+ <AttributeResolver type="Query" subjectMatch="true"/>
+ <AttributeFilter type="XML" validate="true"
+ path="attribute-policy.xml"/>
+
+ <!--
+ Your SP generated these credentials.
+ They're used to talk to IdP's.
+ -->
+ <CredentialResolver type="File" key="sp-key.pem"
+ certificate="sp-cert.pem"/>
+
+ <ApplicationOverride id="idp_1" entityID="https://<yourhosthere>/shibboleth">
+ <Sessions lifetime="28800" timeout="3600" checkAddress="false"
+ relayState="ss:mem" handlerSSL="false">
+
+ <!-- Triggers a login request directly to the TestShib IdP. -->
+ <SSO entityID="https://<idp_1-url>/idp/shibboleth" ECP="true">
+ SAML2 SAML1
+ </SSO>
+
+ <Logout>SAML2 Local</Logout>
+ </Sessions>
+
+ <MetadataProvider type="XML" uri="<idp_1-metadata-file>"
+ backingFilePath="<local idp_1 metadata>"
+ reloadInterval="180000" />
+
+ </ApplicationOverride>
+
+ <ApplicationOverride id="idp_2" entityID="https://<yourhosthere>/shibboleth">
+ <Sessions lifetime="28800" timeout="3600" checkAddress="false"
+ relayState="ss:mem" handlerSSL="false">
+
+ <!-- Triggers a login request directly to the TestShib IdP. -->
+ <SSO entityID="https://<idp_2-url>/idp/shibboleth" ECP="true">
+ SAML2 SAML1
+ </SSO>
+
+ <Logout>SAML2 Local</Logout>
+ </Sessions>
+
+ <MetadataProvider type="XML" uri="<idp_2-metadata-file>"
+ backingFilePath="<local idp_2 metadata>"
+ reloadInterval="180000" />
+
+ </ApplicationOverride>
+
+ </ApplicationDefaults>
+
+ <!--
+ Security policies you shouldn't change unless you
+ know what you're doing.
+ -->
+ <SecurityPolicyProvider type="XML" validate="true"
+ path="security-policy.xml"/>
+
+ <!--
+ Low-level configuration about protocols and bindings
+ available for use.
+ -->
+ <ProtocolProvider type="XML" validate="true" reloadChanges="false"
+ path="protocols.xml"/>
+
+ </SPConfig>
+
+Keystone enforces `external authentication`_ when the ``REMOTE_USER``
+environment variable is present so make sure Shibboleth doesn't set the
+``REMOTE_USER`` environment variable. To do so, scan through the
+``/etc/shibboleth/shibboleth2.xml`` configuration file and remove the
+``REMOTE_USER`` directives.
+
+Examine your attributes map file ``/etc/shibboleth/attributes-map.xml`` and adjust
+your requirements if needed. For more information see
+`attributes documentation <https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPAddAttribute>`_
+
+Once you are done, restart your Shibboleth daemon:
+
+.. _`external authentication`: ../external-auth.html
+
+.. code-block:: bash
+
+ $ service shibd restart
+ $ service apache2 restart
diff --git a/keystone-moon/doc/source/federation/websso.rst b/keystone-moon/doc/source/federation/websso.rst
new file mode 100644
index 00000000..4ada0a4c
--- /dev/null
+++ b/keystone-moon/doc/source/federation/websso.rst
@@ -0,0 +1,239 @@
+:orphan:
+
+..
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+
+===============================
+Keystone Federation and Horizon
+===============================
+
+Keystone Changes
+================
+
+1. Update `trusted_dashboard` in keystone.conf.
+
+Specify URLs of trusted horizon servers. This value may be repeated
+multiple times. This setting ensures that keystone only sends token data back
+to trusted servers. This is performed as a precaution, specifically to
+prevent man-in-the-middle (MITM) attacks.
+
+.. code-block:: ini
+
+ [federation]
+ trusted_dashboard = http://acme.horizon.com/auth/websso/
+ trusted_dashboard = http://beta.horizon.com/auth/websso/
+
+2. Update httpd vhost file with websso information.
+
+The `/v3/auth/OS-FEDERATION/websso/<protocol>` route must be protected by the
+chosen httpd module. This is performed so the request that originates from
+horizon will use the same identity provider that is configured in keystone.
+
+If `mod_shib` is used, then use the following as an example:
+
+.. code-block:: xml
+
+ <VirtualHost *:5000>
+
+ ...
+
+ <Location ~ "/v3/auth/OS-FEDERATION/websso/saml2">
+ AuthType shibboleth
+ Require valid-user
+ ...
+ </Location>
+ </VirtualHost>
+
+If `mod_auth_openidc` is used, then use the following as an example:
+
+.. code-block:: xml
+
+ <VirtualHost *:5000>
+
+ OIDCRedirectURI http://localhost:5000/v3/auth/OS-FEDERATION/websso/redirect
+
+ ...
+
+ <Location ~ "/v3/auth/OS-FEDERATION/websso/oidc">
+ AuthType openid-connect
+ Require valid-user
+ ...
+ </Location>
+ </VirtualHost>
+
+If `mod_auth_kerb` is used, then use the following as an example:
+
+.. code-block:: xml
+
+ <VirtualHost *:5000>
+
+ ...
+
+ <Location ~ "/v3/auth/OS-FEDERATION/websso/kerberos">
+ AuthType Kerberos
+ AuthName "Acme Corporation"
+ KrbMethodNegotiate on
+ KrbMethodK5Passwd off
+ Krb5Keytab /etc/apache2/http.keytab
+ ...
+ </Location>
+ </VirtualHost>
+
+If `mod_auth_mellon` is used, then use the following as an example:
+
+.. code-block:: xml
+
+ <VirtualHost *:5000>
+
+ ...
+
+ <Location ~ "/v3/auth/OS-FEDERATION/websso/saml2">
+ AuthType Mellon
+ MellonEnable auth
+ Require valid-user
+ ...
+ </Location>
+ </VirtualHost>
+
+.. NOTE::
+ If you are also using SSO via the API, don't forget to make the Location
+ settings match your configuration used for the keystone identity provider
+ location:
+ `/v3/OS-FEDERATION/identity_providers/<idp>/protocols/<protocol>/auth`
+
+3. Update `remote_id_attribute` in keystone.conf.
+
+A remote id attribute indicates the header to retrieve from the WSGI
+environment. This header contains information about the identity
+of the identity provider. For `mod_shib` this would be
+``Shib-Identity-Provider``, for `mod_auth_openidc`, this could be
+``HTTP_OIDC_ISS``. For `mod_auth_mellon`, this could be ``MELLON_IDP``.
+
+It is recommended that this option be set on a per-protocol basis.
+
+.. code-block:: ini
+
+ [saml2]
+ remote_id_attribute = Shib-Identity-Provider
+ [oidc]
+ remote_id_attribute = HTTP_OIDC_ISS
+
+Alternatively, a generic option may be set at the `[federation]` level.
+
+.. code-block:: ini
+
+ [federation]
+ remote_id_attribute = HTTP_OIDC_ISS
+
+4. Set `remote_ids` for a keystone identity provider using the API or CLI.
+
+A keystone identity provider may have multiple `remote_ids` specified, this
+allows the same *keystone* identity provider resource to be used with multiple
+external identity providers. For example, an identity provider resource
+``university-idp``, may have the following `remote_ids`:
+``['university-x', 'university-y', 'university-z']``.
+This removes the need to configure N identity providers in keystone.
+
+This can be performed using the `OS-FEDERATION API`_:
+``PATCH /OS-FEDERATION/identity_providers/{idp_id}``
+
+Or by using the `OpenStackClient CLI`_:
+
+.. code-block:: bash
+
+ $ openstack identity provider set --remote-id <remote-id> <idp-id>
+
+.. NOTE::
+
+ Remote IDs are globally unique. Two identity providers cannot be
+ associated with the same remote ID. Once authenticated with the external
+ identity provider, keystone will determine which identity provider
+ and mapping to use based on the protocol and the value returned from the
+ `remote_id_attribute` key.
+
+ For example, if our identity provider is ``google``, the mapping used is
+ ``google_mapping`` and the protocol is ``oidc``. The identity provider's
+ remote IDs would be: [``accounts.google.com``].
+ The `remote_id_attribute` value may be set to ``HTTP_OIDC_ISS``, since
+ this value will always be ``accounts.google.com``.
+
+ The motivation for this approach is that there will always be some data
+ sent by the identity provider (in the assertion or claim) that uniquely
+ identifies the identity provider. This removes the requirement for horizon
+ to list all the identity providers that are trusted by keystone.
+
+.. _`OpenStackClient CLI`: http://docs.openstack.org/developer/python-openstackclient/command-objects/identity-provider.html#identity-provider-set
+.. _`OS-FEDERATION API`: http://specs.openstack.org/openstack/keystone-specs/api/v3/identity-api-v3-os-federation-ext.html#update-identity-provider
+
+Horizon Changes
+===============
+
+.. NOTE::
+
+ Django OpenStack Auth version 1.2.0 or higher is required for these steps.
+
+1. Set the Identity Service version to 3
+
+Ensure the `OPENSTACK_API_VERSIONS` option in horizon's local_settings.py has
+been updated to indicate that the `identity` version to use is `3`.
+
+.. code-block:: python
+
+ OPENSTACK_API_VERSIONS = {
+ "identity": 3,
+ }
+
+2. Authenticate against Identity Server v3.
+
+Ensure the `OPENSTACK_KEYSTONE_URL` option in horizon's local_settings.py has
+been updated to point to a v3 URL.
+
+.. code-block:: python
+
+ OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v3"
+
+3. Set the `WEBSSO_ENABLED` option.
+
+Ensure the `WEBSSO_ENABLED` option is set to True in horizon's local_settings.py file,
+this will provide users with an updated login screen for horizon.
+
+.. code-block:: python
+
+ WEBSSO_ENABLED = True
+
+4. (Optional) Create a list of authentication methods with the
+ `WEBSSO_CHOICES` option.
+
+Within horizon's settings.py file, a list of supported authentication methods
+can be specified. The entries in the list map to keystone federation protocols,
+with the exception of ``credentials`` which is reserved by horizon, and maps to
+the user name and password used by keystone's identity backend.
+
+.. code-block:: python
+
+ WEBSSO_CHOICES = (
+ ("credentials", _("Keystone Credentials")),
+ ("oidc", _("OpenID Connect")),
+ ("saml2", _("Security Assertion Markup Language"))
+ )
+
+5. (Optional) Specify an initial choice with the `WEBSSO_INITIAL_CHOICE`
+ option.
+
+The list set by the `WEBSSO_CHOICES` option will be generated in a drop-down
+menu in the login screen. The setting `WEBSSO_INITIAL_CHOICE` will
+automatically set that choice to be highlighted by default.
+
+.. code-block:: python
+
+ WEBSSO_INITIAL_CHOICE = "credentials"