keystone/doc/source/admin/federated-identity.rst
Colleen Murphy cbdc84ac7f Partially clarify federation auth plugins
Federation protocols in keystone are very confusing due to the way they
have evolved since the original service provider implementation where
the auth plugin was defined in saml2.py. We renamed saml2.py to
mapped.py[1] and now we can effectively support any federation protocol
as long as there is some kind of Apache module that can understand it
and pass certain IdP and user attributes through to keystone. So we
started recommending not using the 'saml2' auth plugin and instead using
the 'mapped' plugin, eventually removing the the notice when we removed
the plugin[2]. Since the name of the federation protocol resource
created in keystone must match one of the [auth]/methods, we also
changed the documentation to start creating the 'mapped' protocol and
use 'mapped' in the Apache settings[3]. This was really the wrong
course. 'mapped' is not a protocol. Using only 'mapped' prevents us from
defining multiple remote_id_attributes for different protocols.

This patch changes references to the 'mapped' protocol and 'mapped'
plugin back to 'saml2' (we never changed the openid ones). While the
saml2 plugin does not itself exist, it is defined as an entrypoint to
the mapped plugin, so it all works out. This doesn't solve the problem
for if we want to define different remote_id_attributes for different
SAML2.0 implementations, but there is a workaround for that[4]. Using
'saml2' as the protocol name is just much more intuitive than 'mapped'.

[1] https://git.openstack.org/cgit/openstack/keystone-specs/tree/specs/keystone/juno/generic-mapping-federation.rst
[2] https://review.openstack.org/#/c/397456/
[3] https://review.openstack.org/#/c/371210/
[4] https://bugs.launchpad.net/keystone/+bug/1724645/comments/1

Change-Id: I23fc3f1f651c12c4e3c1987dc71008e6e97b4ed8
Related-bug: #1724645
2017-10-24 11:52:33 +02:00

16 KiB

Federated Identity

You can use federation for the Identity service (keystone) in two ways:

  • Supporting keystone as a SP (Service Provider): consuming identity assertions issued by an external Identity Provider, such as SAML assertions or OpenID Connect claims.

  • Supporting keystone as an IdP (Identity Provider): fulfilling authentication requests on behalf of Service Providers.

    Note

    It is also possible to have one keystone act as an SP that consumes Identity from another keystone acting as an IdP.

There is currently support for two major federation protocols:

Keystone federation

To enable federation:

  1. Run keystone under Apache. See Configure the Apache HTTP server for more information.

    Note

    Other application servers, such as nginx, have support for federation extensions that may work but are not tested by the community.

  2. Configure Apache to use a federation capable module. We recommend Shibboleth, see the Shibboleth documentation<../advanced-topics/federation/shibboleth> for more information.

    Note

    Another option is mod_auth_melon, see the mod's github repo for more information.

  3. Configure federation in keystone.

Note

The external IdP is responsible for authenticating users and communicates the result of authentication to keystone using authentication assertions. Keystone maps these values to keystone user groups and assignments created in keystone.

Supporting keystone as a SP

To have keystone as an SP, you will need to configure keystone to accept assertions from external IdPs. Examples of external IdPs are:

  • ADFS (Active Directory Federation Services)
  • FreeIPA
  • Tivoli Access Manager
  • Keystone

Configuring federation in keystone

  1. Configure authentication drivers in keystone.conf by adding the authentication methods to the [auth] section in keystone.conf. Ensure the names are the same as to the protocol names added via Identity API v3.

    For example:

    [auth]
    methods = external,password,token,saml2,openid

    Note

    saml2 and openid are instances of the mapped plugin. These must match the name of the of the federation protocol created via the Identity API. The other names in the example are not related to federation.

  2. Create local keystone groups and assign roles.

    Important

    The keystone requires group-based role assignments to authorize federated users. The federation mapping engine maps federated users into local user groups, which are the actors in keystone's role assignments.

  3. Create an IdP object in keystone. The object must represent the IdP you will use to authenticate end users:

    PUT /OS-FEDERATION/identity_providers/{idp_id}

    More configuration information for IdPs can be found Register an Identity Provider.

  4. Add mapping rules:

    PUT /OS-FEDERATION/mappings/{mapping_id}

    More configuration information for mapping rules can be found Create a mapping.

    Note

    The only keystone API objects that support mapping are groups and users.

  5. Add a protocol object and specify the mapping ID you want to use with the combination of the IdP and protocol:

    PUT /OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}

    More configuration information for protocols can be found Add a protocol and attribute mapping to an identity provider.

Performing federated authentication

  1. Authenticate externally and generate an unscoped token in keystone:

    Note

    Unlike other authentication methods in keystone, the user does not issue an HTTP POST request with authentication data in the request body. To start federated authentication a user must access the dedicated URL with IdP's and protocol's identifiers stored within a protected URL. The URL has a format of: /v3/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}/auth.

    GET/POST /OS-FEDERATION/identity_providers/{identity_provider}/protocols/{protocol}/auth
  2. Determine accessible resources. By using the previously returned token, the user can issue requests to the list projects and domains that are accessible.

    • List projects a federated user can access: GET /OS-FEDERATION/projects
    • List domains a federated user can access: GET /OS-FEDERATION/domains
    GET /OS-FEDERATION/projects
  3. Get a scoped token. A federated user can request a scoped token using the unscoped token. A project or domain can be specified by either ID or name. An ID is sufficient to uniquely identify a project or domain.

    POST /auth/tokens

Supporting keystone as an IdP

When acting as an IdP, the primary role of keystone is to issue assertions about users owned by keystone. This is done using PySAML2.

Configuring federation in keystone

There are certain settings in keystone.conf that must be set up, prior to attempting to federate multiple keystone deployments.

  1. Within keystone.conf, assign values to the [saml] related fields, for example:

    [saml]
    certfile=/etc/keystone/ssl/certs/ca.pem
    keyfile=/etc/keystone/ssl/private/cakey.pem
    idp_entity_id=https://keystone.example.com/v3/OS-FEDERATION/saml2/idp
    idp_sso_endpoint=https://keystone.example.com/v3/OS-FEDERATION/saml2/sso
    idp_metadata_path=/etc/keystone/saml2_idp_metadata.xml
  2. We recommend the following Organization configuration options. Ensure these values contain not special characters that may cause problems as part of a URL:

    idp_organization_name=example_company
    idp_organization_display_name=Example Corp.
    idp_organization_url=example.com
  3. As with the Organization options, the Contact options are not necessary, but it is advisable to set these values:

    idp_contact_company=example_company
    idp_contact_name=John
    idp_contact_surname=Smith
    idp_contact_email=jsmith@example.com
    idp_contact_telephone=555-55-5555
    idp_contact_type=technical

Generate metadata

Metadata must be exchanged to create a trust between the IdP and the SP.

  1. Create metadata for your keystone IdP, run the keystone-manage command and pipe the output to a file. For example:

    $ keystone-manage saml_idp_metadata > /etc/keystone/saml2_idp_metadata.xml

    Note

    The file location must match the value of the idp_metadata_path configuration option assigned previously.

Create a SP

To setup keystone-as-a-Service-Provider properly, you will need to understand what protocols are supported by external IdPs. For example, keystone as an SP can allow identities to federate in from a ADFS IdP but it must be configured to understand the SAML v2.0 protocol. ADFS issues assertions using SAML v2.0. Some examples of federated protocols include:

  • SAML v2.0
  • OpenID Connect

The following instructions are an example of how you can configure keystone as an SP.

  1. Create a new SP with an ID of BETA.

  2. Create a sp_url of http://beta.example.com/Shibboleth.sso/SAML2/ECP.

  3. Create a auth_url of http://beta.example.com:5000/v3/OS-FEDERATION/identity_providers/beta/protocols/saml2/auth.

    Note

    Use the sp_url when creating a SAML assertion for BETA and signed by the current keystone IdP. Use the auth_url when retrieving the token for BETA once the SAML assertion is sent.

  4. Set the enabled field to true. It is set to false by default.

  5. Your output should reflect the following example:

    $ curl -s -X PUT \
    -H "X-Auth-Token: $OS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"service_provider": {"auth_url": "http://beta.example.com:5000/v3/OS-FEDERATION/identity_providers/beta/protocols/saml2/auth", "sp_url": "https://example.com:5000/Shibboleth.sso/SAML2/ECP", "enabled": true}}' \
    http://localhost:5000/v3/OS-FEDERATION/service_providers/BETA | python -mjson.tool

keystone-to-keystone

Keystone acting as an IdP is known as k2k (keystone-2-keystone) or k2k federation, where a keystone somewhere is acting as the SP and another keystone is acting as the IdP. All IdPs issue assertions about the identities it owns using a Protocol.

Mapping rules

Mapping adds a set of rules to map federation attributes to keystone users or groups. An IdP has exactly one mapping specified per protocol.

A mapping is a translation between assertions provided from an IdP and the permission and roles applied by an SP. Given an assertion from an IdP, an SP applies a mapping to translate attributes from the IdP to known roles. A mapping is typically owned by an SP.

Mapping objects can be used multiple times by different combinations of IdP and protocol.

A rule hierarchy is as follows:

{
     "rules": [
        {
            "local": [
               {
                    "<user> or <group>"
                }
            ],
            "remote": [
                {
                    "<condition>"
                }
            ]
        }
    ]
}
  • rules: top-level list of rules.
  • local: a rule containing information on what local attributes will be mapped.
  • remote: a rule containing information on what remote attributes will be mapped.
  • condition: contains information on conditions that allow a rule, can only be set in a remote rule.

For more information on mapping rules, see Mapping Rules.

Mapping creation

Mapping creation starts with the communication between the IdP and SP. The IdP usually provides a set of assertions that their users have in their assertion document. The SP will have to map those assertions to known groups and roles. For example:

Identity Provider 1:
  name: jsmith
  groups: hacker
  other: <assertion information>
The Service Provider may have 3 groups:
  Admin Group
  Developer Group
  User Group

The mapping created by the Service Provider might look like:
  Local:
  Group: Developer Group
Remote:
  Groups: hackers

The Developer Group may have a role assignment on the Developer Project. When jsmith authenticates against IdP 1, it presents that assertion to the SP.The SP maps the jsmith user to the Developer Group because the assertion says jsmith is a member of the hacker group.

Mapping examples

A bare bones mapping is sufficient if you would like all federated users to have the same authorization in the SP cloud. However, mapping is quite powerful and flexible. You can map different remote users into different user groups in keystone, limited only by the number of assertions your IdP makes about each user.

A mapping is composed of a list of rules, and each rule is further composed of a list of remote attributes and a list of local attributes. If a rule is matched, all of the local attributes are applied in the SP. For a rule to match, all of the remote attributes it defines must match.

In the base case, a federated user simply needs an assertion containing an email address to be identified in the SP cloud. To achieve that, only one rule is needed that requires the presence of one remote attribute:

{
    "rules": [
        {
            "remote": [
                {
                    "type": "Email"
                }
            ],
            "local": [
                {
                    "user": {
                        "name": "{0}"
                    }
                }
            ]
        }
    ]
}

However, that is not particularly useful as the federated user would receive no authorization. To rectify it, you can map all federated users with email addresses into a federated-users group in the default domain. All federated users will then be able to consume whatever role assignments that user group has already received in keystone:

Note

In this example, there is only one rule requiring one remote attribute.

{
    "rules": [
        {
            "remote": [
                {
                    "type": "Email"
                }
            ],
            "local": [
                {
                    "user": {
                        "name": "{0}"
                    }
                },
                {
                    "group": {
                        "domain": {
                            "id": "0cd5e9"
                        },
                        "name": "federated-users"
                    }
                }
            ]
        }
    ]
}

This example can be expanded by adding a second rule that conveys additional authorization to only a subset of federated users. Federated users with a title attribute that matches either Manager or Supervisor are granted the hypothetical observer role, which would allow them to perform any read-only API call in the cloud:

{
    "rules": [
        {
            "remote": [
                {
                    "type": "Email"
                },
            ],
            "local": [
                {
                    "user": {
                        "name": "{0}"
                    }
                },
                {
                    "group": {
                        "domain": {
                            "id": "default"
                        },
                        "name": "federated-users"
                    }
                }
            ]
        },
        {
            "remote": [
                {
                    "type": "Title",
                    "any_one_of": [".*Manager$", "Supervisor"],
                    "regex": "true"
                },
            ],
            "local": [
                {
                    "group": {
                        "domain": {
                            "id": "default"
                        },
                        "name": "observers"
                    }
                }
            ]
        }
    ]
}

Note

any_one_of and regex in the rule above map federated users into the observers group when a user's Title assertion matches any of the regular expressions specified in the any_one_of attribute.

Keystone also supports the following:

  • not_any_of, matches any assertion that does not include one of the specified values
  • blacklist, matches all assertions of the specified type except those included in the specified value
  • whitelist does not match any assertion except those listed in the specified value.