how to authenticate IBM Cloud Function to use IBM Cloud Foundry API

616 views Asked by At

I'm having trouble figuring out how I could authenticate and authorize a IBM Cloud Function to use the IBM Cloud Foundry API to manage some routes on one of my Cloud Foundry apps.

The Cloud Foundry API says I'll need a valid bearer token, and that I can get a token using the Cloud Foundry UAA server. I don't think using OAuth2 fits for my use case because I am not accessing anyone else's resources on their behalf.

How can I authenticate & authorize my Cloud Function to access the Cloud Foundry API?

EDIT:

I just found Generating an IBM Cloud IAM token by using an API key. Is an IAM token compatible with the Cloud Foundry API? I see in this document that the https response describes the token type as Bearer.

2

There are 2 answers

0
habercde On

I can't guide you the full way right now, but I hope the information that I can provide will guide you into the right direction.

First you'll need to identify the authorization endpoint:

curl http://api.us-south.cf.cloud.ibm.com/info

With that and a valid IAM API token for your account you can get the bearer token that will work against the IBM Cloud CF Public API:

curl -v -X POST "https://iam.cloud.ibm.com/cloudfoundry/login/us-south/oauth/token" -d "grant_type=password&scope=&username=apikey&password=<yourApiKey>" --user "cf:"

Note that you need to append /oauth/token to the authorization endpoint that you received in step 1.

The response contains the access token that you need. For this example, just put it into an environment variable:

export TOKEN=<yourAccessToken>

Next try a command against the IBM Cloud CF Public API:

curl "https://api.us-south.cf.cloud.ibm.com/v2/organizations" -X GET -H "Authorization: bearer $TOKEN"

I hope once you have followed these steps in your command line, you will be able to do the same steps in your IBM Cloud Function and you'll reach your goal.

0
habercde On

I have created an example in Node.js that is based on the steps from my previous answer to this question.

The first action expects a valid apikey in params.apikey as input parameter and returns a bearer token:

/**
 *
 * main() will be run when you invoke this action
 *
 * @param Cloud Functions actions accept a single parameter, which must be a JSON object.
 *
 * @return The output of this action, which must be a JSON object.
 *
 */


function main(params) {

  const axios = require('axios');
  const querystring = require('querystring');

  return axios.post('https://iam.cloud.ibm.com/cloudfoundry/login/us-south/oauth/token',
      querystring.stringify({
        grant_type: "password",
        username: "apikey",
        password: params.apikey
      }), {
        auth: {
          username: 'cf'
        }
      })
    .then(res => {
      console.log(`statusCode: ${res.status}`);
      console.log(res.data);

      return {
        token: res.data.access_token
      };
    })
    .catch(error => {
      console.error(error);
      return {
        error: err.message
      };
    })
}

The second action expects a valid bearer token in params.token and is then executing an API call against the IBM Cloud CF Public API. In this example a get request against /v2/organizations:

/**
 *
 * main() will be run when you invoke this action
 *
 * @param Cloud Functions actions accept a single parameter, which must be a JSON object.
 *
 * @return The output of this action, which must be a JSON object.
 *
 */


function main(params) {

  const axios = require('axios');
  axios.defaults.headers.common['Authorization'] = "bearer " + params.token;
  const querystring = require('querystring');

  return axios.get('https://api.us-south.cf.cloud.ibm.com/v2/organizations')
    .then(res => {
      console.log(`statusCode: ${res.status}`);
      console.log(res.data);

      return {
        organizations: res.data.resources
      };
    })
    .catch(error => {
      console.error(error);
      return {
        error: error.message
      };
    })
}

Now you can put both actions into a sequence, so that the output from the first action (the bearer token) is used as token within the second action.