Prima di iniziare
Framework di vincoli
gcloud beta terraform vet
utilizza i criteri del Constraint Framework, costituiti da vincoli e modelli di vincolo. La
differenza tra i due è la seguente:
- Un modello di vincolo è simile a una dichiarazione di funzione: definisce una regola in Rego e, facoltativamente, accetta parametri di input.
- Un vincolo è un file che fa riferimento a un modello di vincolo e definisce i parametri di input da passare e le risorse coperte dal criterio.
In questo modo puoi evitare ripetizioni. Puoi scrivere un modello di vincolo con un criterio generico, quindi scrivere un numero qualsiasi di vincoli che forniscono parametri di input diversi o regole di corrispondenza delle risorse diverse.
Asset CAI e risorse Terraform
Le risorse di Cloud Asset Inventory sono un formato standard di esportazione dei dati di Google disponibile
per molte risorse Google Cloud.
In genere, i dati CAI sono disponibili solo dopo la creazione o l'aggiornamento di una risorsa.
Tuttavia, la conversione delle modifiche delle risorse Terraform in dati di asset CAI consente di scrivere un criterio una volta e di utilizzarlo sia prima dell'applicazione sia come controllo di revisione con strumenti compatibili.gcloud beta terraform vet
Strumenti compatibili
I seguenti strumenti non sono prodotti ufficiali Google e non sono supportati.
Tuttavia, potrebbero essere compatibili con i criteri scritti per gcloud beta terraform vet
:
Creare un modello di vincolo
Prima di sviluppare il modello di vincolo, verifica che l'asset per cui vuoi scrivere un criterio sia supportato sia da Cloud Asset Inventory sia da gcloud beta terraform vet
.
Per creare un modello di vincolo, svolgi i seguenti passaggi:
- Raccogli i dati di esempio.
- Scrivi Rego.
- Testa il tuo Rego.
- Configura uno scheletro del modello di vincolo.
- Inserisci la regola in linea.
- Configura un vincolo.
Raccogliere dati di esempio
Per scrivere un modello di vincolo, devi disporre di dati di esempio su cui operare. Le limitazioni basate su CAI operano sui dati delle risorse CAI. Raccogliere i dati di esempio creando risorse del tipo appropriato ed esportandole come JSON, come descritto nella guida introduttiva a CAI.
Ecco un esempio di esportazione JSON per un indirizzo di calcolo:
[
{
"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"
}
}
},
]
Rego di scrittura
Dopo aver ottenuto i dati di esempio, puoi scrivere la logica per il modello di vincolo
in
Rego.
Il tuo Rego deve avere una regola violations
. L'asset in fase di revisione è disponibile come input.review
. I parametri di vincolo sono disponibili come input.parameters
.
Ad esempio, per richiedere che gli asset compute.googleapis.com/Address
abbiano un valore addressType
consentito, scrivi:
# 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}
}
Assegna un nome al modello di vincolo
L'esempio precedente utilizza il nome
GCPComputeAddressAddressTypeAllowlistConstraintV1
. Si tratta di un identificatore univoco per ogni modello di vincolo. Ti consigliamo di seguire queste linee guida per la denominazione:
- Formato generale:
GCP{resource}{feature}Constraint{version}
. Utilizza il CamelCase. In altre parole, scrivi ogni nuova parola con la lettera maiuscola. - Per i vincoli relativi a una singola risorsa, segui i nomi dei gruppi gcloud per la denominazione delle risorse. Ad esempio, utilizza "compute" anziché "gce", "sql" anziché "cloud-sql" e "container-cluster" anziché "gke".
- Se un modello si applica a più di un tipo di risorsa, ometti la parte della risorsa e includi solo la funzionalità (ad es. "GCPAddressTypeAllowlistConstraintV1").
- Il numero di versione non segue la forma semver; è solo un singolo numero. In questo modo, ogni versione di un modello diventa un modello unico.
Ti consigliamo di utilizzare un nome per il file Rego che corrisponda al nome del
modello di vincolo, ma utilizzando la notazione snake_case. In altre parole, converti il nome in lettere minuscole e separa le parole con _
. Per l'esempio precedente, il nome file consigliato è gcp_compute_address_address_type_allowlist_constraint_v1.rego
Testa il tuo Rego
Puoi testare Rego manualmente con Rego Playground. Assicurati di utilizzare dati non sensibili.
Ti consigliamo di scrivere
test automatici.
Inserisci i dati di esempio raccolti in validator/test/fixtures/<constraint
filename>/assets/data.json
e fai riferimento a questi dati nel file di test come segue:
# 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
}
Inserisci il tuo Rego e il tuo test nella cartella validator
della raccolta di criteri.
Configurare uno scheletro del modello di vincolo
Dopo aver creato una regola Rego funzionante e testata, devi impacchettarla come modello di vincolo. Constraint Framework utilizza le definizioni delle risorse personalizzate Kubernetes come contenitore per il criterio Rego.
Il modello di vincolo definisce anche i parametri consentiti come input dei vincoli, utilizzando lo schema OpenAPI V3.
Utilizza lo stesso nome per lo scheletro che hai utilizzato per Rego. In particolare:
- Utilizza lo stesso nome file del tuo Rego. Esempio:
gcp_compute_address_address_type_allowlist_constraint_v1.yaml
spec.crd.spec.names.kind
deve contenere il nome del modellometadata.name
deve contenere il nome del modello, ma in minuscolo
Inserisci lo scheletro del modello di vincolo in policies/templates
.
Per l'esempio riportato sopra:
# 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
Inserisci il tuo Rego in linea
A questo punto, seguendo l'esempio precedente, il layout della directory sarà simile al seguente:
| 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 hai clonato il
repository della libreria di criteri fornita da Google,
puoi eseguire make build
per aggiornare automaticamente i modelli di vincoli in
policies/templates
con il Rego definito in validator
.
Configurare un vincolo
I vincoli contengono tre informazioni di cui gcloud beta terraform vet
ha bisogno per applicare e segnalare correttamente le violazioni:
severity
:low
,medium
ohigh
match
: parametri per determinare se una limitazione si applica a una determinata risorsa. Sono supportati i seguenti parametri di corrispondenza:ancestries
: un elenco di percorsi di ascendenza da includere utilizzando la corrispondenza di tipo globexcludedAncestries
: (Facoltativo) Un elenco di percorsi di ascendenza da escludere utilizzando la corrispondenza in stile glob.
parameters
: valori per i parametri di input del modello di vincolo.
Assicurati che kind
contenga il nome del modello di vincolo. Ti consigliamo di impostare metadata.name
su uno slug descrittivo.
Ad esempio, per consentire solo tipi di indirizzi INTERNAL
utilizzando il modello di vincolo dell'esempio precedente, scrivi:
# 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"
Esempi di corrispondenza:
Corrispondenza del percorso di appartenenza | Descrizione |
---|---|
organizations/** | Tutte le organizzazioni |
organizations/123/** | Tutto nell'organizzazione 123 |
organizations/123/folders/** | Tutto ciò che si trova nell'organizzazione 123 in una cartella |
organizations/123/folders/456 | Tutti i contenuti della cartella 456 nell'organizzazione 123 |
organizations/123/folders/456/projects/789 | Tutto nel progetto 789 nella cartella 456 nell'organizzazione 123 |
Se l'indirizzo di una risorsa corrisponde ai valori in ancestries
e excludedAncestries
,
viene escluso.
Limitazioni
I dati del piano Terraform forniscono la migliore rappresentazione disponibile dello stato effettivo dopo l'applicazione. Tuttavia, in molti casi, lo stato dopo l'applicazione potrebbe non essere noto perché viene calcolato lato server. In questi casi, i dati non sono disponibili nemmeno nelle risorse CAI convertite.
La creazione di percorsi di ascendenza CAI fa parte della procedura di convalida dei criteri. Utilizza il progetto predefinito fornito per aggirare gli ID progetto sconosciuti. Nel caso in cui non venga fornito un progetto predefinito, il percorso dell'ascendenza predefinito è organizations/unknown
.
Puoi non consentire l'ascendenza sconosciuta aggiungendo il seguente vincolo:
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: {}
Risorse supportate
Se vuoi che gcloud beta terraform vet
aggiunga il supporto per una risorsa non presente in questo elenco, apri una richiesta di miglioramento e valuta la possibilità di contribuire con il codice.
L'elenco delle risorse supportate dipende dalla versione di gcloud beta terraform vet
installata. Di seguito è riportato l'elenco attuale delle risorse supportate:
Risorsa Terraform | Asset di 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 |