Alex Meuer
Alex Meuer

Reputation: 1779

Secret manager access denied despite correct roles for service account

I'm writing a cloud function in Nodejs (10), and trying to access a secret like so:

const [secret] = await new SecretManagerServiceClient().accessSecretVersion({
    name: `projects/PROJECT_NUMBER/secrets/SECRET_NAME/versions/latest`
})

I created the secret in the web console and the name used in code matches that of the existing secret. On the page for the cloud function details, it states that the service account is [email protected],com, so I added the secretmanager.secretAccessor role to it. However, I'm still getting the same error every time:

Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource 'projects/PROJECT_NUMBER/secrets/SECRET_NAME/versions/latest' (or it may not exist).

It makes no difference if I specify a concrete version or just use latest.

Upvotes: 69

Views: 73334

Answers (11)

CommonSenseCode
CommonSenseCode

Reputation: 25359

Add secret manager accesor to the service account of cloud build you can do it in Pulumi:

  const project = await gcp.organizations.getProject({});

  const cloudBuildSASecretManager = new gcp.projects.IAMBinding(
    `${env}-cloud-build-sa-secret-manager`,
    {
      project: gcpProject,
      role: "roles/secretmanager.secretAccessor",
      members: [`serviceAccount:${project.number}@cloudbuild.gserviceaccount.com`],
    }
  );

or in with gcloud:

gcloud projects add-iam-policy-binding $PROJECT_ID \ 
--member="serviceAccount:[email protected]" \ 
--role="roles/cloudbuild.serviceAgent"

Upvotes: 0

Loic Devaux
Loic Devaux

Reputation: 326

If you encounter this problem trying to add the "firestore-send-email" firebase extension with terraform (google_firebase_extensions_instance), you can fix the problem creating two service accounts beforehand :

  • service-${YOUR_PROJECT_ID}@gcp-sa-firebasemods.iam.gserviceaccount.com
  • service-${YOUR_PROJECT_ID}@gcf-admin-robot.iam.gserviceaccount.com

and add the roles below to the service accounts.

Terraform code:

resource "google_project_service_identity" "staging_firebaseext" {
  provider = google-beta

  project = google_firebase_project.staging.project
  service = "firebaseextensions.googleapis.com"
}

resource "google_project_iam_member" "staging_firebaseext" {
  project =google_project.staging.project_id

  for_each = toset([
    "roles/firebasemods.serviceAgent",
    "roles/secretmanager.admin",
  ])

  role = each.key

  member  = "serviceAccount:service-${google_project.staging.number}@gcp-sa-firebasemods.iam.gserviceaccount.com"
  depends_on = [
    google_project_service_identity.staging_firebaseext,

  ]
}

resource "google_project_service_identity" "staging_cloudfunc" {
  provider = google-beta

  project = google_firebase_project.staging.project
  service = "cloudfunctions.googleapis.com"
}

resource "google_project_iam_member" "staging_cloudfunc" {
  project =google_project.staging.project_id

  for_each = toset([
    "roles/cloudfunctions.serviceAgent",
    "roles/artifactregistry.reader"
  ])

  role = each.key

  member  = "serviceAccount:service-${google_project.staging.number}@gcf-admin-robot.iam.gserviceaccount.com"
  depends_on = [
    google_project_service_identity.staging_cloudfunc,
  ]
}

Upvotes: 0

Walker
Walker

Reputation: 954

I was having the same issue when running Go program and was getting error - rpc error: code = PermissionDenied desc = Permission 'secretmanager.versions.access' denied for resource 'projects/...' on my machine. It did not work by setting role "Secret Manager Secret Accessor" on my Compute Engine default service account that looks something like [email protected], nor editing permissions from within Secret Manager, side panel permissions.

What helped was gcloud secrets list and gcloud secrets get-iam-policy my-secret, as mentioned in this document. I am assuming it probably refreshed something locally, and I was able to get through without getting an error. https://cloud.google.com/sdk/gcloud/reference/secrets/get-iam-policy

Also gcloud secrets get-iam-policy my-secret will give which service account you are using with that secret.

Update -

I had the issue again, and this time, the command below helped.

gcloud auth application-default login

Hope this helps someone.

Upvotes: 0

TorrentialRain
TorrentialRain

Reputation: 11

In order to fix this issue, you must go to IAM (main page) -> Select the right Service Account as the Principal on there. THEN add the role of Secret Manager Secret Accessor.

If you go to the IAM -> Service Accounts page, and then go to add a new role, you will not find the Secrets Manager Secrets Accessor role - along with many others that aren't available there.

Can't take credit for this, this is from
arao6's comment on the previous top comment. I just don't have the rep to like posts yet.

Upvotes: 1

Abrar Mahi
Abrar Mahi

Reputation: 145

In my case, I was using my project-id instead of my project-number as mentioned in the OP's description:

const [secret] = await new SecretManagerServiceClient().accessSecretVersion({
    name: `projects/PROJECT_NUMBER/secrets/SECRET_NAME/versions/latest`
})

This wasn't very clear, especially since my project-id and numbers have been the same in my other projects.

You can find the project-number in the GCP console > Your Project > Settings and Utilities (3 dots on top right as of 2023) > Project Settings

Upvotes: 1

Lin Du
Lin Du

Reputation: 102207

HTTP cloud function code:

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

const secretManagerServiceClient = new SecretManagerServiceClient();
const name = 'projects/shadowsocks-218808/secrets/workflow/versions/latest';

exports.testSecretManager = async (req, res) => {
  const [version] = await secretManagerServiceClient.accessSecretVersion({ name });
  const payload = version.payload.data.toString();
  console.debug(`Payload: ${payload}`);
  res.sendStatus(200);
};

Deploy:

gcloud functions deploy testSecretManager --runtime nodejs10 --trigger-http --allow-unauthenticated

Deploying function (may take a while - up to 2 minutes)...done.                                                                                                                                                                                                                        
availableMemoryMb: 256
entryPoint: testSecretManager
httpsTrigger:
  url: https://us-central1-shadowsocks-218808.cloudfunctions.net/testSecretManager
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/shadowsocks-218808/locations/us-central1/functions/testSecretManager
runtime: nodejs10
serviceAccountEmail: [email protected]
sourceUploadUrl: https://storage.googleapis.com/gcf-upload-us-central1-43476143-b555-4cb2-8f6f-1b2d1952a2d7/42c4cda4-98a8-4994-a3be-d2203b9e646a.zip?GoogleAccessId=service-16536262744@gcf-admin-robot.iam.gserviceaccount.com&Expires=1596513795&Signature=kbLw5teN8EoYmj4fEweKKiIaakxcrhlUg2GGHV4jWJjvmeEfXePpRNOn9yz2zLn%2Fba0UqM9qdJMXujs5afBk%2BVBmywPEiptAZe2qgmldpr%2BsYejFu0woNgsPHVqtJ0NoWDo6W2dq4CuNNwO%2BaQ89mnhahUUQTInkJ55Y3wCIe9smk%2BqWtcvta3zICiToA7RQvPKY5MS6NViyj5mLxuJtDlTY9IKPL%2BqG6JAaQJSFYKYVgLyb6JfirXk8Q7%2FMvnHPpXPlhvsBLQksbF6jDPeefp2HyW4%2FSIQYprfpwKV3hlEIQyRQllz5J9yF83%2FxDPh%2BQPc5QmswKP5XAvYaszJPEw%3D%3D
status: ACTIVE
timeout: 60s
updateTime: '2020-08-04T03:34:32.665Z'
versionId: '2'

Test:

gcloud functions call testSecretManager --data '{}'

Got error same as you:

error: |-
  Error: function terminated. Recommended action: inspect logs for termination reason. Details:
  7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource 'projects/shadowsocks-218808/secrets/workflow/versions/latest' (or it may not exist).

solution:

You can find the serviceAccountEmail: [email protected] from the deployment information details of cloud function.

go to IAM & Admin web UI, click ADD ANOTHER ROLE button, add Secret Manager Secret Accessor role to this service account.

enter image description here

Test again:

> gcloud functions call testSecretManager --data '{}'

executionId: 1tsatxl6fndw
result: OK

Read the logs for testSecretManager cloud function:

gcloud functions logs read testSecretManager

You will see the logs for the secret payload string.

Upvotes: 59

Utkarsh Sharma
Utkarsh Sharma

Reputation: 625

OAuth scope plays an important role here and please make sure the scope is defined correctly.

To use Secret Manager with workloads running on Compute Engine or GKE, the underlying instance or node must have the cloud-platform OAuth scope. If you receive an error with the following message, it means the instance or node was not provisioned with the correct OAuth scopes.

Request had insufficient authentication scopes

The required OAuth scope to use Secret Manager is:

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

Example gcloud command to create dataproc with scope

gcloud dataproc clusters create xyz-pqr --region asia-south1 --subnet projects/xyz-pqr/regions/asia-south1/subnetworks/abc-serverless-vpc --zone asia-south1-b --master-machine-type n1-standard-4 --master-boot-disk-size 100 --num-workers 2 --worker-machine-type n1-standard-4 --worker-boot-disk-size 100 --image-version 2.0-debian10 --project xyz-development -scopes https://www.googleapis.com/auth/cloud-platform

Upvotes: 0

Samuel
Samuel

Reputation: 21

I had similar problem using terraform under gitlab. I must add two authorizations to the service account which runs the pipeline:

resource "google_project_iam_policy" "gitlab" {
  project     = "secret_owner_project_id"
  policy_data = data.google_iam_policy.iam.policy_data
}

data "google_iam_policy" "iam" {
  binding {
    role = "roles/secretmanager.secretAccessor"
    members = [
      "serviceAccount:[email protected]",
    ]
  }
  binding {
    role = "roles/viewer"
    members = [
      "serviceAccount:[email protected]",
    ]
  }
}

Upvotes: 2

Pascal Delange
Pascal Delange

Reputation: 516

I have had similar issues working with secretmanager and the python google-cloud-secretmanager library (2.4). Specifically, after creating a secret and giving my service account the secretmanager.secretAccessor role on this secret (and nothing else, following the principle of least privilege), I was getting the following error when trying to access it:

details = "Permission 'secretmanager.versions.access' denied for resource 'projects/projectid/secrets/keyname/versions/latest' (or it may not exist)."

I could only make it work by also adding the secretmanager.viewer role at the project level, which as far as I can tell is not described in the documentation.

Upvotes: 19

binarytrails
binarytrails

Reputation: 645

I had the same issue and to solve it, I just had to:

  1. Find the Service Account under General of my Google Cloud Function.

    It looked like <project-name>@appspot.gserviceaccount.com

  2. In IAM Admin, Add Secret Manager Secret Accessor Role to this Service Account.

After this, everything worked!

Upvotes: 35

niks
niks

Reputation: 659

A bit late, but maybe this answer could be useful for future users. I encountered the same behavior only with Python. I tried lots of things but only thing that worked was creating new service account with zero roles(if I granted it secretmanager.secretAccessor role immediately, I got the same error). Then when empty service account is created, in IAM tab I press +Add, copy my empty service account adress and ONLY then I add secretmanager.secretAccessor role to it. Then I use this account as the account that will execute particular function. You of course may need to add other roles depending on what your function is intended to accomplish.

Upvotes: 1

Related Questions