יצירת אילוצים של CAI

קל לארגן דפים בעזרת אוספים אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.

לפני שמתחילים

Constraint Framework

בשדה gcloud beta terraform vet פועלת מדיניות Constraint Framework, שמכילה אילוצים וגם תבניות אילוצים. ההבדל בין שניהם:

  • תבנית אילוצים דומה להצהרת פונקציה, היא מגדירה כלל ומאפשרת להשתמש במקורות קלט בתור משתנים.
  • אילוץ הוא קובץ שמפנה לתבנית אילוצים ומגדיר את הערכים שיהיו שם בשימוש.

נכסי CAI לעומת משאבי Terraform

נכסים של מאגר משאבי הענן (CAI) הם פורמט סטנדרטי לייצוא נתונים מ-Google שזמין למשאבים רבים של GCP. בדרך כלל נתוני CAI זמינים רק אחרי שיוצרים או מעדכנים משאבים. עם זאת, כשממירים שינויים במשאבי Terraform לנתונים של נכס CAI, אפשר להשתמש ב-gcloud beta terraform vet כדי לכתוב מדיניות אחת ולהשתמש בה גם כבדיקה מקדימה וגם כביקורת באמצעות הכלים התואמים.

הכלים התואמים

הכלים הבאים הם לא מוצרים רשמיים של Google ואנחנו לא תומכים בהם. עם זאת, יכול להיות שהם יתאימו לכללי מדיניות שייכתבו עבור gcloud beta terraform vet.

יצירה של תבנית אילוצים

לפני שאתם מפתחים את תבנית האילוצים, ודאו שהנכס שאתם רוצים לכתוב עבורו מדיניות נתמך על ידי מאגר משאבי הענן ועל ידי gcloud beta terraform vet.

1. איסוף נתונים לדוגמה

כדי לכתוב תבנית אילוצים יש צורך בנתונים לדוגמה שאפשר להסתמך עליהם. אילוצים המבוססים על CAI מסתמכים על נתונים של נכסי CAI. כדי לאסוף נתונים לדוגמה תצטרכו ליצור משאבים מהסוג המתאים ולייצא אותם כקובץ JSON. תוכלו להיעזר בהסבר שמופיע במדריך למתחילים ל-CAI.

דוגמה לייצוא קובץ JSON לכתובת ב-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"
      }
    }
  },
]

2. כתיבה בשפת Rego

אחרי שהנתונים לדוגמה מתקבלים, אפשר לכתוב את הלוגיקה של תבנית האילוצים ב-Rego. חייב להיות כלל violations ב-Rego. הנכס שנמצא בבדיקה זמין בתור input.review. הפרמטרים של האילוצים זמינים בתור input.parameters. לדוגמה, כדי לדרוש שלנכסים של compute.googleapis.com/Address יהיה addressType מורשה, צריך לכתוב:

# 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}
}

בחירת שם לתבנית האילוצים

בדוגמה הקודמת השתמשנו בשם GCPComputeAddressAddressTypeAllowlistConstraintV1. זהו מזהה מובהק של כל תבנית אילוצים. מומלץ לבחור שמות לפי ההנחיות הבאות:

  • פורמט כללי: GCP{resource}{feature}Constraint{version}. צריך להשתמש ב-CamelCase (כלומר, להשתמש באות גדולה בכל מילה חדשה).
  • באילוצים של משאב יחיד צריך להשתמש בשמות הקבוצות של gcloudעבור שמות המשאבים. לדוגמה, צריך לכתוב "compute" במקום "gce", ‏"sql" במקום "cloud-sql" ו-"container-cluster" במקום "gke".
  • אם התבנית חלה על יותר מסוג אחד של משאב, צריך להשמיט את החלק של המשאב ולכלול רק את המאפיין (לדוגמה: "GCPAddressTypeAllowlistConstraintV1")‏.
  • מספר הגרסה מורכב ממספר אחד בלבד, ולא לפי תבנית semver. כך למעשה כל גרסה של תבנית הופכת לתבנית ייחודית.

מומלץ לבחור שם לקובץ ה-Rego שמתאים לשם של תבנית האילוצים, אבל עם שימוש ב-snake_case. במילים אחרות, צריך להמיר את השם למילים נפרדות באותיות קטנות באמצעות _. בדוגמה הקודמת, השם המומלץ לקובץ הוא gcp_compute_address_address_type_allowlist_constraint_v1.rego.

3. בדיקת ה-Rego

תוכלו לבדוק את קוד ה-Rego באופן ידני בעזרת Rego Playground. הקפידו להשתמש בנתונים שלא מכילים מידע אישי רגיש.

אנחנו ממליצים לנסח בדיקות אוטומטיות. עליכם להכניס את נתוני הדגימה שאספתם אל validator/test/fixtures/<constraint filename>/assets/data.json ולציין אותם בקובץ הבדיקה, באופן הבא:

# 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
}

צריך להעביר את ה-Rego ואת הבדיקה לתיקייה validator שבספריית המדיניות שלכם.

4. הגדרת שלד של תבנית אילוצים

אחרי שיצרתם כלל Rego שנבדק ופועל, עליכם לארוז אותו כתבנית אילוצים. המדיניות Constraint Framework משתמשת ב-Kubernetes Custom Resource Definitions בתור הקונטיינר של ה-Rego במדיניות.

תבנית האילוצים גם מגדירה באמצעות הסכימה OpenAPI V3 באילו פרמטרים אפשר להשתמש כמקורות קלט מאילוצים.

שם השלד צריך להיות זהה לשם שהשתמשתם ב-Rego. הקפידו במיוחד על הדברים הבאים:

  • עליכם להשתמש באותו שם קובץ שבשימוש עבור ה-Rego. לדוגמה: gcp_compute_address_address_type_allowlist_constraint_v1.yaml
  • השדה spec.crd.spec.names.kind חייב להכיל את שם התבנית.
  • השדה metadata.name חייב להכיל את שם התבנית, אבל צריך להשתמש באותיות קטנות.

עליכם להציב את השלד של תבנית האילוצים ב-policies/templates.

בדוגמה הקודמת, זה יופיע כך:

# 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

5. הצבת ה-Rego בתוך שורה

עכשיו, לאחר הדוגמה הקודמת, הפריסה של הספריות נראית כך:

| 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

אם שכפלתם את מאגר ספריית המדיניות של Google, תוכלו להריץ את make build כדי לעדכן אוטומטית את תבניות האילוצים ב-policies/templates לפי ה-Rego שהוגדר ב-validator.

6. הגדרת אילוץ

האילוצים מכילים שלושה פרטים שנדרשים ל-gcloud beta terraform vet כדי לאכוף הפרות ולדווח עליהן כמו שצריך:

  • severity:‏ low,‏ medium או high
  • match:‏ פרמטרים שנועדו לקבוע אם האילוץ חל על משאב מסוים. אפשר להשתמש בפרמטרים הבאים להתאמה:
    • target: רשימת נתיבים לישויות אב שצריך לכלול באמצעות התאמה של glob-style.
    • exclude: (אופציונלי) רשימה של נתיבים לישויות אב שצריך להחריג באמצעות התאמה של glob-style.
  • parameters: ערכים לפרמטרים של הקלט של תבנית האילוצים.

הקפידו שהשדה kind יכלול את השם של תבנית האילוצים. מומלץ להגדיר שהשדה metadata.name יהיה שורה עם תיאור.

לדוגמה, כדי לאפשר רק כתובות מסוג INTERNAL באמצעות תבנית האילוצים מהדוגמה הקודמת, עליכם לכתוב:

# 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:
    target:
    - "**"
  parameters:
    allowed_address_types:
    - "INTERNAL"

דוגמאות להתאמות:

כלי להתאמת נתיבים לישויות אב תיאור
organizations/**‎ כל הארגונים
organizations/123/**‎ כל מה שבארגון 123
organizations/123/folders/**‎ כל מה שבתיקייה של ארגון 123
organizations/123/folders/456‎ כל מה שבתיקייה 456 של ארגון 123
organizations/123/folders/456/projects/789 כל מה שבפרויקט 789 בתיקייה 456 של ארגון 123

אם כתובת של משאב מסוים תהיה תואמת לערכים ברשימות target ו-exclude, היא תוחרג.

מגבלות

הנתונים של תוכנית Terraform מציגים הכי טוב את הייצוג הזמין של המצב בפועל אחרי ההחלה, אבל במקרים רבים ייתכן שהמצב לאחר ההחלה לא יהיה ידוע כי הוא מחושב בצד של השרת. במקרים כאלה, הנתונים לא יהיו זמינים גם בפורמט המומר של נכסי CAI.

משאבים נתמכים

אם אתם רוצים להוסיף תמיכה ב-gcloud beta terraform vet למשאב שלא מופיע ברשימה, תוכלו ליצור בקשה לשיפור ולשקול לתרום קוד.

רשימת המשאבים הנתמכים תלויה בגרסה של gcloud beta terraform vet שמותקנת. רשימת המשאבים הנתמכים:

משאב Terraform נכסים במאגר משאבי הענן
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