gcloud beta terraform vet 빠른 시작

이 빠른 시작에서는 도메인 제한을 시행하는 제약조건을 적용하는 방법을 보여줍니다. 이 제약조건을 테스트하고 내부적으로 오류를 발생시킵니다. 그런 후 도메인이 통과하도록 제약조건을 수정합니다.

시작하기 전에

  • Google Cloud 프로젝트가 필요합니다.
  • 해당 프로젝트에 대해 다음 Identity and Access Management(IAM) 권한이 필요합니다.

    • resourcemanager.projects.getIamPolicy – 이 권한은 조직의 보안 검토자 역할을 통해 부여될 수 있습니다.
    • resourcemanager.projects.get – 이 권한은 조직의 프로젝트 뷰어 역할을 통해 부여될 수 있습니다.

빠른 시작을 위해 이 안내에서는 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 편집기를 사용하여 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 정책 binding에 제공한 이메일 주소가 서비스 계정에 속하지 않으므로 이 계획은 설정된 제약조건을 위반합니다.

    [
    {
      "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으로 변환합니다.