Search code examples
google-cloud-platformgoogle-cloud-storagegoogle-cloud-kms

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

Solution

  • 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.