使用自定义服务帐户在 GCP 中创建 VM 时,KMS 权限出现 400 错误

Posted

技术标签:

【中文标题】使用自定义服务帐户在 GCP 中创建 VM 时,KMS 权限出现 400 错误【英文标题】:400 Error on KMS Permissions when creating a VM in GCP using a custom service account 【发布时间】:2021-09-25 05:29:13 【问题描述】:

我正在使用 Terraform 创建一个 VM 实例和连接到所述实例的网络、计算磁盘、该磁盘的快照以及用于加密数据的 KMS 密钥环和密钥。

我使用自己创建的服务帐户向 GCP 进行身份验证,使用以下代码块:

credentials = file("gcp-account.json")

该帐户具有以下权限:

云 KMS 管理员 Cloud KMS CryptoKey 加密器/解密器 计算管理员 计算网络管理员 编辑器

然后,在google_compute_snapshotgoogle_compute_disk 块中,我提供kms_key_self_link 和服务帐户,以使用新创建的KMS 密钥和我的自定义服务帐户为请求加密数据:

kms_key_self_link       = var.kms_key_selflink
kms_key_service_account = var.service_account

我在google_compute_instance 块中做同样的事情,并在boot_diskattached_disk 中提供kms_key_self_link,并指定VM 应该使用自定义服务帐户来处理请求:

  service_account 
    email  = var.service_account
    scopes = []
  

然后,在运行terraform apply 时出现以下错误:

错误:创建实例时出错:googleapi:错误 400:Cloud KMS 错误 使用钥匙时 projects/project name/locations/location/keyRings/key ring name/cryptoKeys/key name:权限“cloudkms.cryptoKeyVersions.useToEncrypt”被拒绝 资源 'projects/project name/locations/location/keyRings/key ring name/cryptoKeys/key name:'(或者它可能不存在)。,kmsPermissionDenied

当我授予该权限时会得到解决

角色/cloudkms.cryptoKeyEncrypterDecrypter

Compute Engine Service Agent 的权限,然后脚本就可以正常运行了。

data "google_iam_policy" "kms_key_encrypt_decrypt" 
  binding 
    role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"

    members = ["serviceAccount:servicePROJECT_NUMBER@computesystem.iam.gserviceaccount.com"]
  


resource "google_kms_crypto_key_iam_policy" "crypto_key" 
  crypto_key_id = google_kms_crypto_key.key.id
  policy_data   = data.google_iam_policy.kms_key_encrypt_decrypt.policy_data

但是,我希望我的所有资源仅使用我的自定义服务帐户来处理请求,而不以任何方式涉及默认的 Compute Engine 服务代理。

我查过了,Compute Engine Service Agent 分配了哪些角色,只有一个:

计算引擎服务代理

并将完全相同的角色分配给我的自定义服务帐户。 这没有帮助。后来我注意到,问题只发生在VM的boot_disk中:

  boot_disk 
    kms_key_self_link = var.kms_key_selflink

    initialize_params 
      image = var.vm_image
      type  = var.gce_disk_type
    
  

当我注释掉boot_disk 块中的kms_key_self_link 时,其他资源(快照、计算磁盘、附加磁盘)也使用kms_key_self_link 和自定义服务帐户,没有任何问题。如果我将kms_key_self_link 参数留在boot_disk 中,问题仍然存在,我需要指定默认代理才能解决。

有没有办法只使用自定义服务帐户来配置我的所有资源,而无需默认 Compute Engine 服务代理的任何参与,我只是在我的脚本中遗漏了一些东西,或者默认代理是否需要保留一些操作?

【问题讨论】:

根据cloud.google.com/compute/docs/disks/customer-managed-encryption,您需要授予计算引擎 SA 的权限。请注意,这与启动 VM 时的默认计算引擎服务帐户或自定义服务帐户不同。这是控制平面服务帐号。 是的,当我向 Compute Engine 服务代理授予必要的权限时,一切正常。然而,我很好奇是否可以通过将加密器/解密器权限分配给自定义服务帐户并将此自定义帐户与 VM 相关联,在不修改或涉及 CE SA 的情况下启动和运行所有内容。 服务代理帐户由 Google 创建并管理控制平面。示例在您的帐户中为您创建资源。您可以向服务代理添加/删除角色,但不能替换它。 Google 使用服务代理帐户来管理您的资源。在您的情况下,您授权 Google 代表您解密数据以创建实例。 感谢两位的详细解释。 你能解决你的问题吗? 【参考方案1】:

因此,通过提供的答案证明,如果没有 Compute Engine 服务代理的参与,就不可能获得预配的所有资源。它必须有

角色/cloudkms.cryptoKeyEncrypterDecrypter

角色授予,无论使用任何其他自定义服务帐户。这是我在 Terraform 代码中用于授予它必要权限的策略:

data "google_iam_policy" "kms_key_encrypt_decrypt" 
  binding 
    role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"

    members = ["serviceAccount:servicePROJECT_NUMBER@computesystem.iam.gserviceaccount.com"]
  


resource "google_kms_crypto_key_iam_policy" "crypto_key" 
  crypto_key_id = google_kms_crypto_key.key.id
  policy_data   = data.google_iam_policy.kms_key_encrypt_decrypt.policy_data

感谢大家的回答。

【讨论】:

以上是关于使用自定义服务帐户在 GCP 中创建 VM 时,KMS 权限出现 400 错误的主要内容,如果未能解决你的问题,请参考以下文章

谷歌云项目:使用自定义界面创建

等待 GCP 基础架构更改传播的 Terraform 问题

如何使用 Stackdriver Trace 在 App Engine Standard 中创建自定义 Span?

Azure自动化帐户-如何使用自定义服务主体登录而不是作为帐户运行?

如何从本地机器访问 GCP bigquery API?

在 Dataflow 中创建作业时出错(当前用户不能充当服务帐户)