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:
- Recolha dados de amostra.
- Escreva Rego.
- Teste o Rego.
- Configure um esqueleto de modelo de restrição.
- Incorporar o Rego.
- 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 modelometadata.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
ouhigh
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 globexcludedAncestries
: (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 vet
adicionar 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 |