nodejs-vision icon indicating copy to clipboard operation
nodejs-vision copied to clipboard

Can't use with Application Default Credentials

Open lostpebble opened this issue 4 years ago • 15 comments

Environment details

  • OS: Windows
  • Node.js version: 13.6.0
  • npm version: 6.13.4
  • @google-cloud/vision version: 1.9.0

Steps to reproduce

  1. Have my gcloud shell all set up correctly for ADC
  2. Try and use this library as I'm using all my other Google API Node.js Client libraries
  3. Get an error:

7 PERMISSION_DENIED: Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the vision.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.

Has this always been the case? I thought I'd made use of the library before with ADC.

lostpebble avatar Mar 02 '20 16:03 lostpebble

@lostpebble I'm not 100% when this became a requirement, I'll see if I can find someone to dig into this for you.

Are you unblocked for the time being did you find these instructions on creating a service account?

bcoe avatar Mar 03 '20 01:03 bcoe

I have multiple deployment / dev environments - such as Cloud Functions, Kubernetes, and my local windows dev machine... Having to consider and configure environment variables for all these use-cases now is really not a great dev experience. I'm not even sure what the path structures look like in my deployment environments. This was quite a productivity blocker yesterday- I ended up deciding to move on and forget about this part of my app's development for now.

Its been years now that I've relied on simply ADC for all the Google Cloud products I use in my Node.js applications, so I would have hoped this would be the same.

lostpebble avatar Mar 03 '20 09:03 lostpebble

Can you please list your Cloud SDK version? 'gcloud version' We had a release of Cloud SDK that changed the ADC behavior and it could produce the behavior described, but if you update to the latest version and run 'gcloud auth application-default login' everything should work as before.

AlanGasperini avatar Mar 03 '20 18:03 AlanGasperini

@AlanGasperini that's already what I did.

But I'll do it again to make sure:

C:\dev> gcloud version
Google Cloud SDK 282.0.0
alpha 2019.05.17
app-engine-java 1.9.78
app-engine-python 1.9.88
beta 2019.05.17
bq 2.0.54
cloud-datastore-emulator 2.1.0
core 2020.02.21
docker-credential-gcr
gcloud
gsutil 4.47
Updates are available for some Cloud SDK components.  To install them,
please run:
  $ gcloud components update

Then I updated to latest:

Your current Cloud SDK version is: 282.0.0
You will be upgraded to version: 283.0.0
...
Update done!

Did the login auth stuff again:

C:\dev> gcloud auth application-default login
...
Credentials saved to file: [C:\Users\Paul\AppData\Roaming\gcloud\application_default_credentials.json]

These credentials will be used by any library that requests Application Default Credentials (ADC).

And then tried to run the API stuff again, but unfortunately the same error:

7 PERMISSION_DENIED: Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the vision.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.

lostpebble avatar Mar 04 '20 08:03 lostpebble

Can you please check if application_default_credentials.json has this field? quota_project_id That will help determine the nature of the error.

AlanGasperini avatar Mar 04 '20 16:03 AlanGasperini

It currently has a structure like this:

{
  "client_id": xxx,
  "client_secret": xxx,
  "refresh_token": xxx,
  "type": "authorized_user"
}

So no quota_project_id to be seen

lostpebble avatar Mar 04 '20 18:03 lostpebble

On that note, something weird was happening before.. I'm not sure exactly what changed it. I think it was before I re-did the gcloud auth application-default login the last time.

I was getting an error from @google-cloud/vision that basically said I hadn't enabled the API (I definitely had) and it had a link that sent me to the cloud console website to enable it - but the link was incorrect and had a weird "project id" in it that the console didn't know what to do with and just gave me an error.

lostpebble avatar Mar 04 '20 18:03 lostpebble

There are three flows that are typically used for development:

ADC with the default Cloud SDK client id. That is what happens when you do 'gcloud auth application-default login'. These credentials use a global project for quota and billing. APIs that have usage based billing(such as vision) have been disabled, because the billing needs to be charged to a customer project.

ADC with a different client id. You can set this with --client-id-file flag, documented here: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login This will use ADC, but APIs that bill on usage will charge the project associated with the given client id.

Service accounts. This will use service account credentials, and will bill against the project associated with the service account. Documented here: https://cloud.google.com/docs/authentication/getting-started

We have enabled a fourth flow recently, which uses ADC with default credentials, and the ability to specify a project for billing, using the --add-quota-project flag. This requires that you specify a project where you have permission to make API calls, and will use the active gcloud project as the billing project.

It sounds like you've always been using the first method(plain ADC) and perhaps it has broken recently. If you are calling vision APIs that have a cost per API call, then plain ADC will not work because GCP will need a customer project to charge for the calls.

AlanGasperini avatar Mar 04 '20 18:03 AlanGasperini

@AlanGasperini ahh okay. Thanks for explaining.

I now ran the auth like so:

gcloud auth application-default login --add-quota-project

and my application_default_credentials.json looks like this:

{
  "client_id": xxx,
  "client_secret": xxx,
  "quota_project_id": xxx,
  "refresh_token": xxx,
  "type": "authorized_user"
}

Unfortunately the same error is persisting though.

7 PERMISSION_DENIED: Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the vision.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.

I think something must have broken for @google-cloud/vision, or it isn't communicating properly with the billing stuff. I make use of multiple APIs which require billing and they still continue to run without issue.

lostpebble avatar Mar 05 '20 18:03 lostpebble

Hello devs, has anyone managed to solve these problems? The same thing happens to me. :(

wvvinicius avatar May 07 '20 15:05 wvvinicius

Devs, after generate new file a with a new key. I import the new file to folder of project and it worked. Tks

wvvinicius avatar May 07 '20 21:05 wvvinicius

Hi there @lostpebble! After reproducing the issue successfully, I found that I was able to solve it by adding a flag to set the quota project, like so:

gcloud auth application-default set-quota-project QUOTA_PROJECT_ID

Would you mind giving this a try to see if it helps you?

sofisl avatar Jun 15 '20 21:06 sofisl

Hi @sofisl ,

I did what you suggested and it didn't work on the version which I used when I originally opened this issue. But after updating the package to ^2.1.0, it seems all is working automatically again now.

Thanks!

lostpebble avatar Jun 16 '20 14:06 lostpebble

Just thought I'd comment here to say, after trying this out a bit more lately- I noticed that my initial, first request after creating the client works fine. But every request after that fails with the Application Default Credentials error again. I need to create the client every time fresh for the requests to not fail, like so:

  const VisionApiClient = new vision.ImageAnnotatorClient();
  const visionResults = await VisionApiClient.annotateImage({ // ... });

This seems a bit wasteful, as surely a single instance of the client should be able to take care of all future requests?

lostpebble avatar Feb 02 '21 08:02 lostpebble

We have to implement Firebase for push notifications (extremely annoying and were forced by Google basically) and part of that process is implementing insecure service accounts into the NodeJS environment instead of using the one provided by the environment that is inside GCP, not Firebase.

Service account files should never be used in a production project, big security issue, they really need to fix their docs and Firebase so that it works with the account provided by the environment.

This also applies to some of their libraries that force you to use private keys during init... crazy.

ollyde avatar May 20 '22 12:05 ollyde

Hi folks — generally, it seems like the issues raised in the thread have been resolved. There is updated documentation on using Application Default Credentials, both here: https://cloud.google.com/docs/authentication/application-default-credentials and https://cloud.google.com/docs/authentication/provide-credentials-adc If you're still seeing issues with this, can you please open a new issue describing the problem?

Re: the Firebase issue, I apologize but we're not able to address that in this repo — I recommend filing an issue in the relevant repo for the library you're using.

meredithslota avatar Jan 12 '23 19:01 meredithslota

@meredithslota it's not resolved as some libraries are still asking for insecure JSON files. We should never ever be using JSON files to access Google Cloud environments, that's a security problem.

Really, what needs to happen is libraries like 'storage' or 'vision' need to upgrade to use the environments security parameters.

Right now in order to get round this issue we have to use the Secrets API and download the API key into memory on the container, which can also be a security issue.

A few years ago one of our services got hacked and the hackers spun up bitcoin minors because one of our developers used a JSON file to access the environment.

Not good.

ollyde avatar Jan 14 '23 17:01 ollyde