Background
Some background context is important for this to make sense. On Google Cloud, many services operate as a Service Account. For example, Google Cloud Storage has a unique service account per Google Cloud project. You can get the Cloud Storage service account via the Cloud Console, API, or even curl (as shown below):
$ curl https://storage.googleapis.com/storage/v1/projects/${PROJECT_ID}/serviceAccount \
--header "Authorization: Bearer $(gcloud auth print-access-token)"
The service account is usually expressed as an email like:
[email protected]
When the Cloud Storage service interacts with other Google Cloud services, it uses this service account to authorize those actions.
Customer Managed Encryption Keys
By default, all data is encrypted at rest on Google Cloud. Normally this data is encrypted with Google-managed keys. When you enable Customer Managed Encryption Keys (CMEK) for Cloud Storage, you configure a Cloud Storage bucket to automatically encrypt/decrypt data that is uploaded/downloaded using a provided Cloud KMS key. You, the customer, have control over that key through Cloud KMS.
Note: I'm going to explain how this works for uploading files, but the same principles apply in reverse for downloading them.
Without CMEK
Without CMEK, a developer uploads an object to Cloud Storage. Cloud Storage encrypts the object with a Google-managed encryption key and persists the encrypted object to disk:
+-----------+ +---------------+ +-------+
| Developer | | Cloud Storage | | Disk |
+-----------+ +---------------+ +-------+
| | |
| Upload object | |
|---------------------->| |
| | ----------------------------------\ |
| |-| Encrypt with Google-managed key | |
| | |---------------------------------| |
| | |
| | Write encrypted object |
| |-------------------------------------->|
| | |
With CMEK
With CMEK, a developer uploads an object to Cloud Storage. Cloud Storage invokes the Cloud KMS API using the Cloud Storage service account to encrypt the object and persists the encrypted object to disk:
+-----------+ +---------------+ +-----------+ +-------+
| Developer | | Cloud Storage | | Cloud KMS | | Disk |
+-----------+ +---------------+ +-----------+ +-------+
| | | |
| Upload object | | |
|---------------------->| | |
| | | |
| | Encrypt this object | |
| |---------------------------------->| |
| | | |
| | Here's the encrypted object | |
| |<----------------------------------| |
| | | |
| | Write encrypted object | |
| |---------------------------------------------->|
| | | |
The most important point here is that the Cloud KMS API is invoked using the Cloud Storage service account's identity, not the calling developer's identity.
This is by design, because most customers want CMEK to be transparent to the developer. When you enable CMEK on a Cloud Storage bucket, developers do not need to be aware of CMEK configuration. They use the Cloud Storage API as normal, and Cloud Storage takes care of the encryption/decryption operations using the key you specified. The developer does not need permissions on the Cloud KMS keys because, as shown in the diagram above, the developer never interacts with Cloud KMS directly.
Restricting Access
So, revisiting your original question:
Is there any way that I could restrict encrypt/decrypt permission for a user? More specifically, this user should be able to upload files to the first storage bucket, and not to the second bucket, like we could do with AWS KMS + S3.
You have a few options here:
You could use Application-Layer Encryption (ALE) instead of CMEK. You can still use Cloud KMS, but the Developer encrypts the data using Cloud KMS before saving to Cloud Storage:
+-----------+ +-----------+ +---------------+ +-------+
| Developer | | Cloud KMS | | Cloud Storage | | Disk |
+-----------+ +-----------+ +---------------+ +-------+
| | | |
| Encrypt this object | | |
|---------------------------------->| | |
| | | |
| Here's the encrypted object | | |
|<----------------------------------| | |
| | | |
| Upload KMS-encrypted object | | |
|-------------------------------------------------->| |
| | | ----------------------------------\ |
| | |-| Encrypt with Google-managed key | |
| | | |---------------------------------| |
| | | |
| | | Write KMS-encrypted, Google-encrypted object |
| | |------------------------------------------------->|
| | | |
Do not grant the user permissions on the bucket. Instead of restricting IAM permissions on the key, you need to restrict IAM permissions on the bucket.