Antes de começar
Framework de restrição
gcloud beta terraform vet
usa políticas do Constraint
Framework, que consistem em restrições e modelos de restrição. A
diferença entre os dois é a seguinte:
- Um modelo de restrição é como uma declaração de função, ele define uma regra em Rego e, opcionalmente, aceita parâmetros de entrada.
- Uma restrição é um arquivo que faz referência a um modelo de restrição e define os parâmetros de entrada a serem transmitidos a ele e aos recursos cobertos pela política.
Isso evita repetições. É possível gravar um modelo de restrição com uma política genérica e, em seguida, gravar qualquer número de restrições que forneçam diferentes parâmetros de entrada ou regras de correspondência de recursos distintas.
Recursos do CAI x recursos do Terraform
Os recursos de Inventário de recursos do Cloud são um formato padrão de exportação de dados do Google,
disponível
para muitos recursos do Google Cloud.
Os dados de CAI normalmente só estão disponíveis depois que um recurso é criado ou atualizado.
No entanto, ao converter as alterações dos recursos do Terraform nos dados do recurso CAI,
o gcloud beta terraform vet
permite gravar uma política uma vez e usá-la antes da aplicação e
como uma verificação de auditoria com ferramentas compatíveis.
Ferramentas compatíveis
As seguintes ferramentas não são produtos oficiais do Google e não são compatíveis.
No entanto, eles podem ser compatíveis com as políticas criadas para gcloud beta terraform vet
:
Criar um modelo de restrição
Antes de desenvolver seu modelo de restrição, verifique se o recurso
em que você quer gravar uma política é compatível com o
Inventário de recursos do Cloud
e com gcloud beta terraform vet
..
A criação de um modelo de restrição é o seguinte:
- Coletar dados de amostra
- Gravar o Rego.
- Testar o Rego.
- Configurar um esqueleto de modelo de restrição.
- Colocar o Rego em linha.
- Configurar uma restrição.
Coletar dados de amostra
Para escrever um modelo de restrição, é necessário ter dados de amostra para operar. As restrições baseadas em CAI operam em dados de CAI. Colete dados de amostra criando recursos do tipo apropriado e exportando-os como JSON, conforme descrito no Guia de início rápido da CAI.
Veja um exemplo de exportação JSON para um endereço do 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"
}
}
},
]
Gravar o Rego
Após os dados de amostra, escreva a lógica do modelo de restrição
em Rego.
O Rego precisa ter uma regra violations
. O recurso que está sendo revisado 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}
}
Nomear seu modelo de restrição
O exemplo anterior usa o nome GCPComputeAddressAddressTypeAllowlistConstraintV1
. Esse é um identificador exclusivo para cada modelo de restrição. Recomendamos seguir
estas diretrizes de nomenclatura:
- Formato geral:
GCP{resource}{feature}Constraint{version}
Use o CamelCase. Em outras palavras, coloque cada palavra nova em letra maiúscula. - Para restrições de recursos únicos, siga os nomes de grupos do 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 de um tipo de recurso, omita a parte dele e inclua apenas o recurso (por exemplo: "GCPAddressTypeAllowlistConstraintV1").
- O número da versão não segue o formulário semver. é apenas um número. Isso torna cada versão de um modelo único.
Recomendamos o uso de um nome para seu arquivo Rego que corresponda ao nome do
modelo de restrição, mas usando snake_case. Em outras palavras, converta o nome em
letras minúsculas com _
. No exemplo anterior, o nome de arquivo recomendado
é gcp_compute_address_address_type_allowlist_constraint_v1.rego
Testar o Rego
É possível testar o Rego manualmente com o Rego Playground. Use dados não confidenciais.
Recomendamos a criação de testes automatizados.
Coloque os dados de amostra coletados em validator/test/fixtures/<constraint
filename>/assets/data.json
e referencie-os no arquivo de teste desta 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
da biblioteca de políticas.
Configurar um esqueleto de modelo de restrição
Depois de criar uma regra do Rego em funcionamento e testada, é necessário empacotá-la como um modelo de restrição. O Constraint Framework usa as definições de recursos personalizados do Kubernetes como o contêiner do Rego da política.
O modelo de restrição também define quais parâmetros são permitidos como entradas de restrições, usando o esquema OpenAPI V3.
Use o mesmo nome do esqueleto que você usou para o Rego. Especificamente:
- Use o mesmo nome de arquivo que você tem no Rego. Exemplo:
gcp_compute_address_address_type_allowlist_constraint_v1.yaml
spec.crd.spec.names.kind
precisa conter o nome do modelometadata.name
precisa conter o nome do modelo, mas com 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
Colocar o Rego em linha
Neste momento, seguindo o exemplo anterior, seu layout de diretório é semelhante a este:
| 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 você clonou o repositório de biblioteca de políticas fornecido pelo Google,
pode executar make build
para atualizar automaticamente seus modelos de restrição em
policies/templates
com o Rego definido em validator
Configurar uma restrição
As restrições contêm três informações que o gcloud beta terraform vet
precisa
para aplicar e denunciar violações corretamente:
severity
:low
,medium
ouhigh
match
: parâmetros para determinar se uma restrição se aplica a um determinado recurso. Os seguintes parâmetros de correspondência são compatíveis:ancestries
: uma lista de caminhos de ancestral a serem incluídos usando a correspondência no estilo globexcludedAncestries
: (opcional) uma lista de caminhos de ancestral a serem excluídos usando a correspondência em estilo glob.
parameters
: valores para os parâmetros de entrada do modelo de restrição.
Verifique se kind
contém o nome do modelo de restrição. Recomendamos definir
metadata.name
como um slug descritivo.
Por exemplo, para permitir apenas os tipos de endereços INTERNAL
usando o modelo de restrição
de 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 caminho ancestral | Descrição |
---|---|
organizations/** | Todas as organizações |
organizations/123/** | Tudo na organização 123 |
organizations/123/folders/** | Tudo na organização 123 que está em uma pasta |
organizations/123/folders/456 | Tudo na pasta 456 da organização 123 |
organizations/123/folders/456/projects/789 | Tudo no projeto 789 na pasta 456 da organização 123 |
Se um endereço de recurso corresponder a valores em ancestries
e excludedAncestries
, ele
será excluído.
Limitações
Os dados do plano do Terraform fornecem 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 porque é calculado no lado do servidor. Nesses casos, os dados também não estão disponíveis nos recursos CAI convertidos.
A criação de caminhos de ancestralidade do CAI faz parte do processo de validação das políticas. Ele
usa o projeto padrão fornecido para contornar IDs de projetos desconhecidos. Se
um projeto padrão não for fornecido, o caminho de ancestralidade padrão será
organizations/unknown
.
É possível proibir a ancestralidade 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 você quiser que gcloud beta terraform vet
adicione compatibilidade com um recurso que não está na lista, abra uma solicitação de melhoria e considere colaborar com o código.
A lista de recursos compatíveis depende da versão de gcloud beta terraform vet
instalada. Veja a lista atual de recursos compatíveis:
Recurso do Terraform | Recursos do inventário de recursos do 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 |