Perennialista
Perennialista

Reputation: 1302

How to get Openshift session token using rest api calls

As part of an automated tests suite I have to use OpenShift's REST APIs to send commands and get OpenShift's status. To authenticate these API calls I need to embed an authorization token in every call.

Currently, I get this token by executing the following commands with ssh on the machine where OpenShift is installed: oc login --username=<uname> --password=<password> oc whoami --show-token

I would like to stop using the oc tool completely and get this token using HTTP calls to the APIs but am not really able to find a document that explains how to use it. If I use the option --loglevel=10 when calling oc commands I can see the HTTP calls made by oc when logging in but it is quite difficult for me to reverse-engineer the process from these logs.

Theoretically this is not something specific to OpenShift but rather to the OAuth protocol, I have found some documentation like the one posted here but I still find it difficult to implement without specific examples.

If that helps, I am developing this tool using ruby (not rails).

P.S. I know that normally for this type of job one should use Service Account Tokens but since this is a testing environment the OpenShift installation gets removed and reinstalled fairly often. This would force me to re-create the service account every time with the oc command line tool and again prevent me from automatizing the process.

Upvotes: 17

Views: 43821

Answers (5)

Anthony O.
Anthony O.

Reputation: 24397

I tried to use @Nils Buer's solution but as I was in docker image in a GitLab job, I obtained a grep: unrecognized option: P error (as it was using BusyBox version of grep). Moreover inside this container, curl doesn't exist, I only have wget.

So I ended up using BusyBox wget and awk with this script:

IDP_URL=https://oauth-openshift.<clustername><domain>
wget -O - -S --header "Authorization: Basic $(echo -n "$USER_NAME:$USER_PASSWORD" | base64)" --no-check-certificate "$IDP_URL/oauth/authorize?client_id=openshift-challenging-client&response_type=token" 2>&1 | cat > ocp4_response.txt || grep "Location: $IDP_URL" ocp4_response.txt
OCP4_TOKEN=$(grep "Location: $IDP_URL" ocp4_response.txt | awk -F 'access_token=' '{split($2,a,"&"); print a[1]}')

(the || grep "Location: $IDP_URL" ocp4_response.txt is used as a way to avoid exiting the script because the resolution of the 302 Redirect ends up in a 404 Not Found so wget fails with an exit code of 1).

Upvotes: 0

Nils Buer
Nils Buer

Reputation: 41

In case you are using OpenShift CRC: Then the URL is: https://oauth-openshift.apps-crc.testing/oauth/authorize

Command to get the Token:

curl -v --insecure --user developer:developer --header "X-CSRF-Token: xxx" --url "https://oauth-openshift.apps-crc.testing/oauth/authorize?response_type=token&client_id=openshift-challenging-client" 2>&1 | grep -oP "access_token=\K[^&]*"

Note:

  1. 2>&1 is required, because curl writes to standard error
  2. --insecure: because I have not set up TLS certificate
  3. Adjust the user and password developer as needed (crc developer/developer is standard user in crc, therefore good for testing.)
  4. Token is per default 24h vaild

Export the Token to an environment Variable

export TOKEN=$(curl -v --insecure --user developer:developer --header "X-CSRF-Token: xxx" --url "https://oauth-openshift.apps-crc.testing/oauth/authorize?response_type=token&client_id=openshift-challenging-client" 2>&1 | grep -oP "access_token=\K[^&]*")

And Use the token then in, e.g., oc login:

oc login --token=$TOKEN --server=https://api.crc.testing:6443

Upvotes: 4

felician
felician

Reputation: 11

You need to use the correct url for your oauth server. In my case, I use openshift 4.7 and this is the url:

https://oauth-openshift.apps.<clustername><domain>/oauth/authorize\?response_type\=token\&client_id\=openshift-challenging-client

oc get route oauth-openshift -n openshift-authentication -o json | jq .spec.host

Upvotes: 1

Perennialista
Perennialista

Reputation: 1302

I have found the answer in this GitHub issue.

Surprisingly, one curl command is enough to get the token:

curl -u joe:password -kv -H "X-CSRF-Token: xxx" 'https://master.cluster.local:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token'

The response is going to be an HTTP 302 trying to redirect to another URL. The redirection URL will contain the token, for example:

Location: https://master.cluster.local:8443/oauth/token/display#access_token=VO4dAgNGLnX5MGYu_wXau8au2Rw0QAqnwq8AtrLkMfU&expires_in=86400&token_type=bearer

Upvotes: 16

anonymous
anonymous

Reputation: 51

You can use token or combination user/password. To use username:password in header, you can use Authorizartion: Basic. The oc client commands are doing simple authentication with your user and password in header. Like this

curl -H "Authorization: Basic <SOMEHASH>"

where the hash is exactly base64 encoded username:password. (try it with echo -n "username:password" | base64).

To use token, you can obtain the token here with curl:

curl -H Authorization: Basic $(echo -n username:password | base64)" https://openshift.example.com:8443/oauth/authorize\?response_type\=token\&client_id\=openshift-challenging-client

But the token is replied in the ugly format format. You can try to grep it

... | grep -oP "access_token=\K[ˆ&]*"

Upvotes: 4

Related Questions