Configure single sign-on with federated identity

Configure federated authentication so that users can log in to the Dashboard with centralized credentials.

Red Hat supports only Red Hat’s SSO technology as the federated identity provider for RHOSO. If you use another vendor, contact Red Hat Support for a support exception.

Enable SSO login for OpenStack Dashboard

Deploy Red Hat OpenStack Services on OpenShift (RHOSO) with Red Hat’s single sign-on (SSO) technology to enable users to log in to the OpenStack Dashboard (horizon) with centralized federated credentials.

Before you begin

  • You have installed RHOSO.
  • You have a SSO federated solution in your environment.

About this task

Note
By default, users who log out of the OpenStack Dashboard are not logged out of SSO.

You must modify the Identity service (keystone) configuration to integrate your federated SSO authentication solution. For more information, see Connect the Identity service to SSO to enable federated user authentication.

Important
When a federated user uses an application credential for authentication, this application credential remains valid for its configured lifetime even when its associated federated user account is disabled.

Procedure

  1. Retrieve the Identity service (keystone) endpoint:
    $ oc get keystoneapis.keystone.openstack.org -o json | jq '.items[0].status.apiEndpoints.public'
  2. Provide your SSO administrator with the following redirect URIs and the web origin.
    https://<keystoneURL>/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso/
    https://<keystoneURL>/v3/auth/OS-FEDERATION/websso/openid
    
    webOrigins: https://<keystoneURL>

    where:

    <keystoneURL>
    Specifies the URL retrieved in step 1. This URL must end in a trailing /.
    <idp_name>
    Specifies a value of your choosing, for example, kcipaIdP.

    In response, your SSO administrator provides you with a ClientID and a ClientSecret.

    Note
    The chosen <idp_name> value must match all referenced <idp_name> values in this procedure.
  3. Retrieve the Memcached hostname:
    1. For an IPv4 deployment run the following command:
      $ oc get memcacheds.memcached.openstack.org -n openstack -o json | jq -r '.items[0].status.serverList[0] | split(":")[0]'
    2. For an IPv6 deployment, run the following command:
      $ oc get memcacheds.memcached.openstack.org -n openstack -o json | jq -r '.items[0].status.serverListWithInet[0]'
  4. Create a keystone-httpd-override.yaml CR file and add the following configuration:
    apiVersion: v1
    kind: Secret
    metadata:
      name: keystone-httpd-override
      namespace: openstack
    type: Opaque
    stringData:
      federation.conf: |
        # Example OIDC directives for the *public* endpoint
        OIDCClaimPrefix "OIDC-"
        OIDCScope "openid email profile"
        OIDCClaimDelimiter ";"
        OIDCPassUserInfoAs "claims"
        OIDCPassClaimsAs "both"
        OIDCClientID "<my_client_id>"
        OIDCClientSecret "<my_client_secret>"
        OIDCCryptoPassphrase "<crypto_pass>"
        OIDCProviderMetadataURL <metadata_url>
        OIDCResponseType "<response-type>"
        OIDCOAuthClientID "my_oauth_client_id"
        OIDCOAuthClientSecret "12345678"
        OIDCOAuthIntrospectionEndpoint "<https://my_oauth_introspection_endpoint>"
        OIDCRedirectURI "{{ .KeystoneEndpointPublic }}/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso/"
    
        <LocationMatch "/v3/auth/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/websso">
            AuthType "openid-connect"
            Require valid-user
        </LocationMatch>
    
        <Location ~ "/v3/OS-FEDERATION/identity_providers/<idp_name>/protocols/openid/auth">
            AuthType oauth20
            Require valid-user
        </Location>
    
        <LocationMatch "/v3/auth/OS-FEDERATION/websso/openid">
            AuthType "openid-connect"
            Require valid-user
        </LocationMatch>

    where:

    <my_client_id>
    Specifies your client ID to use for the OpenID Connect provider handshake. You must get this from your SSO administrator.
    <my_client_secret>
    Specifies the client secret to use for the OpenID Connect provider handshake. You must get this from your SSO administrator after providing your redirect URLs.
    <crypto_pass>
    Specifies a secure passphrase to use when encrypting data for the OpenID Connect handshake. This is a user-defined value.
    <metadata_url>
    Specifies the URL that points to your OpenID Connect provider metadata. Use the format: "https://<FQDN>/realms/<realm>/.well-known/openid-configuration. The SSO administrator will provide the requisite <FQDN> and organization-specific <realm> name for your OpenID provider.
    <response-type>
    Specifies the response type required by your federation client.
    • If your federation client has Implicit Flow enabled, specify: id_token.
    • If your federation client has Authorization Code Flow enabled, specify: code.
    https://my_oauth_introspection_endpoint
    Specifies the value provided by the SSO administrator.
    <idp_name>
    Specifies your chosen string that creates unique redirect URL, for example, kcipaIdP. This value must be replaced for the keystoneFederationIdentityProviderName parameter and the LocationMatch and Location directive arguments.
    Important
    The full value for the OIDCRedirectURI parameter must end in a trailing /.
  5. Create the secret:
    $ oc create -f keystone-httpd-override.yaml
  6. Get the URL for the OpenStack Dashboard:
    $ oc get horizons.horizon.openstack.org -o json | jq -r '.items[0].status.endpoint'
    1. Edit the keystone section of the OpenStackControlPlane CR file and add the secret:

      Remove external from the methods = comma-delimited list and add the httpdCustomization.customConfigSecret parameter and set this value to the key created in the keystone-httpd-override.yaml CR file.

      keystone:
        template:
          customServiceConfig: |
            [federation]
            trusted_dashboard=<horizon_endpoint>/dashboard/auth/websso/
            [openid]
            remote_id_attribute=HTTP_OIDC_ISS
            [auth]
            methods = password,token,oauth1,mapped,application_credential,openid
          httpdCustomization:
            customConfigSecret: keystone-httpd-override

      where:

      <horizon_endpoint>
      Specifies the value you retrieved in step 6.
  7. Edit the horizon section of the OpenStackControlPlane CR file to configure the OpenStack Dashboard (horizon):
    horizon:
      template:
        customServiceConfig: |
          # Point Horizon to the Keystone public endpoint
          OPENSTACK_KEYSTONE_URL = "<keystone_endpoint>/v3"
    
          # Enable WebSSO in Horizon
          WEBSSO_ENABLED = True
    
          # Provide login options in Horizon's dropdown menu
          WEBSSO_CHOICES = (
            ("credentials", _("Keystone Credentials")),
            ("OIDC", _("OpenID Connect")),
          )
    
          # Map Horizon's "OIDC" choice to the Keystone IDP and protocol
          WEBSSO_IDP_MAPPING = {
            "OIDC": ("<idp_name>", "openid"),
          }

    where:

    <keystone_endpoint>
    Specifies the value you retrieved in the first step.
    <idp_name>
    Specifies your chosen string that creates a unique redirect URL, for example, kcipaIdP.
  8. Update the control plane:
    $ oc apply -f openstack_control_plane.yaml

What to do next

Connect the Identity service to SSO to enable federated user authentication

After you deploy Red Hat OpenStack Services on OpenShift (RHOSO) with Red Hat’s single sign-on (SSO) technology, integrate SSO with the Identity service (keystone) to enable federated user authentication and role-based access.

Procedure

  1. Create a federated domain:
    $ openstack domain create <federated_domain_name>

    where:

    <federated_domain_name>

    Specifies the name of the domain you are managing with your identity provider, for example, my_domain.

    For example:

    +-------------+----------------------------------+
    | Field       | Value                            |
    +-------------+----------------------------------+
    | description |                                  |
    | enabled     | True                             |
    | id          | b493634c9dbf4546a2d1988af181d7c9 |
    | name        | my_domain                        |
    | options     | {}                               |
    | tags        | []                               |
    +-------------+----------------------------------+
  2. Set up the federation identity provider:
    $ openstack identity provider create \
        --remote-id https://<sso_fqdn>:9443/realms/<realm> \
        --domain <federated_domain_name> \
        [--authorization-ttl <ttl-minutes> \]
        <idp_name>
     

    Optional: If your federated users obtain their project roles through mapped groups and you must create OpenStack Orchestration service (heat) stacks or use other trust-based workflows, then specify the --authorization-ttl parameter.

    where:

    <ttl_minutes>

    Specifies the time in minutes that the Identity service retains the group memberships of a federated user. Set the shortest TTL that covers the interval between the user logging in and the trust-based operation completing.

    Note
    Each federated login retains the memberships for another full TTL window.
    <sso_fqdn>
    Specifies the fully qualified domain name for your SSO identity provider.
    <realm>
    Specifies the SSO realm. The default realm is master.
    <federated_domain_name>
    Specifies the name of the federated domain that you created in step 1, for example, my_domain.
    <idp_name>

    Specifies the string that you chose when deploying SSO to create the unique redirect URL, for example, kcipaIdP.

    In this example the optional --authorization-ttl parameter was not specified:

    +-------------------+-----------------------------------------------------+
    | Field             | Value                                               |
    +-------------------+-----------------------------------------------------+
    | authorization_ttl | None                                                |
    | description       | None                                                |
    | domain_id         | b493634c9dbf4546a2d1988af181d7c9                    |
    | enabled           | True                                                |
    | id                | kcipaIdP                                            |
    | remote_ids        | https://sso.fqdn.local:9443/realms/master           |
    +-------------------+-----------------------------------------------------+
  3. Create a mapping file that is unique to the identity needs of your cloud:
    $ cat > mapping.json << EOF
    [
    	{
        	"local": [
            	{
                	"user": {
                 	"name": "{0}"
                	},
                	"group": {
                    	"domain": {
                     	"name": "<federated_domain_name>"
                    	},
                    	"name": "<federated_group_name>"
                	}
            	}
        	],
        	"remote": [
            	{
                	"type": "OIDC-preferred_username"
            	}
        	]
    	}
    ]
    EOF

    where:

    <federated_domain_name>
    Specifies the domain you created in step 1, for example, my_domain.
    <federated_group_name>
    Specifies the name of the federated group that you create in a later step, for example, my_fed_group.
  4. Use the mapping file to create the federation mapping rules for RHOSO:
    $ openstack mapping create --rules <mapping_file> <mapping_rules>

    where:

    <mapping_file>
    Specifies the name of the mapping file that you created in the previous step, for example, mapping.json.
    <mapping_rules>
    Specifies the name of the mapping rules created from this file, for example, IPAmap.
  5. Create a federated group:
    $ openstack group create --domain <federated_domain_name> <federated_group_name>

    where:

    <federated_domain_name>
    Specifies the name of the domain that you created in step 1, for example, my_domain.
    <federated_group_name>
    Specifies the name of the federated group that have specified in the mapping file, for example, my_fed_group.
  6. Create an Identity service (keystone) project:
    $ openstack project create --domain <federated_domain_name> <federated_project_name>

    where:

    <federated_project_name>
    Specifies the name of the Identity service project.
  7. Add the Identity service federation group to a role:
    $ openstack role add --group <federated_group_name> --group-domain <federated_domain_name> --project <federated_project_name> --project-domain <federated_domain_name> member
  8. Create the OpenID federation protocol:
    $ openstack federation protocol create openid --mapping <mapping_rules> --identity-provider <idp_name>

    where:

    <mapping_rules>
    Specifies the name of the mapping rules you created from your mapping file, for example, IPAmap.
    <idp_name>
    Specifies your chosen string that creates the unique redirect URL, for example, kcipaIdP.

What to do next

Authenticate federated users in the openstack CLI

You can authenticate federated users in the openstack CLI after you have enabled logging into the OpenStack Dashboard (horizon) by using Red Hat's single sign-on (SSO) technology and you have connected the Identity service to SSO to enable federated user authentication.

You can use the following command to access the remote shell for the OpenStackClient pod from your workstation to run the required openstack CLI authentication commands: oc rsh openstackclient.

You can use the following methods of authenticating federated users in the openstack CLI:

Note
If you require a federated project-scoped token then you must provide the following two additional parameters to these openstack CLI authentication commands:
--os-project-name "<federated_project_name>" \ 
--os-project-domain-name "<federated_domain_name>" \

where

<federated_project_name>
Specifies the name of the federated project.
<federated_domain_name>
Specifies the name of the federated domain.
  • Authenticate using the Resource Owner Password Credentials Flow: Your federation client must support the Resource Owner Password Credentials Flow and use the settings that you specified when deploying and integrating SSO with RHOSO.

    Run the following openstack CLI command:

    $ openstack --os-auth-url "https://<keystone_endpoint>/v3" \
     --os-identity-api-version 3 \
     --os-auth-type v3oidcpassword \
     --os-identity-provider "<idp_name>" \
     --os-protocol "openid" \
     --os-client-id "<client_id>" \
     --os-client-secret "<client_secret>" \
     --os-discovery-endpoint "https://<sso_fqdn>/realms/<realm>/.well-known/openid-configuration" \
     --os-openid-scope "openid email profile" \
     --os-access-token-type "access_token" \
     --os-username "<idp_username>" \
     --os-password "<idp_password>" \
     token issue

    where:

    <keystone_endpoint>
    Specifies the URL that you can retrieve by running the following command: oc get keystoneapis.keystone.openstack.org -o json | jq '.items[0].status.apiEndpoints.public'. This URL must end in a trailing `/`.
    <idp_name>
    Specifies a value of your choosing, for example, kcipaIdP.
    <client_id>
    Specifies the client ID provided by your SSO administrator.
    <client_secret>
    Specifies the client secret provided by your SSO administrator.
    <sso_fqdn>
    Specifies the fully qualified domain name for your SSO identity provider (IdP).
    <realm>
    Specifies the SSO realm name.
    <idp_username>
    Specifies your IdP username.
    <idp_password>
    Specifies your IdP password.
  • Authenticate using an access token from your SSO identity provider: This method is useful when the IdP does not allow the Resource Owner Password Credentials Flow, or when you want to use an existing SSO session without passing credentials to the OpenStack CLI. Important
    You must receive a valid access token from your SSO identity provider and if OS_CLOUD is set then depending upon your specific OS_CLOUD parameters you may need to unset this first to avoid conflicts with this authentication.

    Run the following openstack CLI command:

    $ openstack --os-auth-url "https://<keystone_endpoint>/v3" \
     --os-identity-api-version 3 \
     --os-auth-type v3oidcaccesstoken \
     --os-identity-provider "<idp_name>" \
     --os-protocol "openid" \
     --os-access-token "<access_token_from_idp>" \
     token issue

    where:

    <access_token_from_idp>
    Specifies the valid access token you have obtained from your SSO identity provider.
  • Authenticate using the Authorization Code Flow or browser redirect: Your federation client must support the standard OAuth 2.0 Authorization Code Flow, typically used in web applications. This method requires obtaining an authorization code through a browser-based redirect, then exchanging this authorization code for an access token.

    Your users must use the following authorization endpoint to obtain the authorization code, which is returned via the specified redirect URI:

    Note
    The redirect URI, in this example https://<keystone_endpoint>/v3/redirect_uri, must be registered with the IdP and must exactly match the value specified in the openstack command.
    https://<sso_fqdn>/auth/realms/<realm>/protocol/openid-connect/auth?client_id=<client_id>&redirect_uri=https://<keystone_endpoint>/v3/redirect_uri&response_type=code&scope=openid%20profile%20email&state=<random_string>

    where:

    <random_string>
    Specifies a unique, cryptographically random string generated by the client application for each authentication attempt.

    After the user successfully authenticates, the IdP redirects the authorization code as a query parameter to this redirect URI. You can then run the following openstack command to obtain an access token from this authorization code:

    $ openstack --os-auth-url "https://<keystone_endpoint>/v3" \
     --os-identity-api-version 3 \
     --os-auth-type v3oidcauthcode \
     --os-identity-provider "<idp_name>" \
     --os-protocol "openid" \
     --os-client-id "<client_id>" \
     --os-client-secret "<client_secret>" \
     --os-discovery-endpoint "https://<sso_fqdn>/realms/<realm>/.well-known/openid-configuration" \
     --os-openid-scope "openid email profile" \
     --os-access-token-type "access_token" \
     --os-redirect-uri "https://<keystone_endpoint>/v3/redirect_uri" \
     --os-code "<authorization_code>" \
     token issue

    where:

    <authorization_code>
    Specifies the authorization code that is returned to the specified redirect URI.
  • Authenticate using the Client Credentials Flow for service accounts: Your federation client must support the Client Credentials Flow that provides service-to-service authentication where no user context is required. In this case the federation client authenticates using its own credentials with its client ID and secret rather than with user credentials. Note
    The IdP must have Service Accounts enabled for the federation client to use this flow.

    Run the following openstack CLI command:

    $ openstack --os-auth-url "https://<keystone_endpoint>/v3" \
     --os-identity-api-version 3 \
     --os-auth-type v3oidcclientcredentials \
     --os-identity-provider "<idp_name>" \
     --os-protocol "openid" \
     --os-client-id "<client_id>" \
     --os-client-secret "<client_secret>" \
     --os-discovery-endpoint "https://<sso_fqdn>/realms/<realm>/.well-known/openid-configuration" \
    token issue