I'm trying to give a given GCE instance the permission to get one specific secret stored inside the secret manager. Not the WHOLE set of secrets, just one.

So, I added this binding in my terraform code for the service account which in turn is used inside my GCE:

resource "google_secret_manager_secret_iam_binding" "secret_iam_binding" {
  project   = <my project>
  # I also used google_secret_manager_secret.<my secret>.secret_id here, but nothing changed     
  secret_id = google_secret_manager_secret.<my secret>.name
  role      = "roles/secretmanager.secretAccessor"
  members   = [
    "serviceAccount:${<the service account used by the GCE instance>.email}"
  ]
}

This is the relevant code into the GCE creation terraform block: the scope should be enough I guess...

service_account {
    email = <the service account used by the GCE instance>.email
    scopes = ["cloud-platform"]
  }

Then, i ssh into the GCE node and tried to make some checks (since i have Container OS there, i had to use curl for testing)

  • Check if GCE is using the right service account: OK
curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email" -H "Metadata-Flavor: Google"
  • Getting a valid token: OK (well, I assume so)
TOKEN=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google" | jq -r .access_token)
  • Getting the secret value: KO
curl -s "https://secretmanager.googleapis.com/v1/projects/<my project id>/secrets/<my secret name>/versions/latest" -H "Authorization: Bearer $TOKEN" | jq -r .payload.data | base64 -d

with this error:

{
  "error": {
    "code": 403,
    "message": "Permission 'secretmanager.versions.get' denied for resource 'projects/<my project id>/secrets/<my secret name>/versions/latest' (or it may not exist).",
    "status": "PERMISSION_DENIED"
  }
}

thus, I guess I'm not granting enough roles to the service account....but I've no clue on which one I'm missing...

EDIT: outside the GCE node, I tried this command:

gcloud secrets get-iam-policy <my secret id> --project <my project id>

and the output is the expected:

bindings:
- members:
  - serviceAccount:<my service account name>>@<my project id>.iam.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwX8DrYyZtw=
version: 1
1

There are 1 best solutions below

0
On BEST ANSWER

It went out that the endpoint I was using to get the payload was incomplete. In facts, the structure was totally wrong:

curl -s "https://secretmanager.googleapis.com/v1/projects/<my project id>/secrets/<my secret name>/versions/latest:access" -H "Authorization: Bearer $TOKEN" | jq -r .payload.data | base64 -d

In other words, I was missing the ":access" trail.