8

While testing a Google Cloud Function I wrote that attempts to access a secret stored in the Secret Manager, I get this error: Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource '<resource-name>' (or it may not exist).

My code:

const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
const secretClient = new SecretManagerServiceClient();

...

const [version] = await secretClient.accessSecretVersion({
  name: secretName
});
const secret = version.payload.data.toString();

I've followed the steps in the documentation, specifying the full name of the secret in the call to the service (projects/<project-id>/secrets/<secret-name>/versions/latest, so the problem in Can't access secret in GCP Secret Manager doesn't apply here) and giving the service account that runs my cloud functions the "Secret Manager Secret Accessor" role (which should rule out the root problem in Why isn't my Firebase app connecting to Google Secret Manager?).

I've seen this issue both when trying to trigger the function locally using curl and when testing it in the UI (GCF > Function details > Testing).

Is there anything I'm missing here?

bhawk90
  • 321
  • 1
  • 2
  • 7
  • Can you share the full error message? Does it actually say ``? – sethvargo Jul 20 '20 at 17:42
  • 1
    And did you grant the Cloud Function's service account permissions to access the secret? – sethvargo Jul 20 '20 at 17:42
  • It doesn't actually say ``````, it says the full name of the resource that I'm trying to access. And that is the full error message. Yes, I gave my service account access - I did so globally, but I confirmed that the service account shows up as an accessor when I view the secret in the console. – bhawk90 Jul 20 '20 at 17:52
  • 1
    And you're sure there's no small typo in the project or secret? You're using the project _ID_, not the project _name_? What happens if you run `gcloud secrets versions access `? – sethvargo Jul 20 '20 at 23:30
  • Correct, I'm confident there's no typo and that I'm using the project ID, not the name. I just tried the command you suggested in the Cloud Shell, copying the resource name directly from my code, and it successfully retrieved the secret version content. So it seems to be a problem with permissions, though I did give my GCF service account the role it needs as I said before - "Secret Manager Secret Accessor". – bhawk90 Jul 21 '20 at 02:30
  • Could it be that the function isn't running as that service account for some reason? I'm not sure how to check that. Though if not as that user I would think it would be as me, but I should have that permission as the project owner (and I gave myself the role anyway just to see if it would help, and it didn't). – bhawk90 Jul 21 '20 at 02:34
  • Turns out that was the case - I added the roles to the GCF administrative service account rather than to the runtime service account. Once I added them to the runtime account it worked. Thanks for the help! – bhawk90 Jul 21 '20 at 03:37

3 Answers3

17

It turns out that I gave the "Secret Manager Secret Accessor" role to the wrong service account - I gave it to the GCF administrative service account, which is used to create/update/delete functions (service-<project-id>@gcf-admin-robot.iam.gserviceaccount.com) instead of to the runtime service account, which is what's actually used to run the function (<project-id>@appspot.gserviceaccount.com).

Once I added the role above (among others the function needed) to the runtime service account, the function completed successfully.

bhawk90
  • 321
  • 1
  • 2
  • 7
  • 1
    lol. After searching everywhere for why I was having this issue, this prompted me to go double-check my permissions. Yep, same error, I had assigned the `Accessor` role to something else instead of the service account I wanted to give access to. – Ari Feb 01 '21 at 05:05
  • it's worth mentioning that firebase functions supports secrets in a non-async manner with appropriate permissions out of the box. These are useful for most scenarios and are a lot easier to implement – Kevin Danikowski Dec 27 '21 at 20:21
1

All other answers here are valid and useful, however, one might need one more piece of advice that solved a problem for me: I was using a wrong secret name. I used the "short" secret name, e.g. MY_SECRET_NAME string. While to make things work, the full qualified secret name should be used, e.g. projects/<MY_PROJECT_ID>/secrets/<MY_SECRET_NAME>. When I changed this, everything worked :)

Dmytro Titov
  • 2,802
  • 6
  • 38
  • 60
0

In addition to the other suggestions, I found I had to give Secret Manager Secret Accessor access to the Default compute service account (i.e. <project_number>-compute@developer.gserviceaccount.com).

I suspect this is as there is a sanity check as part of the Cloud Build process when building the Cloud Function that executes the top level python file. Since I access the secrets registry at this level, the Compute service account also needs access.

Mike Knapp
  • 71
  • 4