Authenticate in OpenStack API as a federated OIDC user¶
This section offers an example workflow of federated user authentication in OpenStack using an external identity provider and OpenID Connect (OIDC) protocol. The example illustrates a typical HTTP-based interchange of authentication data happening underneath between the client software, identity provider, and MOSK Identity service (OpenStack Keystone) when a cloud user logs in to a cloud using their corporate or social ID, depending on cloud configuration.
The instructions below can be handy for cloud operators who want to delve into how federated authentication operates in OpenStack and troubleshoot any related issues, as well as advanced cloud users keen on crafting their own basic automation tools for cloud interactions.
The instructions are provided for educational purposes. Mirantis encourages
the majority of cloud users to rely on existing mature tools and libraries,
such as openstacksdk
, keystoneauth
, python-openstackclient
,
or gophercloud
to communicate with OpenStack APIs in a programmable
manner.
Warning
Mirantis advises cloud users not to rely on federated authentication when managing their cloud resources using command line and cloud automation tool. Instead, consider using OpenStack built-in application credentials mechanism to ensure secure and reliable access to OpenStack APIs of your MOSK cloud. See Manage application credentials for details.
Verify cloud configuration with the cloud administrator¶
For cloud users to be able to log in to an OpenStack cloud using their federated identity, the cloud administrator should configure the cloud to integrate with an external OIDC-compatible identity provider, such as Mirantis Container Cloud IAM (Keycloak) with all the necessary resources pre-created in the OpenStack Keystone API.
To authenticate in OpenStack using your federated identity, an
OIDC-compatible identity provider protocol, and the v3oidcpassword
authentication method, get yourself acquainted with the authentication
parameters listed below. You can extract the required information from the
OpenStack RC file that is available for download from OpenStack Dashboard
(Horizon) once you log in to it with your federated identity, or the
clouds.yaml
file.
Parameter |
Description |
---|---|
|
The URL pointing to the OpenStack Keystone API. |
|
The URL pointing to the OIDC discovery document served by the identity provider,
usually ends with |
|
The identifier of the OIDC client to use. |
|
The secret for the OIDC client. Many OIDC providers require this parameter. Some providers, including Mirantis Container Cloud IAM (Keycloak), allow so-called public clients, where secrets are not used and can be any string. |
|
The scope requested when using OIDC authentication. This is at least
|
|
The name of the corresponding identity provider object as created in the Keystone API. |
|
The name of the protocol object as created in the Keystone API. |
|
Your user name. |
|
Your password in the identity provider, such as Mirantis Container Cloud IAM (Keycloak). |
Note
Additionally, to obtain a scoped token, you need information about
the target scope, such as, OS_PROJECT_DOMAIN_NAME
and
OS_PROJECT_NAME
.
Below is an example of RC file to set environment variables used in the further code examples for the project scope authentication:
export OS_AUTH_URL=https://keystone.it.just.works
export OS_DISCOVERY_ENDPOINT=https://keycloak.it.just.works/auth/realms/iam/.well-known/openid-configuration
export OS_CLIENT_ID=os
export OS_CLIENT_SECRET=someRandomClientSecretMightBeNull
export OS_USERNAME=writer
export OS_PASSWORD=password
export OS_IDENTITY_PROVIDER=keycloak
export OS_PROTOCOL=mapped
export OS_OPENID_SCOPE=openid
export OS_PROJECT_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
Obtain the OIDC access token¶
Obtain the token endpoint of the identity provider by extracting it from the OIDC discovery document:
token_endpoint=$(curl -sk -X GET $OS_DISCOVERY_ENDPOINT | jq -r .token_endpoint)
Obtain the access token from the identity provider by sending the POST request to the token endpoint that will return the access token in exchange to the login credentials:
access_token=$(curl -sk \ -X POST $token_endpoint \ -u $OS_CLIENT_ID:$OS_CLIENT_SECRET \ -d "username=${OS_USERNAME}&password=${OS_PASSWORD}&scope=${OS_OPENID_SCOPE}&grant_type=password" \ -H "Content-Type: application/x-www-form-urlencoded" \ | jq -r .access_token)
Note
As per OpenID Connect RFC, the request to the endpoint must use the Form serialization.
Now, you can exchange the OIDC access token for an unscoped token from OpenStack Keystone.
Obtain the unscoped token from OpenStack Keystone¶
The Keystone token is included in the response header. However, the response
body in the JSON format often contains additional data that may prove useful
for certain applications. The following example excludes the body by using
the -I
flag:
unscoped_token=$(curl -sik \
-I \
-X POST $OS_AUTH_URL/OS-FEDERATION/identity_providers/${OS_IDENTITY_PROVIDER}/protocols/${OS_PROTOCOL}/auth \
-H "Authorization: Bearer $access_token" \
| grep x-subject-token \
| awk '{print $2}' \
| tr -d '\r')
Note
The tr -d '\r'
line trims the carriage return characters from
grep and awk outputs so that the extracted data
can be properly inserted into the JSON authentication request later.
Now, you can generate a scoped token from OpenStack Keystone using the unscoped token and specifying the project scope.
Optional. Discover available scopes¶
In case you do not know beforehand the OpenStack authorization scope you want to log in to, use the unscoped token to get a list of the available scopes:
curl -sk $OS_AUTH_URL/auth/projects \
-H "X-Auth-Token: $unscoped_token" | jq .projects
Obtain the scoped token from OpenStack Keystone¶
Create a JSON-formatted authentication request using the following script. For example, for the project scope:
token_request=$(mktemp) cat > $token_request << EOJSON { "auth": { "identity": { "methods": [ "token" ], "token": { "id": "$unscoped_token" } }, "scope": { "project": { "domain": { "name": "$OS_PROJECT_DOMAIN_NAME" }, "name": "$OS_PROJECT_NAME" } } } } EOJSON
Send the authentication request to OpenStack Keystone to obtain a scoped token:
scoped_token=$(curl -sik \ -X POST $OS_AUTH_URL/auth/tokens \ -d "@$token_request" -H "Content-Type: application/json" \ | grep x-subject-token \ | awk '{print $2}' \ | tr -d '\r')
Remove the temporary file used to store the authentication request:
rm $token_request
Use the scoped token to access OpenStack services APIs¶
To verify that you can access the OpenStack services APIs, for example, obtain the list of available images:
curl -sk -H "X-Auth-Token: $scoped_token" \
-X GET https://glance.it.just.works/v2/images
Replace https://glance.it.just.works
with the endpoint of the
MOSK Image service (OpenStack Glance) that you can obtain
from the Access & Security dashboard of OpenStack Horizon.