Alert.png The wiki is deprecated and due to be decommissioned by the end of September 2022.
The content is being migrated to other supports, new updates will be ignored and lost.
If needed you can get in touch with EGI SDIS team using operations @ egi.eu.

Difference between revisions of "AAI guide for OpenStack"

From EGIWiki
Jump to navigation Jump to search
(Replaced content with "{{TOC_right}} This documentation is now available in the [http://egi-federated-cloud-integration.readthedocs.io/en/ EGI Federated Cloud integration docs] section on [http:/...")
Line 1: Line 1:
{{TOC_right}}
{{TOC_right}}


= Overview  =
This documentation is now available in the [http://egi-federated-cloud-integration.readthedocs.io/en/ EGI Federated Cloud integration docs] section on [http://egi-federated-cloud-integration.readthedocs.io/en/latest/openstack.html#openid-connect-support OpenID Connect support for OpenStack].
 
This wiki page contains information about enabling federated access to OpenStack cloud providers through the [[AAI|EGI AAI CheckIn service]]. While the [[AAI_guide_for_SPs| AAI guide for Service Providers]] contain the general instructions that apply to any services registered with CheckIn, in this guide we detais the specifics for enabling support for OpenID Connect using CheckIn as '''OpenID Provider (OP)'''
 
The integration of new service providers into the EGI CheckIn is a two-step process:
* '''Step 1.'''  Test integration with the development instance of EGI CheckIn. This will allow you to check complete the complete functionality of the system without affecting  the production CheckIn service.
* '''Step 2.''' Once the integration is working correctly, register your provider with the production instance of EGI CheckIn to allow members of the EGI User Community to access your service.
 
= Registration into CheckIn development instance  =
 
Before your service can use the EGI CheckIn OIDC Provider for user login, you must set up a client at https://aai-dev.egi.eu/oidc/manage/#admin/clients in order to obtain OAuth 2.0 credentials and register one or more redirect URIs.
 
Make sure that you fill in the following options:
* Main tab:
** Set redirect URL to <code><nowiki>https://<your keystone endpoint>/v3/auth/OS-FEDERATION/websso/oidc/redirect</nowiki></code>. Recent versions of OpenStack deploy Keystone at <code>/identity/</code>, be sure to include that in the <code><your keystone endpoint></code> part of the URL if needed.
* Access tab:
** Enable '''authorization code''' in the grant type
** Enable '''Introspection Allow calls to the Introspection Endpoint?'''
 
Once done, you will get a client id and client secret. Save them for the following steps
 
= Keystone setup =
 
== Pre-requisites ==
 
# Keystone must run as a WSGI application behind an HTTP server (Apache is used in this documentation, but any server should be possible if it has OpenID connect/OAuth2.0 support). Keystone project has deprecated eventlet, so you should be already running Keystone in such way.
# It is highly recommended that you run Keystone with SSL
# You need to install [https://github.com/pingidentity/mod_auth_openidc mod_auth_openidc] for adding support for OpenID Connect to Apache.
 
== Apache Configuration ==
 
Include this configuration on the Apache config for the virtual host of your Keystone service, using the client id and secret obtained above:
<pre>
OIDCResponseType "code"
OIDCClaimPrefix "OIDC-"
OIDCClaimDelimiter ;
# Define the OpenID Connect scope(s) requested from the OP (e.g. "openid email profile").
# When not defined, the bare minimal scope "openid" is used.
# See https://wiki.egi.eu/wiki/AAI_guide_for_SPs#Claims for a list of supported scopes and related claims
OIDCScope "openid refeds_edu"
OIDCProviderMetadataURL https://aai-dev.egi.eu/oidc/.well-known/openid-configuration
OIDCClientID <client id>
OIDCClientSecret <client secret>
OIDCCryptoPassphrase <some crypto pass phrase>
OIDCRedirectURI https://<your keystone endpoint>/v3/auth/OS-FEDERATION/websso/oidc/redirect
 
# OAuth for CLI access
OIDCOAuthIntrospectionEndpoint  https://aai-dev.egi.eu/oidc/introspect
OIDCOAuthClientID <client id>
OIDCOAuthClientSecret <client secret>
 
<Location ~ "/v3/auth/OS-FEDERATION/websso/oidc">
        AuthType  openid-connect
        Require  valid-user
</Location>
 
<Location ~ "/v3/OS-FEDERATION/identity_providers/egi.eu/protocols/oidc/auth">
        Authtype oauth20
        Require  valid-user
</Location>
</pre>
 
Be sure to enable the mod_auth_oidc module in Apache, in Ubuntu:
<pre>
sudo a2enmod auth_openidc
</pre>
 
== Keystone Configuration ==
 
Configure your <code>keystone.conf</code> to include in the <code>[auth]</code> section <code>oidc</code> in the list of authentication methods and the <code>keystone.auth.plugins.mapped.Mapped</code> class for its implementation:
 
<pre>
[auth]
 
# This may change in your installation, add oidc to the list of the methods you support
methods = password, token, oidc
 
# OIDC is basically mapped auth method
oidc = keystone.auth.plugins.mapped.Mapped
</pre>
 
Add a <code>[oidc]</code> section as follows:
<pre>
[oidc]
# this is the attribute in the Keystone environment that will define the identity provider
remote_id_attribute = HTTP_OIDC_ISS
</pre>
 
Add your horizon host as trusted dashboard to the <code>[federation]</code> section:
<pre>
[federation]
trusted_dashboard = https://<your horizon>/dashboard/auth/websso/
</pre>
 
Finally copy the default template for managing the tokens in horizon to /etc/keystone/sso_callback_template.html. This template can be found in keystone git repo at https://github.com/openstack/keystone/blob/master/etc/sso_callback_template.html
<pre>
curl -L https://raw.githubusercontent.com/openstack/keystone/master/etc/sso_callback_template.html \
      > /etc/keystone/sso_callback_template.html
</pre>
 
Now restart your Apache (and Keystone if running in uwsgi) so you can configure the Keystone Federation support.
 
== Keystone Federation Support ==
 
First, create a new <code>egi.eu</code> identity provider with remote id <code><nowiki>https://aai-dev.egi.eu/oidc/</nowiki></code>:
 
<pre>
$ openstack identity provider create --remote-id https://aai-dev.egi.eu/oidc/ egi.eu
+-------------+----------------------------------+
| Field      | Value                            |
+-------------+----------------------------------+
| description | None                            |
| domain_id  | 1cac7817dafb4740a249cc9ca6b14ea5 |
| enabled    | True                            |
| id          | egi.eu                          |
| remote_ids  | https://aai-dev.egi.eu/oidc/    |
+-------------+----------------------------------+
</pre>
 
Create a group for users coming from EGI CheckIn, you should have one group per VO you want to support.
<pre>
$ openstack group create ops
+-------------+----------------------------------+
| Field      | Value                            |
+-------------+----------------------------------+
| description |                                  |
| domain_id  | default                          |
| id          | 89cf5b6708354094942d9d16f0f29f8f |
| name        | ops                              |
+-------------+----------------------------------+
</pre>
 
Add that group to the desired local project:
<pre>
$ openstack role add member --group ops --project ops
</pre>
 
Define a mapping of users from EGI CheckIn to the group just created and restrict with the <code>OIDC-edu_person_entitlements</code> the VOs you want to support for that group. Substitute the group id and the allowed entitlements for the adequate values for your deployment:
<pre>
$ cat mapping.egi.json
[
    {
        "local": [
            {
                "user": {
"name": "{0}"
},
                "group": {
                    "id": "89cf5b6708354094942d9d16f0f29f8f"
                }
            }
        ],
        "remote": [
            {
                "type": "HTTP_OIDC_SUB"
            },
            {
                "type": "HTTP_OIDC_ISS",
                "any_one_of": [
                    "https://aai-dev.egi.eu/oidc/"
                ]
            },
            {
                "type": "OIDC-edu_person_entitlements",
                "regex": true,
                "any_one_of": [
                    "^urn:mace:egi.eu:.*:vm_operator@ops$"
                ]
            }
        ]
    }
]
</pre>
 
More recent versions of Keystone allow for more elaborated mapping, but this configuration should work for Mitaka and onwards
 
Create the mapping in Keystone:
<pre>
$ openstack mapping create --rules mapping.egi.json egi-mapping
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| Field | Value                                                                                                                            |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| id    | egi-mapping                                                                                                                      |
| rules | [{u'remote': [{u'type': u'HTTP_OIDC_SUB'}, {u'type': u'HTTP_OIDC_ISS', u'any_one_of': [u'https://aai-dev.egi.eu/oidc/']},        |
|      | {u'regex': True, u'type': u'OIDC-edu_person_entitlements', u'any_one_of': [u'^urn:mace:egi.eu:.*:ops:vm_operator@egi.eu$']}],      |
|      | u'local': [{u'group': {u'id': u'89cf5b6708354094942d9d16f0f29f8f'}, u'user': {u'name': u'{0}'}}]}]                              |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
</pre>
 
Finally, create the federated protocol with the identity provider and mapping created before:
<pre>
$ openstack federation protocol create --identity-provider egi.eu --mapping egi-mapping oidc
+-------------------+-------------+
| Field            | Value      |
+-------------------+-------------+
| id                | oidc        |
| identity_provider | egi.eu      |
| mapping          | egi-mapping |
+-------------------+-------------+
</pre>
 
Keystone is now ready to accept EGI CheckIn credentials.
 
= Horizon Configuration =
 
Edit your local_settings.py to include the following values:
<pre>
# Enables keystone web single-sign-on if set to True.
WEBSSO_ENABLED = True
 
# Allow users to choose between local Keystone credentials or login
# with EGI CheckIn
WEBSSO_CHOICES = (
    ("credentials", _("Keystone Credentials")),
    ("oidc", _("EGI CheckIn")),
)
</pre>
 
Once horizon is restarted you will be able to choose "EGI CheckIn" for login.
 
= CLI Access =
 
[https://docs.openstack.org/developer/python-openstackclient/ OpenStackClient] has built-in support for using OpenID Connect Access Tokens to authenticate. You first need to get a valid token from EGI CheckIn and then use it in a command like:
 
<pre>
$ openstack --os-auth-url https://<your keystone endpoint>/v3 \
            --os-auth-type v3oidcaccesstoken --os-protocol oidc \
            --os-identity-provider egi.eu \
            --os-access-token <your access token> \
            token issue
+---------+---------------------------------------------------------------------------------------+
| Field  | Value                                                                                |
+---------+---------------------------------------------------------------------------------------+
| expires | 2017-05-23T11:24:31+0000                                                              |
| id      | gAAAAABZJA3fbKX....nEMAPi-IsFOCkU9QWGTISYElzYJsI3z0SJGs7QsTJv4aJQq0JDJUBz6uE85SqXDj3 |
| user_id | 020864ea9415413f9d706f6b473dbeba                                                      |
+---------+---------------------------------------------------------------------------------------+
</pre>
 
= Additional VOs =
 
Configuration can include as many mappings as needed in the json file. Users will be members of all the groups matching the remote part of the mapping. For example this ile has 2 mappings, one for members of <code>ops</code> and another for members of <code>fedcloud.egi.eu</code>:
 
<pre>
[
    {
        "local": [
            {
                "user": {
            "name": "{0}"
        },
                "group": {
                    "id": "66df3a7a0c6248cba8b729de7b042639"
                }
            }
        ],
        "remote": [
            {
                "type": "HTTP_OIDC_SUB"
            },
            {
                "type": "HTTP_OIDC_ISS",
                "any_one_of": [
                    "https://aai-dev.egi.eu/oidc/"
                ]
            },
            {
                "type": "OIDC-edu_person_entitlements",
                "regex": true,
                "any_one_of": [
                    "^urn:mace:egi.eu:.*:vm_operator@ops$"
 
                ]
            }
        ]
    },
    {
        "local": [
            {
                "user": {
            "name": "{0}"
        },
                "group": {
                    "id": "e1c04284718f4e19bb0516e5534a24e8"
                }
            }
        ],
        "remote": [
            {
                "type": "HTTP_OIDC_SUB"
            },
            {
                "type": "HTTP_OIDC_ISS",
                "any_one_of": [
                    "https://aai-dev.egi.eu/oidc/"
                ]
            },
            {
                "type": "OIDC-edu_person_entitlements",
                "regex": true,
                "any_one_of": [
                    "^urn:mace:egi.eu:.*:vm_operator@fedcloud.egi.eu$"
                ]
            }
        ]
    }
]
</pre>
 
= Moving to EGI CheckIn production instance =
 
 
'''TBC'''
 
Register your Service Provider with the production instance of EGI CheckIn to allow members of the EGI User Community to access your service. This requires that your service meets all the [[AAI_guide_for_SPs#Services eligible for integration|eligibility criteria]] and that integration has been thoroughly tested during Step 1.
 
 
= Technical details =
 
OpenID Connect support on Keystone uses the [https://developer.openstack.org/api-ref/identity/v3-ext/index.html#os-federation-api OS-FEDERATION extension of v3 API]. The OS-FEDERATION has a set of API calls that allow getting an unscoped token and Keystone assume the URLs for these calls to be protected by some authentication mechanism (SAML, OpenID Connect, ...) that will make sure the user is valid. Once the user is granted by the underlying authentication, Keystone will perform the authorisation based on the configured mapping. [https://developer.openstack.org/api-ref/identity/v3-ext/index.html#mappings Mappings] restrict the allowed users and maps them to local groups or specific local accounts. If the mapping is successful, an unscoped token will be returned. This is a regular unscoped token that can be scoped to any of the allowed projects as with any other authentication mechanism.
 
In our configuration we are using two different calls for getting a token:
* /v3/auth/OS-FEDERATION/websso/<code>{protocol_id}</code>?origin=https%3A//horizon.example.com (/v3/auth/OS-FEDERATION/identity_providers/<code>{idp_id}</code>/protocol/<code>{protocol_id}</code>/websso?origin=https%3A//horizon.example.com</code> would be equivalent). This is used by Horizon and the URL is protected by mod_auth_oidc using the [http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth Authorization Code Flow], so requires interaction with the user. Keystone is the client in the flow (not horizon!) and gets all the claims included in the id token from mod_auth_oidc. The claims are used as input for the mapping. Once the flow is completed, Keystone sends back the OpenStack Token to Horizon in a [https://github.com/openstack/keystone/blob/master/etc/sso_callback_template.html simple html file]
 
* /v3/OS-FEDERATION/identity_providers/<code>{idp_id}</code>/protocols/<code>{protocol_id}</code>/auth. This is used by the CLI and is protected with mod_auth_oidc but using plain OAuth 2.0. mod_auth_oidc is configured to use the introspection endpoint so with the OAuth 2.0 access token sent by the user is able to get any additional claims configured in EGI CheckIn. The claims returned by the introspection code may change from one provider to another, hence this method may require additional tuning when configuring new providers. Claims returned by the introspection endpoint are used as input for the mapping. Keystone sends back the OpenStack token to the client.
 
For EGI Federation, <code>{idp_id}</code> should be <code>egi.eu</code> and <code>{protocol_id}</code> should be <code>oidc</code> as shown in the documentation above.

Revision as of 12:16, 21 June 2018


This documentation is now available in the EGI Federated Cloud integration docs section on OpenID Connect support for OpenStack.