Authentication onboarding and single sign-on
You can onboard workloads to Identity and Access Management (IAM) and configure single sign-on (SSO).
Onboarding is the configuration of workloads in IBM Cloud Private IAM. You can configure your workloads to obtain the authentication and authorization service requirements. As part of this process, the workloads must make themselves be known to IAM as a service by registering themselves with the authentication and the authorization services.
Customizing the authentication URL
Default configuration of OpenID Connect (OIDC) in IBM Cloud Private uses <cluster_lb_address>:8443 in the authentication endpoints, which are used to authenticate users to Kubernetes. However, in the issuerURL, an
internal or local host IP address is used. This configuration of the issuerURL is required in a VMware NSX-T environment. In environments where NSX-T is not configured, the internal or local host IP address that is used in the issuerURL might cause authentication errors. As a workaround, you can change the issuerURL endpoint to use a hostname or external IP address for Kubernetes authentication by completing the following configurations. You must use the same hostname
or external IP address, and port in all the following updates:
-
Add the external IP address and port in the
platform-auth-idpconfigmap.a. Edit the
platform-auth-idpconfigmap. You needkubectlto run the command. For more information about installingkubectl, see Installing the Kubernetes CLI (kubectl).kubectl -n kube-system edit cm platform-auth-idpb. Update the
OIDC_ISSUER_URLparameter value with the external IP address and port. The external IP address is thecluster_lb_addressthat you configure in theconfig.yamlfile during installation. For more information, see Cluster access settings.
If you enabled SSO in your cluster, you must first complete the following steps. After you complete the steps, you can re-enable SSO.- Back up the Security Assertion Markup Language (SAML) Identity Provider (IDP) metadata file.
- Disable SSO. You need the IBM Cloud Private CLI to run the command. For more information about installing the IBM Cloud Private CLI, see Installing the IBM Cloud Private CLI.
cloudctl iam saml-disable - Get the MongoDB pod name.
kubectl get pods | grep mongodb - Log in to the MongoDB container.
kubectl exec -it <MongoDB pod name> /bin/bash -n kube-system - Connect MondoDB client with MongoDB. Use the cluster administrator credentials.
mongo --host rs0/mongodb:27017 --username $ADMIN_USER --password $ADMIN_PASSWORD --authenticationDatabase admin --ssl --sslCAFile /data/configdb/tls.crt --sslPEMKeyFile /work-dir/mongo.pem -
Run the following commands to delete the
samlcollection entry in thesamlDBdatabase:-
Show all databases.
show databases -
Select the SAML database.
use samlDB -
Drop the SAML database that has the old configuration.
db.saml.drop() -
Exit the MongoDB shell.
exit -
Exit the MongoDB container.
exit
-
- Update the
OIDC_ISSUER_URLparameter value with the external IP address and port. - Enable SAML.
cloudctl iam saml-enable
c. Save the changes.
d. Get the
auth-idppod name.kubectl get pods | grep auth-idpe. Delete the
auth-idppod to restart it.kubectl delete pod <auth-idp-pod-name>f. Upload the SAML IDP metadata file that you backed up.
cloudctl iam saml-upload-metadata --file <metadata_file> -
Add the external IP address and port to the clusterrolebinding resource.
a. Get the clusterrolebinding resource name.
kubectl get clusterrolebinding | grep oidcFollowing is a sample output:
oidc-admin-binding 30db. Open the clusterrolebinding resource for editing.
kubectl -n kube-system edit clusterrolebinding oidc-admin-bindingc. Change the URL in the
subjects.nameparameter.subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: https://127.0.0.1:9443/oidc/endpoint/OP#adminChange
name: https://127.0.0.1:9443/oidc/endpoint/OP#admintoname: https://<cluster_lb_address>:8443/oidc/endpoint/OP#admin.d. Save the changes.
-
Add external IP address and port to the
master.jsonfile.a. Change directory to where the
master.jsonfile is located.cd /etc/cfc/pods/b. Open the
master.jsonfile for editing.vi master.jsonc. Locate the
apiserversection.d. Change the
"--oidc-issuer-url=https://127.0.0.1:9443/oidc/endpoint/OP"value to"--oidc-issuer-url=https://<cluster_lb_address>:8443/oidc/endpoint/OP"orhttps://<cluster_lb_address>:8443/idauth/oidc/endpoint/OP.e. Save and exit the
master.jsonfile.f. Restart the API server by moving out the
master.jsonfile from the/etc/cfc/pods/directory and then moving it back.
Onboarding a workload
The first step towards onboarding the workload to the authentication service of IBM Cloud Private is to register itself as a client of the authentication service based on Liberty. The registration is an important step because it is through this registration that the IBM Cloud Private authentication service knows the following information about the workload:
- An authorized client of IBM Cloud Private authentication service
- The authentication service knows where to redirect requests for this client after a successful authentication
Most of the content workloads have a login page of their own and would want to redirect to their service-specific dashboard page after a successful login.
The OpenID Connect (OIDC) Client Registration process requires access to a secret that is in the kube-system namespace. You can view the OAUTH2_CLIENT_REGISTRATION_SECRET from the Kubernetes secret platform-oidc-credentials.
The following methods are available for obtaining the OAuth secret and for automatic registration:
To manually onboard, that is obtain the secret and register the client, use the cloudctl or IAM.
Onboard by using cloudctl
For more information about the cloudctl IAM commands, see IBM Cloud Private CLI iam commands (iam).
-
Install
cloudctl. For more information, see Installing the IBM Cloud Private CLI. -
Construct the client registration payload.
Following is a sample content from theregistration.jsonfile:{ "token_endpoint_auth_method":"client_secret_basic", "client_id": "<WLP_CLIENT_ID>", "client_secret": "<WLP_CLIENT_SECRET>", "scope":"openid profile email", "grant_types":[ "authorization_code", "client_credentials", "password", "implicit", "refresh_token", "urn:ietf:params:oauth:grant-type:jwt-bearer" ], "response_types":[ "code", "token", "id_token token" ], "application_type":"web", "subject_type":"public", "post_logout_redirect_uris":[ "https://<ICP_PROXY_IP>:<PORT_WHERE_SERVICE_RUNS>" ], "preauthorized_scope":"openid profile email general", "introspect_tokens":true, "trusted_uri_prefixes":[ "https://<ICP_ENDPOINT>:<port>", "https://<ICP_PROXY_IP>" ], "redirect_uris":["https://<ICP_PROXY_IP>:<PORT_WHERE_SERVICE_RUNS>/auth/liberty/callback"] } -
Create the customized version of your
regisration.jsoncontent by editing the sample content.
Thewlp_client_idandwlp_client_secretcan be generated by the content service. Your output might resemble the following code:wlp_client_id: {{ randAlphaNum 32 | b64enc | quote }} wlp_client_secret: {{ randAlphaNum 32 | b64enc | quote }} -
Register a client with the IBM Cloud Private authentication service.
cloudctl iam oauth-client-register -f registration.json
Onboard by using IAM
-
Install
kubectl. For more information, see Installing the Kubernetes CLI (kubectl). -
Obtain the OAUTH secret:
OAUTH2_CLIENT_REGISTRATION_SECRET=$(kubectl -n kube-system get secret platform-oidc-credentials -o yaml | grep OAUTH2_CLIENT_REGISTRATION_SECRET | awk '{ print $2}' | base64 --decode) -
Construct the client registration payload.
Following is a sample content from theregistration.jsonfile:{ "token_endpoint_auth_method":"client_secret_basic", "client_id": "<WLP_CLIENT_ID>", "client_secret": "<WLP_CLIENT_SECRET>", "scope":"openid profile email", "grant_types":[ "authorization_code", "client_credentials", "password", "implicit", "refresh_token", "urn:ietf:params:oauth:grant-type:jwt-bearer" ], "response_types":[ "code", "token", "id_token token" ], "application_type":"web", "subject_type":"public", "post_logout_redirect_uris":[ "https://<ICP_PROXY_IP>:<PORT_WHERE_SERVICE_RUNS>" ], "preauthorized_scope":"openid profile email general", "introspect_tokens":true, "trusted_uri_prefixes":[ "https://<ICP_ENDPOINT>:<port>", "https://<ICP_PROXY_IP>" ], "redirect_uris":["https://<ICP_PROXY_IP>:<PORT_WHERE_SERVICE_RUNS>/auth/liberty/callback"] } -
Create the customized version of your
regisration.jsoncontent by editing the sample content.
Thewlp_client_idandwlp_client_secretcan be generated by the content service. Your output might resemble the following code:wlp_client_id: {{ randAlphaNum 32 | b64enc | quote }} wlp_client_secret: {{ randAlphaNum 32 | b64enc | quote }} -
Register a client with the IBM Cloud Private authentication service. Run the following API command from any node that has access to the master node:
curl -i -k -X POST -u oauthadmin:$OAUTH2_CLIENT_REGISTRATION_SECRET -H "Content-Type: application/json" --data @platform-oidc-registration.json https://icp-ip:port/idauth/oidc/endpoint/OP/registration
Authentication enforcement by workloads
After you register the content service as a client of IBM Cloud Private authentication service, you can use the IBM Cloud Private OIDC authentication endpoints to enforce authentication. IBM Cloud Private supports two authentication protocols: OIDC and Security Assertion Markup Language (SAML). The OIDC-based authentication service is the default service in IBM Cloud Private. If required, you can be configure a SAML server to provide federated authentication.
OIDC and SAML are both used for single-sign on with IBM Cloud Private, but for different purposes.
IBM Cloud Private is an OIDC identity provider and provides authentication and authorization services to the IBM Cloud Private management console and APIs. It works along with one or more Lightweight Directory Access Protocol (LDAP) providers to authenticate the user ID and password with the LDAP service. It provides an access token for subsequent requests to IBM Cloud Private services. IBM Cloud Private is an identity provider through LDAP.
You can configure IBM Cloud Private as a SAML service provider to allow federated authentication with an external SAML 2.0 identity provider. When you log in to the management console, your browser is redirected to the third-party party login page and OIDC issues a bearer token to you.
The following endpoints can be used to enforce authentication for both the OIDC-based and SAML-based authentication services:
OIDC Endpoints for Authentication
IBM Cloud Private provides OIDC-based authentication through WebSphere Liberty server. The IAM authentication micro service manages the OIDC authentication. This authentication is backed by the Liberty-based OIDC server for providing local and LDAP directory-based authentication.
The following standard OIDC APIs are supported by IBM Cloud Private:
https://icp-ip:port/idprovider/v1/infohttps://icp-ip:port/idprovider/v1/auth/identitytokenhttps://icp-ip:port/idprovider/v1/auth/token(or)https://icp-ip:port/idauth/oidc/endpoint/OP/tokenhttps://icp-ip:port/idprovider/v1/auth/authorizehttps://icp-ip:port/idprovider/v1/auth/userInfo-
https://icp-ip:port/idprovider/v1/auth/introspectNote: Following is the difference between the two token endpoints:
-
https://icp-ip:port/idprovider/v1/auth/tokenreturns an encrypted token and does more IBM Cloud Private-specific operations before it calls the following endpoint. It then encrypts the token before it returns the token. -
https://icp-ip:port/idauth/oidc/endpoint/OP/tokenis the default Liberty OIDC token endpoint.
Ingresses are available for both the endpoints. However, use the prefix.
-
Similarly, https://icp-ip:port/oidc/endpoint/OP/token returns an encrypted token and can be used for all IBM Cloud Private APIs. https://icp-ip:port/idauth/oidc/endpoint/OP/token returns an unencrypted token and cannot
be used for IBM Cloud Private APIs; it can be used by a content service for authentication or by a service that requires a default OIDC provider.
UI authentication - OAUTH Dance implementation
OAuth Dance is an authentication process that identifies users who use OAuth. It follows a two-step process:
-
Call to the
/authorizeendpoint withclient_id,scope,redirect_uri, andgrant_type. The/authorizeendpoint presents a login page where you can enter your user name and password. On successful authentication, a code is returned. Following are the default parameters:scope: openid+email+profileclient_id: The unique ID that is used to recognize a service withresponse_type: coderedirect_uri: https://ip:port/callback. The URL to which the user is redirect to after successfully authentication. In an OAuth dance, the call to the/authorizeendpoint is withresponse_typevalue equal to the code.
Following is an example of the authorize endpoint that calls the IBM Cloud Private management console login page:
GET https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/authorize?client_id=client_id&scope=openid&redirect_uri=redirect_uri&response_type=code&state=state -
After the user is authenticated, the OIDC server returns a code. The service that runs on the
redirect_uriand listens on this URL, retrieves the code (https://ip:port/callback?code=xvcbdb) and calls the/tokenendpoint to retrieve the token. Following are the default parameters:client_id: The service client IDclient_secret: The service client secretscope: openidredirect_uri: https://ip:port/callbackgrant_type: authorization_code
The /authorize endpoint from the list of OIDC APIs can be used by the content service for its user interface based login. This API requires the client ID and secret to be passed to the IBM Cloud Private authentication service to make
out where the user must be redirected to after a successful authentication. These URIs are the redirect_uris that are specified during the client registration process.
The redirect_uris is the callback that the Liberty server can call for completing the OAUTH Dance. This callback URL of the content service must take the authorization code and then send the /token request to get the valid
access tokens. With these tokens set in the session, the content service can forward the request to the intended page on its service from successful authentication.
CLI authentication
IBM Cloud Private supports CLI-based authentication. If you are running sidecar applications and want to use IBM Cloud Private security features for authentication, you can use the following APIs by running the Curl commands:
Authenticate by using your user name and password:
curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
-d "grant_type=password&client_id=<ID>&client_secret=<secret>&username=admin&password=admin&scope=openid" \
https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/identitytoken --insecure
Where, <Cluster Master Host>:<Cluster Master API Port> is defined in Master endpoints.
Following is a sample output:
{
"access_token": "38400d87f39a7c328a4605265eb601bebd9426e2ef6f1b51a449da6a9cb08e03543857ac4ffbd7d2c259867c89324563c5a89f026683aca9262858ae7ffb1e635242eabab3d579793e8f9da09070708dccf2a8d660f3be06550f02af681d2fa64562fb9dc3df1b19839a5d3933311f89348634fa6908fa7d2d50584ffd36f9dc298a3411d3f5abad5c7f45283428ecf0de249eac5534136c31317493f85363126bfe9a6f582403c34a3dab96e3e7bba83c263f1a4ff8d8609fca888852e097e3bc382b822576a53e55e6753c57f79d5703cf6b6bed4b015702ce3ce1636fd834944231fa77eb90079bca398be511f22fd58792a3766a100af10f274e6b9d75a2be2fe6ab18a3ce2ed0c8da7542e0b79f08e32a9ddced6a389572e6247230e1b62adf5fb0ee6549c06f99b85afc7cccd7a51012dea5df40fc27a934be37e9465ddb46a4f43ec542faecb4e6dd062189392b802b8a0ad8c38a00a14f7b9625bcdab251b87cd478c0e5d3c79f8887797da767f209f5fb2b3d44c8b051f49c2ed680a14cd15388b545ca573540184bb27be28378dbe0ecbe2d71c0ac3d7365fce5f1948ead1576f444f70c87d7ba89352b0d2b795a11ccc5ad06441c4143a3e78f80316c72110ba7062159f249719c664818befd6514b1526498729fe624852128495a5fa9c57ba8c9386a1040e0bb8013e93a751722de6e85966994cefce4c43066",
"token_type": "Bearer",
"expires_in": 43199,
"scope": "openid",
"refresh_token": "ryJlHRTJu0ZWgpDm9Ci11YenaPUk2ehZ51p1gAmL2w5VAThuff",
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiNjZrYjBqMTY1NDBuN3ZhZXczem4iLCJyZWFsbU5hbWUiOiJjdXN0b21SZWFsbSIsInVuaXF1ZVNlY3VyaXR5TmFtZSI6ImFkbWluIiwiaXNzIjoiaHR0cHM6Ly9teWNsdXN0ZXIuaWNwOjk0NDMvb2lkYy9lbmRwb2ludC9PUCIsImF1ZCI6IjZhNTVlMWEzZmY1Mjc5NjY2YTBiNmI4NzcxYTViMzEwIiwiZXhwIjoxNTI5MzQzOTM4LCJpYXQiOjE1MjkzMTUxMzgsInN1YiI6ImFkbWluIiwidGVhbVJvbGVNYXBwaW5ncyI6W119.OHZTG7I5SjTk3uHIJsk7zzg5ueQM5fEU9nC11jSvpRw-tm1T-OBqjKHPQ_g-uhmFuuym3hvQcEB-wRQi4NMB_d580eeXHYYl_NiawunkHIl7AISQQetc7HS4U7ZXx3Mc2EmvqyVyo0zSYowGfT6D_X36O_E6Riz-_rrGvc1nrzOdGa8IjJIi_GncSs5IFNUQxtRA9ZwdtIbQcRrSs9B3hPH8sJqUnaZnOjAkctJA8zQY0eV3IAZ4lFc01_hT5DrOdtAiSAQBoakttxbY8iqEaNHAc07wUiN6J4rcgtJE2ZwOZth1D_39KyD5nbRbNO8HJh6hYFcBplFGwp9FDZb27A"
}
This API returns an access_token, id_token, and a refresh_token. The access_token is used for authorization of IBM Cloud Private security components that include team, user, user group, service
ID, service, API key, and other components. The id_token is used for authorization of Kubernetes components that include pods, daemonsets, services, and other components. The refresh_token can be used to retrieve fresh
tokens in case the tokens are expired.
Retrieve a fresh token
curl -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
-d "grant_type=refresh_token&client_id=<ID>&client_secret=<secret>&scope=openid&refresh_token=ryJlHRTJu0ZWgpDm9Ci11YenaPUk2ehZ51p1gAmL2w5VAThuff" \
https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/token --insecure
Following is a sample output:
{
"access_token": "77f3ea9695e50d147a3081990c331f8ce9baa0b6d02ac4e970c886eabccd7aa7e7f12e1897ceacbdf6bdaf0881ed5a725f214209eb20b9415c2fcf4ad1afb90412a247aeab6ab0e026e08013b8f2b773b5bdb2d8d3c1247e9e7ebeaa8c9c9c66c1e85caf78105e35e934a28f21619bef2ff17cebe75792da86b4a65c19973713559569e92ae6aa86ddb8ee48991c6ced9caf41ae6c3b88f67fcaacf8c2c6af82018b5f55a4e35c1b9026438b690a606de0314bdced35eab21642b4b6c33c5241db457f2564840b9d32c255d0bfa9e4fda176416f7481c205ee98912790a11134597ce7245264669568fd69153a8e2f240df9edb4df3b219e213c3cfb0366713802a9a525fe85c9ec2a8c54ba61b5d845054ff23eb466c990c15dcb025ef320f36bb21ec0d0a412bcdecafba57da6b239891e22c139a7d4057f84fd741215ed5567c3f4b824d9bbfe92d56b77fe1712d35cea60e12f5207b727e3cc658db1b8b5002780049a5faefd8ccc2ccee9100472dfff58978ee3e7303547dc4ea03025275e58ec4e3da8e6ae91939bfb092f1ce78fe2d91124c179f55bda4027957093090c4f47037771e9cacf227867063c909e9aee3bf87140426052821116c6484037822a41f05a0fa565276b5ff1a8a654d3d5d119f6a665469a7591e4ec197d6a90bd586b8b95e227b9869b8654c23c10f78fc6a3fcbbe6d543638f379736193643",
"token_type": "Bearer",
"expires_in": 43199,
"scope": "openid",
"refresh_token": "5QM3H8fmGjxhPRyYlQ77s4Z5APOHVk5276ItT8q41e2xKNMxF6"
}
Validate tokens
At any point in time, if you want to validate the tokens that you received by using the previous APIs, you can use either user information or introspect call. See the following APIs:
Get user information
export ACCESS_TOKEN=<Your access token>
curl -k -X POST --header "Authorization: Bearer $ACCESS_TOKEN" \
https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/userInfo
Following is a sample output:
{
"sub":"admin",
"iss":"https://mycluster.icp:9443/oidc/endpoint/OP"
}
Call introspect endpoint
export TOKEN=<your token>
export CLIENT_ID=<client_id>
export CLIENT_SECRET=<client_secret>
Get the basic authorization header by using the following commands:
BASIC_AUTH_HEADER=`echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64 -w 0`
curl -H "Authorization: Basic $BASIC_AUTH_HEADER" -d "token=$TOKEN" https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/introspect
Revoke a token
If you want to revoke a particular token instead of waiting for its expiry, you can use the following API:
export TOKEN=<Your access token here>
export CLIENT_ID=<client_id here>
export CLIENT_SECRET=<client_secret here>
Get the Basic authorization header by using the following commands:
BASIC_AUTH_HEADER=`echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64 -w 0`
curl -k -X POST -H "Authorization: Basic $BASIC_AUTH_HEADER" -d "token_type_hint=access_token&token=$TOKEN" \
https://<Cluster Master Host>:<Cluster Master API Port>/idprovider/v1/auth/revoke
Following is a sample output:
{}