Prima di iniziare
Framework dei vincoli
gcloud beta terraform vet
utilizza i criteri del framework dei vincoli, che consistono in vincoli e modelli di vincolo. La differenza tra i due è la seguente:
- Un modello di vincolo è come 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 al modello e le risorse coperte dal criterio.
In questo modo eviterai le 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.
Confronto tra asset CAI e risorse Terraform
Gli asset Cloud Asset Inventory sono un formato standard di esportazione dei dati di Google, disponibile per molte risorse di Google Cloud.
I dati CAI sono generalmente disponibili solo dopo che una risorsa è stata creata o aggiornata.
Tuttavia, convertendo le modifiche alle risorse Terraform in dati degli asset CAI, gcloud beta terraform vet
ti consente di scrivere un criterio una sola volta e di utilizzarlo sia prima dell'applicazione sia come controllo di controllo con strumenti compatibili.
Strumenti compatibili
I seguenti strumenti non sono prodotti Google ufficiali e non sono supportati.
Tuttavia, potrebbero essere compatibili con i criteri scritti per gcloud beta terraform vet
:
Crea un modello di vincolo
Prima di sviluppare il tuo 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:
- Raccogli dati di esempio.
- Scrivi Rego.
- Testa il tuo Rego.
- Configura la bozza di un modello di vincolo.
- Rego in linea.
- Configura un vincolo.
Raccogliere dati di esempio
Per scrivere un modello di vincolo, devi disporre di dati di esempio su cui operare. I vincoli basati su CAI operano sui dati degli asset CAI. Raccogli dati di esempio creando risorse del tipo appropriato ed esportandole in formato JSON, come descritto nella guida rapida di CAI.
Ecco un esempio di esportazione JSON per un indirizzo 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"
}
}
},
]
Scrivi Rego
Dopo aver ottenuto i dati di esempio, puoi scrivere la logica del modello di vincolo in Rego.
Rego deve avere una regola violations
. La risorsa esaminata è disponibile come input.review
. I parametri del vincolo sono disponibili come input.parameters
.
Ad esempio, per richiedere che gli asset compute.googleapis.com/Address
abbiano un
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 ciascun modello di vincolo. Ti consigliamo di seguire queste linee guida per l'assegnazione dei nomi:
- Formato generale:
GCP{resource}{feature}Constraint{version}
. Utilizza CamelCase. In altre parole, utilizza lettere maiuscole per ogni nuova parola. - 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ù tipi di risorsa, ometti la parte della risorsa e includi solo la funzionalità (esempio: "GCPAddressTypeAllowlistConstraintV1").
- Il numero di versione non segue il formato di server: è solo un numero singolo. In questo modo, ogni versione di un modello diventa un modello unico.
Ti consigliamo di utilizzare per il file Rego un nome che corrisponda al nome del modello di vincolo, ma utilizzando snake_case. In altre parole, converti il nome in
parole separate in minuscolo con _
. Per l'esempio precedente, il nome file
consigliato è gcp_compute_address_address_type_allowlist_constraint_v1.rego
Testa 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 in questo modo:
# 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 Rego e il test nella cartella validator
della tua libreria di criteri.
Configura la struttura di un modello di vincolo
Dopo aver creato una regola Rego funzionante e testata, devi pacchettizzarla come modello di vincolo. Il framework dei vincoli utilizza le definizioni di risorse personalizzate di Kubernetes come container per il criterio Rego.
Il modello di vincolo definisce anche i parametri consentiti come input dei vincoli, utilizzando lo schema OpenAPI V3.
Usa lo scheletro utilizzato per il Rego. In particolare:
- Utilizza lo stesso nome file utilizzato per 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
Posiziona lo scheletro del modello di vincolo in policies/templates
.
Nell'esempio precedente:
# 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
Incorpora il Rego
A questo punto, seguendo l'esempio precedente, il layout della directory è simile a questo:
| 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 policy-library fornito da Google,
puoi eseguire make build
per aggiornare automaticamente i tuoi modelli di vincolo in
policies/templates
con il Rego definito in validator
.
Configura un vincolo
I vincoli contengono tre informazioni necessarie a gcloud beta terraform vet
per far rispettare e segnalare correttamente le violazioni:
severity
:low
,medium
ohigh
match
: parametri per determinare se un vincolo si applica a una determinata risorsa. Sono supportati i seguenti parametri di corrispondenza:ancestries
: un elenco di percorsi di discendenza da includere utilizzando le corrispondenze di tipo globexcludedAncestries
: (facoltativo) un elenco di percorsi di discendenza da escludere utilizzando la corrispondenza di stile glob.
parameters
: valori dei parametri di input del modello di vincolo.
Assicurati che kind
contenga il nome del modello di vincolo. Ti consigliamo di impostare metadata.name
con uno slug descrittivo.
Ad esempio, per consentire solo INTERNAL
tipi di indirizzo utilizzando il precedente modello di vincolo di esempio, 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 percorso di discendenza | Description |
---|---|
organizations/** | Tutte le organizzazioni |
organizations/123/** | Tutte le funzionalità dell'organizzazione 123 |
organizations/123/folders/** | Tutti gli elementi dell'organizzazione 123 presenti in una cartella |
organizations/123/folders/456 | Tutto nella cartella 456 nell'organizzazione 123 |
organizations/123/folders/456/projects/789 | Tutto nel progetto 789 nella cartella 456 nell'organizzazione 123 |
Se un indirizzo della risorsa corrisponde ai valori in ancestries
e excludedAncestries
, viene escluso.
Limitazioni
I dati del piano Terraform offrono 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 sul lato server. In questi casi, i dati non sono disponibili nemmeno negli asset CAI convertiti.
La creazione di percorsi di discendenza CAI fa parte del processo 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 di discendenza è impostato su organizations/unknown
per impostazione predefinita.
Puoi impedire la discendenza 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 che non è in questo elenco, apri una richiesta di miglioramento e valuta la possibilità di aggiungere 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 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 |