0
votes

We're working on developing a microservice based architecture employing Google Cloud Functions.

We've developed a few functions and want to implement a discovery service. This discovery service would be used to determine if a specific function exists and is operational.

The service discovery itself is a cloud function. It makes a rest request to the below API and succeeds in local development using functions emulator and the default application credentials.

Google provides an API for this [https://cloud.google.com/functions/docs/reference/rest/v1beta2/projects.locations.functions/get][1]

When deployed to production we're receiving: { "code": 401, "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" } }

Cloud functions are stateless so there's no option to use a service account that I can see. How do I go about authenticating a cloud function to call the functions api to determine if a function is available?

Below is how we've accomplished this in a local dev environment:

var options = {
    method: 'get',
    uri: `https://cloudfunctions.googleapis.com/v1beta2/projects/${config.PROJECT_ID}/locations/${config.LOCATION_ID}/functions/${functionName}`
  }

  console.log (options.uri);
  request(options, function (err, res, body) {
    if (!err && res.status === 200) {
      if(typeof res.body.httpsTrigger.url !== undefined) {
        console.log('found a function');
        return cb(false, res.body.httpsTrigger.url);
      }
      else {
        console.log('no function found, looking for static content');
        return cb(true, `Service doesn't exist, returned ${res.status}`)
      }
    }
    else {
      console.log('no function found, looking for static content'); 
      return cb(true, `Service doesn't exist, returned ${res.status}`);
    }
  });
2

2 Answers

1
votes

So I finally figured out how to do this. It's a bit of hack:.

  1. Download the JSON Key file for the Service Account.
  2. Add the JSON file to the Function source.
  3. Install the google-auth-library NPM module.
  4. Modify the request to use the client from google-auth-library

    const keys = require('./VirtualAssistantCred.json');
    

    const {auth} = require('google-auth-library'); const client = auth.fromJSON(keys); client.scopes = ['https://www.googleapis.com/auth/cloud-platform']; client.authorize().then(function () { const url = https://cloudfunctions.googleapis.com/v1beta2/projects/${config.PROJECT_ID}/locations/${config.LOCATION_ID}/functions/${functionName}; client.request({url}, function(err, res) { if (err) { console.log(Error: ${err}); return cb(true, Service, ${functionName} doesn't exist, returned ${res}) } else { console.log(RESPONSE: ${JSON.stringify(res.data)}); console.log(Found Service at ${res.data.httpsTrigger.url}); return cb(false, res.data.httpsTrigger.url); } }); } );

0
votes

The API you mention contains method: projects.locations.functions.get , that requires one of the following OAuth scopes:

https://www.googleapis.com/auth/cloudfunctions

https://www.googleapis.com/auth/cloud-platform

You may have a look at the Authentication in HTTP Cloud Functions online document.