The Cloud Foundry CLI makes it easy to authenticate into a target API endpoint to consume the Cloud Controller API (CAPI).
The “cf login” command allows you to pass or interactively provide the user, password, org, and space. Once logged in, if you want to run raw commands, the “cf curl” can execute a request to an API endpoint. And the “cf oauth-token” command will return the OAuth token for the current login session.
But if you need to authenticate against and execute CAPI commands without access to the CF CLI (perhaps on your CI/CD host), you may need to understand the underlying communication flow. In this article, I’ll show you how use curl to make these calls.
Official CF CLI
First, let me say that unless you have special circumstances, I would suggest using the CF CLI to make your CAPI calls. It makes authentication and requests very easy, and has commands such as “cf curl” and “cf oauth-token” that give you access to underlying CAPI calls. And if you set the environment variable CF_TRACE=true, the raw HTTP request/responses are sent to stdout for detailed inspection.
Additionally, the CLI is continually updated with the latest feature set of the underlying API and insulates you from minor changes in the specification.
If you need tighter integration with your calling program, there are also Java and Go client libraries that can provide access to the CAPI.
But if none of these fit your needs, or you really love diving into the innards of the CAPI, read on for details.
Prerequisites
Before going on, make sure you have installed curl and jq 1.5 (json parser). Ubuntu 16.04 provides this version, but Ubuntu 14.04 only provides jq 1.3 which will throw errors when running the commands in this article.
Install curl:
$ sudo apt-get install curl -y
Then check your jq version and install jq 1.5+ if necessary from the download page:
$ jq --version $ wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 $ sudo cp jq-linux64 /usr/bin/jq $ sudo chown root:root /usr/bin/jq $ sudo chmod ugo+r+x /usr/bin/jq $ jq --version
CAPI using curl
In order to use the CAPI, we first need to identify the API endpoint, which has the syntax, https://api.<domain>. As examples:
For Pivotal Cloud Foundry: https://api.run.pivotal.io
For a local install of PCF Dev: https://api.local.pcfdev.io
Let’s set an environment variable to make our calls more compact. We will use Pivotal Cloud Foundry (free trial) for this article, but feel free to use any CF provider.
$ CFDOMAIN="run.pivotal.io" $ echo We will use this domain for the CF commands: $CFDOMAIN
Get standard endpoints
The first call we should make is one to “/info” which does not require any authentication and provides basic information on endpoints and required versions.
curl -s --insecure https://api.$CFDOMAIN/v2/info -H 'Accept: application/json' -H 'Content-Type: application/json' | jq
The authorization_endpoint is particularly important for us, since it is used for OAuth2 authorization. If we wanted to isolate this value, we could have jq pull it by piping the curl above to:
jq -r .authorization_endpoint
Authenticate
The second call we need to make is a POST to the authorization_endpoint pulled from above, appended with “/oauth/token”. If these credentials are valid, the output will contain an access token.
curl -s --insecure https://login.$CFDOMAIN/oauth/token -X POST -u "cf:" -H "Host: login.$CFDOMAIN" -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept:application/json' -d "grant_type=password&password=myp4ss%21&username=admin%40myhost.com" | jq
Note that the username and password MUST be be URL encoded. In the above call, we are pretending that the user/pass is admin@myhost.com/myp4ss! This means the @ sign in the username must be translated to %40 and the ! in the password had to be represented as %21. Here is an online URL encoding tool you can use to make these translations.
Upon success, you will get a large response, but the most important field is access_token. This is the token that gives us access to the secured CAPI calls. If you want to isolate the output to this field, you can pipe the call above to jk:
jq -r .access_token
Even better, let’s put this token in an environment variable called MYCFTOKEN so we can more conveniently use it in our subsequent calls.
MYCFTOKEN=$(curl -s --insecure https://login.$CFDOMAIN/oauth/token -X POST -u "cf:" -H "Host: login.$CFDOMAIN" -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept:application/json' -d "grant_type=password&password=myp4ss%21&username=admin%40myhost.com" | jq -r .access_token)
Get name of all apps
Now we pass our access token in the Authorization header for authorization to a service call. The “/v2/apps” URL is used to pull all the currently deployed applications.
curl -s --insecure https://api.$CFDOMAIN/v2/apps -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' -H "Authorization: bearer $MYCFTOKEN" | jq -r .resources[].entity.name
The results will be empty if there are no applications deployed. This should return the same names as “cf apps”.
Get name of all orgs/spaces
Now we use our access token in the Authorization header to pull all the organizations.
curl -s --insecure https://api.$CFDOMAIN/v2/organizations -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' -H "Authorization: bearer $MYCFTOKEN" | jq -r .resources[].entity.name
This should return the same names as “cf orgs”. And now all the spaces:
curl -s --insecure https://api.$CFDOMAIN/v2/spaces -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' -H "Authorization: bearer $MYCFTOKEN" | jq -r .resources[].entity.name
This should return the same values as “cf spaces”.
REFERENCES
https://apidocs.cloudfoundry.org/280/# (v2 API ref)
http://v3-apidocs.cloudfoundry.org/version/3.38.0/#authentication (v3 API ref)
https://docs.cloudfoundry.org/devguide/v3-commands.html (v3- commands)
https://stackoverflow.com/questions/27985469/how-to-get-oauth-token-from-cloudfoundry (shows use of “cf:” for user)
https://content.pivotal.io/blog/how-to-integrate-an-application-with-cloud-foundry-using-oauth2 (oauth2 explanation)
https://gist.github.com/subfuzion/08c5d85437d5d4f00e58 (curl common uses)
https://stedolan.github.io/jq/download/ (jq 1.5 binaries download)
https://stedolan.github.io/jq/manual/#Basicfilters (jq reference)
https://blog.scottlowe.org/2014/02/19/using-curl-to-interact-with-a-restful-api/ (curl with cookies, -c saves, -b uses cookies)
http://theblasfrompas.blogspot.com/2016/11/accessing-cloud-foundry-rest-api-from.html (accessing CAPI from Spring boot using generic HTTP REST)
NOTES
oauth token can also be found at~/.cf/config.json under they key “AccessToken” (should be secured at OS level)