Avant de commencer
Framework de contrainte
gcloud beta terraform vet
utilise les règles du framework de contrainte, qui sont constituées de contraintes et de modèles de contrainte. La différence entre les deux est la suivante :
- Un modèle de contrainte est semblable à une déclaration de fonction : il définit une règle et accepte éventuellement des variables en tant qu'entrées.
- Une contrainte est un fichier qui fait référence à un modèle de contrainte et définit les valeurs à utiliser avec celui-ci.
Éléments CAI et ressources Terraform
Les éléments d'inventaire des éléments cloud constituent un format standard d'exportation de données Google disponible pour de nombreuses ressources GCP.
Les données CAI ne sont généralement disponibles qu'après la création ou la mise à jour d'une ressource.
Toutefois, en convertissant les modifications de ressources Terraform en données d'éléments CAI, gcloud beta terraform vet
vous permet d'écrire une stratégie une fois et de l'utiliser avant l'application et en tant que vérification d'audit avec des outils compatibles.
Outils compatibles
Les outils suivants ne sont pas des produits Google officiels et ne sont pas compatibles.
Cependant, ils peuvent être compatibles avec des règles écrites pour gcloud beta terraform vet
.
Créer un modèle de contrainte
Avant de développer votre modèle de contrainte, vérifiez que l'élément pour lequel vous souhaitez écrire une règle est compatible avec Cloud Asset Inventory et gcloud beta terraform vet
.
1. Collecter des exemples de données
Pour écrire un modèle de contrainte, vous devez disposer d'exemples de données à utiliser. Les contraintes basées sur CAI fonctionnent sur des données d'éléments CAI. Collectez des exemples de données en créant des ressources du type approprié et en les exportant au format JSON, comme décrit dans le guide de démarrage rapide de CAI.
Voici un exemple d'exportation au format JSON pour une adresse de calcul:
[
{
"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"
}
}
},
]
2. Écrire dans Rego
Une fois que vous disposez d'exemples de données, vous pouvez écrire la logique de votre modèle de contrainte dans Rego.
Votre Rego doit être associé à une règle violations
. L'élément en cours d'examen est disponible sous la forme input.review
. Les paramètres de contrainte sont disponibles sous la forme input.parameters
.
Par exemple, pour exiger que les éléments compute.googleapis.com/Address
aient un addressType
autorisé, écrivez:
# 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}
}
Attribuer un nom à votre modèle de contrainte
L'exemple précédent utilise le nom GCPComputeAddressAddressTypeAllowlistConstraintV1
.
Il s'agit d'un identifiant unique pour chaque modèle de contrainte. Nous vous recommandons de suivre ces consignes sur l'attribution de noms :
- Format général :
GCP{resource}{feature}Constraint{version}
. Utilisez CamelCase. (En d'autres termes, utilisez une majuscule pour chaque nouveau mot.) - Pour les contraintes de ressource unique, suivez les noms de groupe gcloud pour la dénomination de ressources. Par exemple, utilisez "compute" au lieu de "gce", "sql" au lieu de "cloud-sql" et "container-cluster" au lieu de "gke".
- Si un modèle s'applique à plusieurs types de ressources, omettez la partie ressource et n'incluez que la caractéristique (exemple: "GCPAddressTypeAllowlistConstraintV1").
- Le numéro de version ne suit pas le format semver. C'est un nombre unique. Ainsi, chaque version d'un modèle est unique.
Nous vous recommandons d'utiliser un nom pour votre fichier rego qui correspond au nom du modèle de contrainte, mais en utilisant snake_case. En d'autres termes, convertissez le nom en mots distincts en minuscules avec _
. Pour l'exemple précédent, le nom de fichier recommandé est gcp_compute_address_address_type_allowlist_constraint_v1.rego
.
3. Tester votre Rego
Vous pouvez tester votre Rego manuellement avec Rego Playground. Veillez à utiliser des données non sensibles.
Nous vous recommandons d'écrire des tests automatisés.
Placez les exemples de données collectés dans validator/test/fixtures/<constraint filename>/assets/data.json
et référencez-les dans votre fichier de test comme suit:
# 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
}
Placez votre Rego et votre test dans le dossier validator
de votre bibliothèque de règles.
4. Configurer le squelette d'un modèle de contrainte
Une fois que vous disposez d'une règle Rego opérationnelle et testée, vous devez l'empaqueter en tant que modèle de contrainte. Le framework des contraintes utilise les définitions de ressources personnalisées Kubernetes en tant que conteneur pour la règle Rego.
Le modèle de contrainte définit également les paramètres qui sont autorisés en tant qu'entrées de contraintes, à l'aide du schéma OpenAPI V3.
Utilisez le même nom pour le squelette que celui que vous avez utilisé pour votre Rego. En particulier :
- Utilisez le même nom de fichier que pour votre rego. Exemple :
gcp_compute_address_address_type_allowlist_constraint_v1.yaml
spec.crd.spec.names.kind
doit contenir le nom du modèlemetadata.name
doit contenir le nom du modèle, mais en minuscules.
Placez le squelette de modèle de contrainte dans policies/templates
.
Pour l'exemple ci-dessus:
# 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
5. Intégrer votre Rego
À ce stade, après l'exemple précédent, la disposition de votre répertoire ressemble à ceci:
| 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
Si vous avez cloné leDépôt de bibliothèques de règles fourni par Google, vous pouvez exécutermake build
pour mettre à jour automatiquement vos modèles de contraintes dans policies/templates
avec le rego défini dans le fichiervalidator
.
6. Configurer une contrainte
Les contraintes contiennent trois informations que gcloud beta terraform vet
doit appliquer et signaler correctement les violations:
severity
:low
,medium
ouhigh
.match
: paramètres permettant de déterminer si une contrainte s'applique à une ressource particulière. Les paramètres de correspondance suivants sont acceptés :target
: liste des chemins d'accès ancêtres à inclure à l'aide de la mise en correspondance de style globexclude
(facultatif) : liste des chemins d'accès ancêtres à exclure à l'aide de la correspondance de style glob.
parameters
: valeurs des paramètres d'entrée du modèle de contrainte.
Assurez-vous que kind
contient le nom du modèle de contrainte. Nous vous recommandons de définir metadata.name
sur un slug descriptif.
Par exemple, pour n'autoriser que les types d'adresses INTERNAL
à l'aide de l'exemple de modèle de contrainte précédent, écrivez:
# 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:
target:
- "**"
parameters:
allowed_address_types:
- "INTERNAL"
Exemples de correspondance :
Outil de mise en correspondance des chemins d'accès ancêtres | Description |
---|---|
organizations/** | Toutes les organisations |
organizations/123/** | Tous les éléments de l'organisation 123 |
organizations/123/folders/** | Tous les éléments d'un dossier de l'organisation 123 |
organizations/123/folders/456 | Tous les éléments du dossier 456 de l'organisation 123 |
organizations/123/folders/456/projects/789 | Tous les éléments du projet 789 dans le dossier 456 de l'organisation 123 |
Si une adresse de ressource correspond aux valeurs de target
et exclude
, elle est exclue.
Limites
Les données du plan Terraform fournissent la meilleure représentation disponible de l'état réel après application. Toutefois, dans de nombreux cas, l'état après l'application peut ne pas être connu, car il est calculé côté serveur. Dans ces cas, les données ne sont pas non plus disponibles dans les éléments CAI convertis.
Ressources compatibles
Si vous souhaitez que gcloud beta terraform vet
soit compatible avec une ressource qui ne figure pas dans cette liste, ouvrez une demande d'amélioration ; vous pouvez si vous le souhaitez contribuer à la création du code.
La liste des ressources compatibles dépend de la version de gcloud beta terraform vet
installée. Voici la liste actuelle des ressources acceptées :
Ressource Terraform | Éléments de l'inventaire des éléments 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 |