Membuat batasan CAI

Sebelum memulai

Framework Batasan

gcloud beta terraform vet menggunakan kebijakan Framework Batasan, yang terdiri dari batasan dan template batasan. Perbedaan antara keduanya adalah sebagai berikut:

  • Template batasan itu seperti deklarasi fungsi; yaitu menetapkan aturan di Rego dan secara opsional mengambil parameter input.
  • Batasan adalah file yang mereferensikan template batasan dan menentukan parameter input yang akan diteruskan ke template tersebut serta resource yang dicakup oleh kebijakan.

Ini memungkinkan Anda untuk menghindari pengulangan. Anda dapat menulis template batasan dengan kebijakan umum, lalu menulis sejumlah batasan yang memberikan parameter input berbeda atau aturan pencocokan resource yang berbeda.

Aset CAI vs resource Terraform

Aset Inventaris Aset Cloud adalah format ekspor data Google standar yang tersedia untuk banyak resource Google Cloud. Data CAI biasanya hanya tersedia setelah resource dibuat atau diperbarui. Namun, dengan mengonversi perubahan resource Terraform menjadi data Aset CAI, gcloud beta terraform vet memungkinkan Anda menulis kebijakan satu kali dan menggunakannya sebelum menerapkan serta sebagai pemeriksaan audit dengan alat yang kompatibel.

Alat yang kompatibel

Alat berikut bukan merupakan produk resmi Google dan tidak didukung. Namun, alat ini mungkin kompatibel dengan kebijakan yang ditulis untuk gcloud beta terraform vet:

Membuat template batasan

Sebelum mengembangkan template batasan, pastikan bahwa Aset yang ingin Anda tulis kebijakannya didukung oleh Inventaris Aset Cloud dan gcloud beta terraform vet.

Langkah-langkah untuk membuat template batasan adalah sebagai berikut:

  1. Kumpulkan data sampel.
  2. Tulis Rego.
  3. Uji Rego Anda.
  4. Siapkan kerangka template batasan.
  5. Sejajarkan Rego Anda.
  6. Siapkan batasan.

Mengumpulkan data sampel

Untuk menulis template batasan, Anda harus memiliki contoh data untuk beroperasi. Batasan berbasis CAI beroperasi pada Data Aset CAI. Kumpulkan data sampel dengan membuat resource dari jenis yang sesuai dan mengekspor resource tersebut sebagai JSON, seperti yang dijelaskan di panduan memulai CAI.

Berikut adalah contoh ekspor JSON untuk Alamat Compute:

[
  {
    "name": "//compute.googleapis.com/projects/789/regions/us-central1/addresses/my-internal-address",
    "asset_type": "compute.googleapis.com/Address",
    "ancestors: [
      "organization/123",
      "folder/456",
      "project/789"
    ],
    "resource": {
      "version": "v1",
      "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
      "discovery_name": "Address",
      "parent": "//cloudresourcemanager.googleapis.com/projects/789",
      "data": {
        "address": "10.0.42.42",
        "addressType": "INTERNAL",
        "name": "my-internal-address",
        "region": "projects/789/global/regions/us-central1"
      }
    }
  },
]

Tulis Rego

Setelah memiliki data contoh, Anda dapat menulis logika untuk template batasan di Rego. Rego Anda harus memiliki aturan violations. Aset yang sedang diulas tersedia sebagai input.review. Parameter batasan tersedia sebagai input.parameters. Misalnya, untuk mewajibkan aset compute.googleapis.com/Address memiliki addressType yang diizinkan, tulis:

# validator/gcp_compute_address_address_type_allowlist_constraint_v1.rego
package templates.gcp.GCPComputeAddressAddressTypeAllowlistConstraintV1

violation[{
  "msg": message,
  "details": metadata,
}] {
  asset := input.review
  asset.asset_type == "compute.googleapis.com/Address"

  allowed_address_types := input.parameters.allowed_address_types
  count({asset.resource.data.addressType} & allowed_address_types) >= 1
  message := sprintf(
    "Compute address %s has a disallowed address_type: %s",
    [asset.name, asset.resource.data.addressType]
  )
  metadata := {"asset": asset.name}
}

Beri nama template batasan Anda

Contoh sebelumnya menggunakan nama GCPComputeAddressAddressTypeAllowlistConstraintV1. Ini adalah ID unik untuk setiap template batasan. Sebaiknya ikuti panduan penamaan berikut:

  • Format umum: GCP{resource}{feature}Constraint{version}. Gunakan CamelCase. (Dengan kata lain, gunakan huruf besar untuk setiap kata baru.)
  • Untuk batasan resource tunggal, ikuti nama grup gcloud untuk penamaan resource. Misalnya, gunakan "compute" bukan "gce", "sql", bukan "cloud-sql", dan "container-cluster" bukan "gke".
  • Jika template berlaku untuk lebih dari satu jenis resource, hapus bagian resource dan hanya sertakan fiturnya (contoh: "GCPAddressTypeAllowlistConstraintV1").
  • Nomor versi tidak mengikuti format semver; itu hanya satu angka. Cara ini secara efektif membuat setiap versi template menjadi template yang unik.

Sebaiknya gunakan nama untuk file Rego yang cocok dengan nama template batasan, tetapi gunakan snake_case. Dengan kata lain, konversi nama menjadi kata-kata yang menggunakan huruf kecil dan terpisah dengan _. Untuk contoh sebelumnya, nama file yang direkomendasikan adalah gcp_compute_address_address_type_allowlist_constraint_v1.rego

Uji Rego Anda

Anda dapat menguji Rego secara manual dengan Rego Playground. Pastikan untuk menggunakan data yang tidak sensitif.

Sebaiknya tulis pengujian otomatis. Masukkan data sampel yang Anda kumpulkan di validator/test/fixtures/<constraint filename>/assets/data.json dan referensikan data tersebut di file pengujian seperti ini:

# validator/gcp_compute_address_address_type_allowlist_constraint_v1_test.rego
package templates.gcp.GCPComputeAddressAddressTypeAllowlistConstraintV1

import data.test.fixtures.gcp_compute_address_address_type_allowlist_constraint_v1_test.assets as assets

test_violation_with_disallowed_address_type {
  parameters := {
    "allowed_address_types": "EXTERNAL"
  }
  violations := violation with input.review as assets[_]
    with input.parameters as parameters
  count(violations) == 1
}

Tempatkan Rego dan pengujian Anda dalam folder validator di library kebijakan Anda.

Menyiapkan kerangka template batasan

Setelah memiliki aturan Rego yang berfungsi dan diuji, Anda harus mengemasnya sebagai template batasan. Framework Batasan menggunakan Definisi Resource Kustom Kubernetes sebagai container untuk kebijakan Rego.

Template batasan juga menentukan parameter yang diizinkan sebagai input dari batasan, menggunakan skema OpenAPI V3.

Gunakan nama yang sama untuk kerangka seperti yang Anda gunakan untuk Rego. Pada khususnya:

  • Gunakan nama file yang sama seperti untuk Rego Anda. Contoh: gcp_compute_address_address_type_allowlist_constraint_v1.yaml
  • spec.crd.spec.names.kind harus berisi nama template
  • metadata.name harus berisi nama template, tetapi ditulis dengan huruf kecil

Tempatkan kerangka template batasan di policies/templates.

Untuk contoh di atas:

# policies/templates/gcp_compute_address_address_type_allowlist_constraint_v1.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: gcpcomputeaddressaddresstypeallowlistconstraintv1
spec:
  crd:
    spec:
      names:
        kind: GCPComputeAddressAddressTypeAllowlistConstraintV1
      validation:
        openAPIV3Schema:
          properties:
            allowed_address_types:
              description: "A list of address_types allowed, for example: ['INTERNAL']"
              type: array
              items:
                type: string
  targets:
    - target: validation.gcp.forsetisecurity.org
      rego: |
            #INLINE("validator/gcp_compute_address_address_type_allowlist_constraint_v1.rego")
            #ENDINLINE

Sejajarkan Rego Anda

Pada tahap ini, mengikuti contoh sebelumnya, tata letak direktori Anda akan terlihat seperti ini:

| policy-library/
|- validator/
||- gcp_compute_address_address_type_allowlist_constraint_v1.rego
||- gcp_compute_address_address_type_allowlist_constraint_v1_test.rego
|- policies
||- templates
|||- gcp_compute_address_address_type_allowlist_constraint_v1.yaml

Jika meng-clone repositori library kebijakan yang disediakan Google, Anda dapat menjalankan make build untuk mengupdate template batasan secara otomatis di policies/templates dengan Rego yang ditentukan di validator.

Menyiapkan batasan

Batasan berisi tiga informasi yang diperlukan gcloud beta terraform vet untuk menerapkan dan melaporkan pelanggaran dengan benar:

  • severity: low, medium, atau high
  • match: Parameter untuk menentukan apakah batasan berlaku untuk resource tertentu. Parameter pencocokan berikut didukung:
    • ancestries: Daftar jalur ancestry yang akan disertakan menggunakan pencocokan gaya glob
    • excludedAncestries: (Opsional) Daftar jalur ancestry yang akan dikecualikan menggunakan pencocokan gaya glob.
  • parameters: Nilai untuk parameter input template batasan.

Pastikan kind berisi nama template batasan. Sebaiknya setel metadata.name ke slug deskriptif.

Contohnya, untuk hanya mengizinkan jenis alamat INTERNAL menggunakan contoh template batasan sebelumnya, tulis:

# policies/constraints/gcp_compute_address_internal_only.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GCPComputeAddressAddressTypeAllowlistConstraintV1
metadata:
  name: gcp_compute_address_internal_only
spec:
  severity: high
  match:
    ancestries:
    - "**"
  parameters:
    allowed_address_types:
    - "INTERNAL"

Contoh yang cocok:

Pencocok jalur ancestry Deskripsi
organizations/** Semua organisasi
organizations/123/** Segala sesuatu di organisasi 123
organizations/123/folders/** Segala sesuatu di organisasi 123 yang berada di bawah folder
organizations/123/folders/456 Semua yang ada di folder 456 dalam organisasi 123
organizations/123/folders/456/projects/789 Semuanya di project 789 di folder 456 dalam organisasi 123

Jika alamat resource cocok dengan nilai di ancestries dan excludedAncestries, alamat tersebut akan dikecualikan.

Batasan

Data paket Terraform memberikan representasi terbaik dari status sebenarnya setelah penerapan. Namun, dalam banyak kasus, status setelah penerapan mungkin tidak diketahui karena dihitung di sisi server. Dalam kasus ini, data juga tidak tersedia dalam Aset CAI yang dikonversi.

Membuat jalur ancestry CAI adalah bagian dari proses saat memvalidasi kebijakan. Gunakan project default yang disediakan untuk menyiasati project ID yang tidak dikenal. Jika project default tidak disediakan, jalur ancestry akan ditetapkan secara default ke organizations/unknown.

Anda dapat melarang ancestry yang tidak diketahui dengan menambahkan batasan berikut:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GCPAlwaysViolatesConstraintV1
metadata:
  name: disallow_unknown_ancestry
  annotations:
    description: |
      Unknown ancestry is not allowed; use --project=<project> to set a
      default ancestry
spec:
  severity: high
  match:
    ancestries:
    - "organizations/unknown"
  parameters: {}

Resource yang didukung

Jika Anda ingin gcloud beta terraform vet menambahkan dukungan untuk resource yang tidak ada dalam daftar ini, buka permintaan peningkatan dan pertimbangkan untuk menyumbangkan kode.

Daftar resource yang didukung bergantung pada versi gcloud beta terraform vet yang diinstal. Daftar resource yang didukung saat ini adalah sebagai berikut:

Resource Terraform Aset Inventaris Aset Cloud
google_access_context_manager_access_policy_iam_binding accesscontextmanager.googleapis.com/AccessPolicy
google_access_context_manager_access_policy_iam_member accesscontextmanager.googleapis.com/AccessPolicy
google_access_context_manager_access_policy_iam_policy accesscontextmanager.googleapis.com/AccessPolicy
google_access_context_manager_service_perimeter accesscontextmanager.googleapis.com/ServicePerimeter
google_apigee_environment_iam_binding apigee.googleapis.com/Environment
google_apigee_environment_iam_member apigee.googleapis.com/Environment
google_apigee_environment_iam_policy apigee.googleapis.com/Environment
google_bigquery_dataset bigquery.googleapis.com/Dataset
google_bigquery_dataset_iam_binding bigquery.googleapis.com/Dataset
google_bigquery_dataset_iam_member bigquery.googleapis.com/Dataset
google_bigquery_dataset_iam_policy bigquery.googleapis.com/Dataset
google_bigquery_table bigquery.googleapis.com/Table
google_bigquery_table_iam_binding bigquery.googleapis.com/Table
google_bigquery_table_iam_member bigquery.googleapis.com/Table
google_bigquery_table_iam_policy bigquery.googleapis.com/Table
google_bigtable_instance bigtableadmin.googleapis.com/Cluster, bigtableadmin.googleapis.com/Instance
google_binary_authorization_attestor_iam_binding binaryauthorization.googleapis.com/Attestor
google_binary_authorization_attestor_iam_member binaryauthorization.googleapis.com/Attestor
google_binary_authorization_attestor_iam_policy binaryauthorization.googleapis.com/Attestor
google_cloud_run_domain_mapping run.googleapis.com/DomainMapping
google_cloud_run_service run.googleapis.com/Service
google_cloud_run_service_iam_binding run.googleapis.com/Service
google_cloud_run_service_iam_member run.googleapis.com/Service
google_cloud_run_service_iam_policy run.googleapis.com/Service
google_cloudfunctions_function cloudfunctions.googleapis.com/CloudFunction
google_cloudfunctions_function_iam_binding cloudfunctions.googleapis.com/CloudFunction
google_cloudfunctions_function_iam_member cloudfunctions.googleapis.com/CloudFunction
google_cloudfunctions_function_iam_policy cloudfunctions.googleapis.com/CloudFunction
google_compute_address compute.googleapis.com/Address
google_compute_backend_service_iam_binding compute.googleapis.com/BackendService
google_compute_backend_service_iam_member compute.googleapis.com/BackendService
google_compute_backend_service_iam_policy compute.googleapis.com/BackendService
google_compute_disk compute.googleapis.com/Disk
google_compute_disk_iam_binding compute.googleapis.com/Disk
google_compute_disk_iam_member compute.googleapis.com/Disk
google_compute_disk_iam_policy compute.googleapis.com/Disk
google_compute_firewall compute.googleapis.com/Firewall
google_compute_forwarding_rule compute.googleapis.com/ForwardingRule
google_compute_global_address compute.googleapis.com/GlobalAddress
google_compute_global_forwarding_rule compute.googleapis.com/GlobalForwardingRule
google_compute_image_iam_binding compute.googleapis.com/Image
google_compute_image_iam_member compute.googleapis.com/Image
google_compute_image_iam_policy compute.googleapis.com/Image
google_compute_instance compute.googleapis.com/Instance
google_compute_instance_iam_binding compute.googleapis.com/Instance
google_compute_instance_iam_member compute.googleapis.com/Instance
google_compute_instance_iam_policy compute.googleapis.com/Instance
google_compute_network compute.googleapis.com/Network
google_compute_region_backend_service_iam_binding compute.googleapis.com/RegionBackendService
google_compute_region_backend_service_iam_member compute.googleapis.com/RegionBackendService
google_compute_region_backend_service_iam_policy compute.googleapis.com/RegionBackendService
google_compute_region_disk_iam_binding compute.googleapis.com/RegionDisk
google_compute_region_disk_iam_member compute.googleapis.com/RegionDisk
google_compute_region_disk_iam_policy compute.googleapis.com/RegionDisk
google_compute_security_policy compute.googleapis.com/SecurityPolicy
google_compute_snapshot compute.googleapis.com/Snapshot
google_compute_ssl_policy compute.googleapis.com/SslPolicy
google_compute_subnetwork compute.googleapis.com/Subnetwork
google_compute_subnetwork_iam_binding compute.googleapis.com/Subnetwork
google_compute_subnetwork_iam_member compute.googleapis.com/Subnetwork
google_compute_subnetwork_iam_policy compute.googleapis.com/Subnetwork
google_container_cluster container.googleapis.com/Cluster
google_container_node_pool container.googleapis.com/NodePool
google_data_catalog_entry_group_iam_binding datacatalog.googleapis.com/EntryGroup
google_data_catalog_entry_group_iam_member datacatalog.googleapis.com/EntryGroup
google_data_catalog_entry_group_iam_policy datacatalog.googleapis.com/EntryGroup
google_data_catalog_tag_template_iam_binding datacatalog.googleapis.com/TagTemplate
google_data_catalog_tag_template_iam_member datacatalog.googleapis.com/TagTemplate
google_data_catalog_tag_template_iam_policy datacatalog.googleapis.com/TagTemplate
google_dns_managed_zone dns.googleapis.com/ManagedZone
google_dns_policy dns.googleapis.com/Policy
google_endpoints_service_consumers_iam_binding servicemanagement.googleapis.com/ServiceConsumers
google_endpoints_service_consumers_iam_member servicemanagement.googleapis.com/ServiceConsumers
google_endpoints_service_consumers_iam_policy servicemanagement.googleapis.com/ServiceConsumers
google_endpoints_service_iam_binding servicemanagement.googleapis.com/Service
google_endpoints_service_iam_member servicemanagement.googleapis.com/Service
google_endpoints_service_iam_policy servicemanagement.googleapis.com/Service
google_filestore_instance file.googleapis.com/Instance
google_folder_iam_binding cloudresourcemanager.googleapis.com/Folder
google_folder_iam_member cloudresourcemanager.googleapis.com/Folder
google_folder_iam_policy cloudresourcemanager.googleapis.com/Folder
google_folder_organization_policy cloudresourcemanager.googleapis.com/Folder
google_healthcare_consent_store_iam_binding healthcare.googleapis.com/ConsentStore
google_healthcare_consent_store_iam_member healthcare.googleapis.com/ConsentStore
google_healthcare_consent_store_iam_policy healthcare.googleapis.com/ConsentStore
google_iap_tunnel_iam_binding iap.googleapis.com/Tunnel
google_iap_tunnel_iam_member iap.googleapis.com/Tunnel
google_iap_tunnel_iam_policy iap.googleapis.com/Tunnel
google_iap_tunnel_instance_iam_binding iap.googleapis.com/TunnelInstance
google_iap_tunnel_instance_iam_member iap.googleapis.com/TunnelInstance
google_iap_tunnel_instance_iam_policy iap.googleapis.com/TunnelInstance
google_iap_web_iam_binding iap.googleapis.com/Web
google_iap_web_iam_member iap.googleapis.com/Web
google_iap_web_iam_policy iap.googleapis.com/Web
google_kms_crypto_key cloudkms.googleapis.com/CryptoKey
google_kms_crypto_key_iam_binding cloudkms.googleapis.com/CryptoKey
google_kms_crypto_key_iam_member cloudkms.googleapis.com/CryptoKey
google_kms_crypto_key_iam_policy cloudkms.googleapis.com/CryptoKey
google_kms_key_ring cloudkms.googleapis.com/KeyRing
google_kms_key_ring_iam_binding cloudkms.googleapis.com/KeyRing
google_kms_key_ring_iam_member cloudkms.googleapis.com/KeyRing
google_kms_key_ring_iam_policy cloudkms.googleapis.com/KeyRing
google_monitoring_alert_policy monitoring.googleapis.com/AlertPolicy
google_monitoring_notification_channel monitoring.googleapis.com/NotificationChannel
google_notebooks_instance_iam_binding notebooks.googleapis.com/Instance
google_notebooks_instance_iam_member notebooks.googleapis.com/Instance
google_notebooks_instance_iam_policy notebooks.googleapis.com/Instance
google_notebooks_runtime_iam_binding notebooks.googleapis.com/Runtime
google_notebooks_runtime_iam_member notebooks.googleapis.com/Runtime
google_notebooks_runtime_iam_policy notebooks.googleapis.com/Runtime
google_organization_iam_binding cloudresourcemanager.googleapis.com/Organization
google_organization_iam_custom_role iam.googleapis.com/Role
google_organization_iam_member cloudresourcemanager.googleapis.com/Organization
google_organization_iam_policy cloudresourcemanager.googleapis.com/Organization
google_organization_policy cloudresourcemanager.googleapis.com/Organization
google_privateca_ca_pool_iam_binding privateca.googleapis.com/CaPool
google_privateca_ca_pool_iam_member privateca.googleapis.com/CaPool
google_privateca_ca_pool_iam_policy privateca.googleapis.com/CaPool
google_privateca_certificate_template_iam_binding privateca.googleapis.com/CertificateTemplate
google_privateca_certificate_template_iam_member privateca.googleapis.com/CertificateTemplate
google_privateca_certificate_template_iam_policy privateca.googleapis.com/CertificateTemplate
google_project cloudbilling.googleapis.com/ProjectBillingInfo, cloudresourcemanager.googleapis.com/Project
google_project_iam_binding cloudresourcemanager.googleapis.com/Project
google_project_iam_custom_role iam.googleapis.com/Role
google_project_iam_member cloudresourcemanager.googleapis.com/Project
google_project_iam_policy cloudresourcemanager.googleapis.com/Project
google_project_organization_policy cloudresourcemanager.googleapis.com/Project
google_project_service serviceusage.googleapis.com/Service
google_pubsub_lite_reservation pubsublite.googleapis.com/Reservation
google_pubsub_lite_subscription pubsublite.googleapis.com/Subscription
google_pubsub_lite_topic pubsublite.googleapis.com/Topic
google_pubsub_schema pubsub.googleapis.com/Schema
google_pubsub_subscription pubsub.googleapis.com/Subscription
google_pubsub_subscription_iam_binding pubsub.googleapis.com/Subscription
google_pubsub_subscription_iam_member pubsub.googleapis.com/Subscription
google_pubsub_subscription_iam_policy pubsub.googleapis.com/Subscription
google_pubsub_topic pubsub.googleapis.com/Topic
google_pubsub_topic_iam_binding pubsub.googleapis.com/Topic
google_pubsub_topic_iam_member pubsub.googleapis.com/Topic
google_pubsub_topic_iam_policy pubsub.googleapis.com/Topic
google_redis_instance redis.googleapis.com/Instance
google_secret_manager_secret_iam_binding secretmanager.googleapis.com/Secret
google_secret_manager_secret_iam_member secretmanager.googleapis.com/Secret
google_secret_manager_secret_iam_policy secretmanager.googleapis.com/Secret
google_spanner_database spanner.googleapis.com/Database
google_spanner_database_iam_binding spanner.googleapis.com/Database
google_spanner_database_iam_member spanner.googleapis.com/Database
google_spanner_database_iam_policy spanner.googleapis.com/Database
google_spanner_instance spanner.googleapis.com/Instance
google_spanner_instance_iam_binding spanner.googleapis.com/Instance
google_spanner_instance_iam_member spanner.googleapis.com/Instance
google_spanner_instance_iam_policy spanner.googleapis.com/Instance
google_sql_database sqladmin.googleapis.com/Database
google_sql_database_instance sqladmin.googleapis.com/Instance
google_storage_bucket storage.googleapis.com/Bucket
google_storage_bucket_iam_binding storage.googleapis.com/Bucket
google_storage_bucket_iam_member storage.googleapis.com/Bucket
google_storage_bucket_iam_policy storage.googleapis.com/Bucket
google_vpc_access_connector vpcaccess.googleapis.com/Connector