Lin Du
Lin Du

Reputation: 102207

Permission denied on Cloud KMS key when using cloud storage

I am using cloud storage upload a file with kms key. Here is my code:

await storage.bucket(config.bucket).upload(file, {
  kmsKeyName: `projects/${process.env.PROJECT_ID}/locations/global/keyRings/test/cryptoKeys/nodejs-gcp`,
  destination: 'mmczblsq.kms.encrypted.doc'
});

I have a cloud-storage-admin.json service account with cloud storage admin permission. Initialize the storage with this service account.

const storage: Storage = new Storage({
  projectId: process.env.PROJECT_ID,
  keyFilename: path.resolve(__dirname, '../.gcp/cloud-storage-admin.json')
});

And, I use gcloud kms keys add-iam-policy-binding add roles/cloudkms.cryptoKeyEncrypterDecrypter to cloud-storage-admin.json service account.

When I try to upload a file with kms key, still got this permission error:

Permission denied on Cloud KMS key. Please ensure that your Cloud Storage service account has been authorized to use this key.

update

☁  nodejs-gcp [master] ⚡  gcloud kms keys get-iam-policy nodejs-gcp --keyring=test --location=global
bindings:
- members:
  - serviceAccount:cloud-storage-admin@<PROJECT_ID>.iam.gserviceaccount.com
  - serviceAccount:[email protected]
  role: roles/cloudkms.cryptoKeyEncrypterDecrypter
etag: BwWJ2Pdc5YM=
version: 1

Upvotes: 3

Views: 12239

Answers (3)

Andreea
Andreea

Reputation: 31

Have u added the service account (which should look like "[email protected]") to the iam binding, in the members sections?

My terraform code looks like this for the use case:

enter image description here

Upvotes: 0

Herr Mefisto
Herr Mefisto

Reputation: 577

Is it possible to encrypt file using provided service account instead of cloud storage service account? It's a bit confusing. If I login to Cloud Storage then I can see all files decrypted (because Cloud storage service account has permission to decrypt it). If I use my service account then any person who log in to Cloud storage will see encrypted files (of course this person should not have access to KMS key).

I tried to encrypt this file on application side (using KMS) but there is a length limitation (65KB).

Upvotes: 0

sethvargo
sethvargo

Reputation: 26997

When you use kmsKeyName, Google Cloud Storage is the entity calling KMS, not your service account. It's a bit confusing:

  1. Your service account has permission to call the Cloud Storage API
  2. The Cloud Storage service account then calls the KMS API in transit

You will need to get the Cloud Storage service account and grant that service account the ability to invoke Cloud KMS:

  • Option 1: Open the API explorer, authorize, and execute
  • Option 2: Install gcloud, authenticate to gcloud, install oauth2l, and run this curl command replacing [PROJECT_ID] with your project ID:

    curl -X GET -H "$(oauth2l header cloud-platform)" \
      "https://www.googleapis.com/storage/v1/projects/[PROJECT_ID]/serviceAccount"
    
  • Option 3: Trust me that it's in the format service-[PROJECT_NUMBER]@gs-project-accounts.iam.gserviceaccount.com and get your [PROJECT_NUMBER] from gcloud projects list or the web interface.

Upvotes: 9

Related Questions