Reputation: 95
I want to trigger a GCP cloud function from a simple nodejs app running locally.
Reading the documentation it should be simple:
gcloud auth application-default login
to write ADC to file used by client libraries./**
* TODO(developer): Uncomment these variables before running the sample.
*/
// Example: https://my-cloud-run-service.run.app/books/delete/12345
// const url = 'https://TARGET_HOSTNAME/TARGET_URL';
// Example (Cloud Functions): https://project-region-projectid.cloudfunctions.net/myFunction
const targetAudience = 'https://<REGION>-<PROJECTID>.cloudfunctions.net/<FUNCTIONNAME>';
const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();
const payload = {"prop1": "prop1Value"};
async function request() {
const client = await auth.getIdTokenClient(targetAudience);
const resp = await client.request({ url: targetAudience, method: 'POST', data: payload });
console.info(`Resp status: ${resp.status}; resp.data: ${resp.data}`);
}
(async () => {
await request();
})();
My understanding was that the google-auth-library would pick up the ADC from the file setup from running gcloud auth application-default login
and everything would work.
My user has permission to invoke GCP functions as I can trigger the function using CURL with the header -H "Authorization:bearer $(gcloud auth print-identity-token)" \
However when I run this, it doesn't get past the line:
const client = await auth.getIdTokenClient(targetAudience);
Failing with:
Cannot fetch ID token in this environment, use GCE or set the GOOGLE_APPLICATION_CREDENTIALS environment variable t o a service account credentials JSON file.
Using PubSub library works fine so expect ADC does work just not sure what am I missing when trying to trigger the GCP function. Am I using the google-auth-library correctly here ?
Thanks
Upvotes: 4
Views: 1722
Reputation: 5147
There are, of course, ways around your issue but fundamentally this library seems to be missing the support of application-default
credentials locally - a feature that many other google libs support out of the box. Requiring service account JSON files locally is an older approach.
This appears like a bug or at least missing feature and I've raised an issue in the client lib: https://github.com/googleapis/google-auth-library-nodejs/issues/1543
Local development without this support means that all developers need to export a privileged service account JSON key, store it locally, and configure an environment variable. GCS, secrets manager, etc, etc all just work "out-of-the-box" with locally authenticated application-default
credentials if you use gcloud auth application-default login
. It would be a shame to force this burden, (and potential security issues with JSON keys floating around the place), on our local developers for one library so hopefully the issue gains traction.
Upvotes: 3
Reputation: 1142
As mentioned in the thread:
gcloud auth activate-service-account --key-file is only for "you" running gcloud commands, it won’t be picked up by "applications" that need
GOOGLE_APPLICATION_CREDENTIALS
. As you can see from Invoke a Google Cloud Run from java or How to call Cloud Run from outside of Cloud Run/GCP?, you either need to have the JSON key file of Service Account, or have to be running inside a GCE/GKE/Cloud Run/App Engine/GCF instance.For this to work on your local environment, I recommend logging in with gcloud auth application-default login command (this command is meant to work as if you’ve set GOOGLE_APPLICATION_CREDENTIALS locally).
If that doesn't work, as a last resort you can refactor your code to pick up identity token from an environment variable (if set) while working locally,
such as:
$ export ID_TOKEN="$(gcloud auth print-identity-token -q)" $ ./your-app
To know more about how the code does it with a JSON key file,refer to the link and similar implementation there. For more information you can refer to a similar thread stated as :
Give the default service account access rights to Workspace resource(s) you're attempting to access.
Use the JSON key file you set up locally already, to have the Cloud Function run as the same user as is happening when you run locally.
Essentially do a hybrid where you create a new service account that ONLY has the permissions you want (instead of using the default
service account or your personal user, both of which might have far
more permissions then desired for safety/security), use a key file to run the Cloud Function under that identity, and only give the desired permissions to that service account.
Upvotes: 1