Crie restrições de CAI

Antes de começar

Framework de restrições

gcloud beta terraform vet usa políticas do Constraint Framework, que consistem em restrições e modelos de restrições. A diferença entre os dois é a seguinte:

  • Um modelo de restrição é como uma declaração de função; define uma regra em Rego e, opcionalmente, usa parâmetros de entrada.
  • Uma restrição é um ficheiro que faz referência a um modelo de restrição e define os parâmetros de entrada a transmitir ao mesmo, bem como os recursos abrangidos pela política.

Isto permite-lhe evitar a repetição. Pode escrever um modelo de restrição com uma política genérica e, em seguida, escrever qualquer número de restrições que forneçam diferentes parâmetros de entrada ou regras de correspondência de recursos diferentes.

Recursos da CAI vs. recursos do Terraform

Os recursos do Cloud Asset Inventory são um formato de exportação de dados da Google padrão que está disponível para muitos Google Cloud recursos. Normalmente, os dados da CAI só estão disponíveis depois de um recurso ter sido criado ou atualizado. No entanto, ao converter as alterações de recursos do Terraform em dados de recursos do CAI, o gcloud beta terraform vet permite-lhe escrever uma política uma vez e usá-la antes de aplicar e como uma verificação de auditoria com ferramentas compatíveis.

Ferramentas compatíveis

As seguintes ferramentas não são produtos oficiais da Google e não são suportadas. No entanto, podem ser compatíveis com políticas escritas para gcloud beta terraform vet:

Crie um modelo de restrição

Antes de desenvolver o modelo de restrição, verifique se o recurso para o qual quer escrever uma política é suportado pelo inventário de recursos da nuvem e pelo gcloud beta terraform vet.

A criação de um modelo de restrição requer os seguintes passos:

  1. Recolha dados de amostra.
  2. Escreva Rego.
  3. Teste o Rego.
  4. Configure um esqueleto de modelo de restrição.
  5. Incorporar o Rego.
  6. Configure uma restrição.

Recolha dados de amostra

Para escrever um modelo de restrição, tem de ter dados de exemplo para operar. As restrições baseadas na CAI operam nos dados de recursos da CAI. Recolha dados de amostra criando recursos do tipo adequado e exportando esses recursos como JSON, conforme descrito no início rápido da CAI.

Segue-se um exemplo de exportação JSON para um endereço de cálculo:

[
  {
    "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"
      }
    }
  },
]

Write Rego

Depois de ter dados de exemplo, pode escrever a lógica para o modelo de restrição em Rego. O seu Rego tem de ter uma regra violations. O recurso que está a ser revisto está disponível como input.review. Os parâmetros de restrição estão disponíveis como input.parameters. Por exemplo, para exigir que os recursos compute.googleapis.com/Address tenham um addressType permitido, escreva:

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

Atribua um nome ao modelo de restrição

O exemplo anterior usa o nome GCPComputeAddressAddressTypeAllowlistConstraintV1. Este valor é um identificador exclusivo para cada modelo de restrição. Recomendamos que siga estas diretrizes de nomenclatura:

  • Formato geral: GCP{resource}{feature}Constraint{version}. Use CamelCase. (Por outras palavras, use maiúsculas em cada nova palavra.)
  • Para restrições de recursos únicos, siga os nomes dos grupos gcloud para a nomenclatura de recursos. Por exemplo, use "compute" em vez de "gce", "sql" em vez de "cloud-sql" e "container-cluster" em vez de "gke".
  • Se um modelo se aplicar a mais do que um tipo de recurso, omita a parte do recurso e inclua apenas a funcionalidade (exemplo: "GCPAddressTypeAllowlistConstraintV1").
  • O número da versão não segue o formato semver. É apenas um único número. Isto torna efetivamente cada versão de um modelo num modelo único.

Recomendamos que use um nome para o ficheiro Rego que corresponda ao nome do modelo de restrição, mas que use snake_case. Por outras palavras, converta o nome em letras minúsculas e separe as palavras com _. Para o exemplo anterior, o nome do ficheiro recomendado é gcp_compute_address_address_type_allowlist_constraint_v1.rego

Teste o seu Rego

Pode testar o Rego manualmente com o Rego Playground. Certifique-se de que usa dados não confidenciais.

Recomendamos que escreva testes automatizados. Coloque os dados de amostra recolhidos em validator/test/fixtures/<constraint filename>/assets/data.json e faça referência aos mesmos no ficheiro de teste da seguinte forma:

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

Coloque o Rego e o teste na pasta validator na biblioteca de políticas.

Configure um esqueleto de modelo de restrição

Depois de ter uma regra Rego funcional e testada, tem de a agrupar como um modelo de restrição. A framework de restrições usa definições de recursos personalizados do Kubernetes como o contentor para a política Rego.

O modelo de restrição também define que parâmetros são permitidos como entradas de restrições, usando o esquema OpenAPI V3.

Use o mesmo nome para o esqueleto que usou para o Rego. Concretamente:

  • Use o mesmo nome de ficheiro que usou para o Rego. Exemplo: gcp_compute_address_address_type_allowlist_constraint_v1.yaml
  • spec.crd.spec.names.kind tem de conter o nome do modelo
  • metadata.name tem de conter o nome do modelo, mas em letras minúsculas

Coloque o esqueleto do modelo de restrição em policies/templates.

Para o exemplo acima:

# 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

Incorporar o seu Rego

Neste ponto, seguindo o exemplo anterior, a disposição do diretório tem o seguinte aspeto:

| 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

Se clonou o repositório da biblioteca de políticas fornecido pela Google, pode executar make build para atualizar automaticamente os modelos de restrições em policies/templates com o Rego definido em validator.

Configure uma restrição

As restrições contêm três informações que o gcloud beta terraform vet precisa para aplicar e comunicar violações corretamente:

  • severity: low, medium ou high
  • match: parâmetros para determinar se uma restrição se aplica a um recurso específico. Os seguintes parâmetros de correspondência são suportados:
    • ancestries: uma lista de caminhos de ascendência a incluir através da correspondência no estilo glob
    • excludedAncestries: (Opcional) Uma lista de caminhos de hierarquia a excluir usando a correspondência no estilo glob.
  • parameters: valores dos parâmetros de entrada do modelo de restrição.

Certifique-se de que kind contém o nome do modelo de restrição. Recomendamos que defina metadata.name como um slug descritivo.

Por exemplo, para permitir apenas tipos de endereços INTERNAL usando o modelo de restrição do exemplo anterior, escreva:

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

Exemplos de correspondência:

Correspondência de caminhos de ascendência Descrição
organizations/** Todas as entidades
organizations/123/** Tudo na organização 123
organizations/123/folders/** Tudo na organização 123 que esteja numa pasta
organizations/123/folders/456 Tudo na pasta 456 na organização 123
organizations/123/folders/456/projects/789 Tudo no projeto 789 na pasta 456 na organização 123

Se um endereço de recurso corresponder aos valores em ancestries e excludedAncestries, é excluído.

Limitações

Os dados do plano do Terraform oferecem a melhor representação disponível do estado real após a aplicação. No entanto, em muitos casos, o estado após a aplicação pode não ser conhecido, uma vez que é calculado no lado do servidor. Nestes casos, os dados também não estão disponíveis nos recursos da IA convertidos.

A criação de caminhos de ascendência da CAI faz parte do processo de validação de políticas. Usa o projeto predefinido fornecido para contornar IDs de projetos desconhecidos. No caso em que não é fornecido um projeto predefinido, o caminho de hierarquia é predefinido como organizations/unknown.

Pode não permitir a ascendência desconhecida adicionando a seguinte restrição:

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: {}

Recursos suportados

Se quiser gcloud beta terraform vetadicionar suporte para um recurso que não esteja nesta lista, abra um pedido de melhoria e considere contribuir com código.

A lista de recursos suportados depende da versão do gcloud beta terraform vet instalada. Segue-se a lista atual de recursos suportados:

Recurso do Terraform Recursos do Cloud Asset Inventory
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