gcloud beta terraform vet 快速入门

本快速入门介绍如何应用强制执行网域限制的限制条件。您将测试该限制条件并有意地抛出错误。然后,您需要修改限制条件,以便您的网域通过。

准备工作

  • 您需要一个 Google Cloud 项目
  • 您需要项目的以下 Identity and Access Management (IAM) 权限

    • resourcemanager.projects.getIamPolicy - 可以使用组织的 Security Reviewer 角色授予此权限。
    • resourcemanager.projects.get - 可以使用组织的 Project Viewer 角色授予此权限。

为了帮助您快速上手,以下说明使用预装了 Terraform 的 Cloud Shell 和克隆的政策库代码库。以下说明假定您已拥有 Google Cloud 账号。

快速入门

  1. 前往 Cloud Shell 并克隆政策库。

    克隆政策库

  2. 将示例 IAM 网域限制约束复制到 policies/constraints 目录。

    cp samples/iam_service_accounts_only.yaml policies/constraints
    
  3. 通过将您复制的约束输出到终端来检查约束。

    cat policies/constraints/iam_service_accounts_only.yaml
    

    输出如下所示:

    # This constraint checks that all IAM policy members are in the
    # "gserviceaccount.com" domain.
    apiVersion: constraints.gatekeeper.sh/v1alpha1
    kind: GCPIAMAllowedPolicyMemberDomainsConstraintV2
    metadata:
      name: service_accounts_only
      annotations:
        description: Checks that members that have been granted IAM roles belong to allowlisted
          domains.
    spec:
      severity: high
      match:
        target: # {"$ref":"#/definitions/io.k8s.cli.setters.target"}
        - "organizations/**"
      parameters:
        domains:
        - gserviceaccount.com
    

    请注意底部的 gserviceaccount.com。这指定只有来自 gserviceaccount.com 网域的成员才能出现在 IAM 政策中。

  4. 如需验证政策按预期工作,请在当前目录中创建以下 Terraform main.tf 文件。您可以使用 nano、vim 或 Cloud Shell Editor 创建 policy-library/main.tf

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = "~> 3.84"
        }
      }
    }
    
    resource "google_project_iam_binding" "sample_iam_binding" {
      project = "PROJECT_ID"
      role    = "roles/viewer"
    
      members = [
        "user:EMAIL_ADDRESS"
      ]
    }
    

    替换以下内容:

    • PROJECT_ID:您的项目 ID。
    • EMAIL_ADDRESS:示例电子邮件地址。可以是任何有效的电子邮件地址。例如 user@example.com
  5. 使用以下命令初始化 Terraform 并生成 Terraform 方案:

    terraform init
    
  6. 导出 Terraform 方案(如果系统提示),请在出现提示时点击授权

    terraform plan -out=test.tfplan
    
  7. 将 Terraform 方案转换为 JSON:

    terraform show -json ./test.tfplan > ./tfplan.json
    
  8. 安装 terraform-tools 组件:

    sudo apt-get install google-cloud-sdk-terraform-tools
    
  9. 输入以下命令,验证您的 Terraform 方案是否符合您的政策:

    gcloud beta terraform vet tfplan.json --policy-library=. --format=json
    

    由于您在 IAM 政策绑定中提供的电子邮件地址不属于服务账号,因此该方案违反了您设置的限制条件。

    [
    {
      "constraint": "GCPIAMAllowedPolicyMemberDomainsConstraintV2.service_accounts_only",
      "constraint_config": {
        "api_version": "constraints.gatekeeper.sh/v1alpha1",
        "kind": "GCPIAMAllowedPolicyMemberDomainsConstraintV2",
        "metadata": {
          "annotations": {
            "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.",
            "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only",
            "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml"
          },
          "name": "service-accounts-only"
        },
        "spec": {
          "match": {
            "target": [
              "organizations/**"
            ]
          },
          "parameters": {
            "domains": [
              "gserviceaccount.com"
            ]
          },
          "severity": "high"
        }
      },
      "message": "IAM policy for //cloudresourcemanager.googleapis.com/projects/PROJECT_ID contains member from unexpected domain: user:user@example.com",
      "metadata": {
        "ancestry_path": "organizations/ORG_ID/projects/PROJECT_ID",
        "constraint": {
          "annotations": {
            "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.",
            "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only",
            "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml"
          },
          "labels": {},
          "parameters": {
            "domains": [
              "gserviceaccount.com"
            ]
          }
        },
        "details": {
          "member": "user:user@example.com",
          "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID"
        }
      },
      "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID",
      "severity": "high"
    }
    ]
    
  10. 如要允许其他网域(您的电子邮件地址),请修改 policy-library/policies/constraints/iam_service_accounts_only.yaml 并将您的电子邮件网域附加到网域许可名单。在以下示例中,我们添加了 example.com,但您需要输入您自己的电子邮件地址的网域:

    apiVersion: constraints.gatekeeper.sh/v1alpha1
    kind: GCPIAMAllowedPolicyMemberDomainsConstraintV1
    metadata:
      name: service_accounts_only
    spec:
      severity: high
      match:
        target: ["organizations/**"]
      parameters:
        domains:
          - gserviceaccount.com
          - example.com
    
  11. 现在,再次验证您的 Terraform 方案,这应该不会发生任何违规行为:

    gcloud beta terraform vet tfplan.json --policy-library=. --format=json
    

    预期输出:

    []
    

问题排查

如果您收到以下错误 "Error 403: The caller does not have permission, forbidden",则表示您没有将 policy-library/main.tf 中的 PROJECT_ID 替换为您的项目名称,或者您没有对指定项目的必要权限。

修改项目名称和/或权限(resourcemanager.projects.getIamPolicyresourcemanager.projects.get)后,返回并再次导出 Terraform 方案,然后将 Terraform 方案转换为 JSON。