Vorbereitung
Einschränkungs-Framework
gcloud beta terraform vet
verwendet Constraint Framework-Richtlinien, die aus Einschränkungen und Einschränkungsvorlagen bestehen. So unterscheiden sich die beiden:
- Eine Einschränkungsvorlage ist wie eine Funktionsdeklaration. Sie definiert eine Regel in Rego und kann optional Eingabeparameter verwenden.
- Eine Einschränkung ist eine Datei, die auf eine Einschränkungsvorlage verweist und die Eingabeparameter definiert, die an sie und die von der Richtlinie abgedeckten Ressourcen übergeben werden.
Damit können Sie Wiederholungen vermeiden. Sie können eine Einschränkungsvorlage mit einer allgemeinen Richtlinie erstellen und dann eine beliebige Anzahl von Einschränkungen schreiben, die unterschiedliche Eingabeparameter oder unterschiedliche Regeln für den Ressourcenabgleich enthalten.
Einschränkungsvorlage erstellen
So erstellen Sie eine Einschränkungsvorlage:
- Erfassen Sie Beispieldaten.
- Schreiben Sie Rego.
- Testen Sie Ihr Rego.
- Richten Sie eine Basis-Einschränkungsvorlage ein.
- Binden Sie Ihr Rego ein.
- Richten Sie eine Einschränkung ein.
Beispieldaten erfassen
Um eine Einschränkungsvorlage schreiben zu können, benötigen Sie Beispieldaten. Terraform-basierte Einschränkungen arbeiten mit Daten zu Ressourcenänderungen, die aus dem Schlüssel resource_changes
von Terraform-Plan JSON stammen.
Ihre JSON-Datei könnte beispielsweise so aussehen:
// tfplan.json
{
"format_version": "0.2",
"terraform_version": "1.0.10",
"resource_changes": [
{
"address": "google_compute_address.internal_with_subnet_and_address",
"mode": "managed",
"type": "google_compute_address",
"name": "internal_with_subnet_and_address",
"provider_name": "registry.terraform.io/hashicorp/google",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"address": "10.0.42.42",
"address_type": "INTERNAL",
"description": null,
"name": "my-internal-address",
"network": null,
"prefix_length": null,
"region": "us-central1",
"timeouts": null
},
"after_unknown": {
"creation_timestamp": true,
"id": true,
"network_tier": true,
"project": true,
"purpose": true,
"self_link": true,
"subnetwork": true,
"users": true
},
"before_sensitive": false,
"after_sensitive": {
"users": []
}
}
}
],
// other data
}
Rego schreiben
Nachdem Sie Beispieldaten haben, können Sie die Logik für Ihre Einschränkungsvorlage in Rego schreiben.
Ihr Rego muss eine violations
-Regel enthalten. Die geprüfte Ressourcenänderung ist als input.review
verfügbar. Einschränkungsparameter sind als input.parameters
verfügbar. Wenn Sie beispielsweise anfordern möchten, dass google_compute_address
-Ressourcen einen zulässigen address_type
haben, schreiben Sie:
# validator/tf_compute_address_address_type_allowlist_constraint_v1.rego
package templates.gcp.TFComputeAddressAddressTypeAllowlistConstraintV1
violation[{
"msg": message,
"details": metadata,
}] {
resource := input.review
resource.type == "google_compute_address"
allowed_address_types := input.parameters.allowed_address_types
count({resource.after.address_type} & allowed_address_types) >= 1
message := sprintf(
"Compute address %s has a disallowed address_type: %s",
[resource.address, resource.after.address_type]
)
metadata := {"resource": resource.name}
}
Einschränkungsvorlage benennen
Im vorherigen Beispiel wird der Name TFComputeAddressAddressTypeAllowlistConstraintV1
verwendet. Dies ist eine eindeutige Kennung für jede Einschränkungsvorlage. Wir empfehlen, diese Richtlinien für Namen zu verwenden:
- Allgemeines Format:
TF{resource}{feature}Constraint{version}
. CamelCase verwenden. (Beginnen Sie also jedes neue Wort mit einem Großbuchstaben.) - Beachten Sie bei Einschränkungen für einzelne Ressourcen die Konventionen für Terraform-Anbieter für die Produktbenennung. Bei
google_tags_tag
lautet der Produktname beispielsweisetags
, obwohl der API-Nameresourcemanager
lautet. - Wenn eine Vorlage für mehr als einen Ressourcentyp gilt, lassen Sie den Ressourcenteil weg und fügen Sie nur das Feature ein (Beispiel: "TFAddressTypeAllowlistConstraintV1").
- Die Versionsnummer folgt nicht der semver-Form. nur eine einzige Zahl. Dadurch wird jede Version einer Vorlage zu einer eindeutigen Vorlage.
Wir empfehlen, für Ihre Rego-Datei einen Namen zu verwenden, der mit dem Namen der Einschränkungsvorlage übereinstimmt, aber "snake_case" verwendet. Mit anderen Worten, konvertieren Sie den Namen mit _
in Kleinbuchstaben. Im obigen Beispiel lautet der empfohlene Dateiname tf_compute_address_address_type_allowlist_constraint_v1.rego
Rego testen
Sie können Ihr Rego manuell mit Rego Playground testen. Verwenden Sie nicht vertrauliche Daten.
Wir empfehlen, automatisierte Tests zu schreiben.
Fügen Sie Ihre gesammelten Beispieldaten in validator/test/fixtures/<constraint
filename>/resource_changes/data.json
ein und verweisen Sie in Ihrer Testdatei so darauf:
# validator/tf_compute_address_address_type_allowlist_constraint_v1_test.rego
package templates.gcp.TFComputeAddressAddressTypeAllowlistConstraintV1
import data.test.fixtures.tf_compute_address_address_type_allowlist_constraint_v1_test.resource_changes as resource_changes
test_violation_with_disallowed_address_type {
parameters := {
"allowed_address_types": "EXTERNAL"
}
violations := violation with input.review as resource_changes[_]
with input.parameters as parameters
count(violations) == 1
}
Platzieren Sie den Rego und den Test im Ordner validator
Ihrer Richtlinienbibliothek.
Basis-Einschränkungsvorlage einrichten
Nachdem Sie eine funktionierende und getestete Rego-Regel haben, müssen Sie diese als Einschränkungsvorlage verpacken. Constraint Framework verwendet benutzerdefinierte Kubernetes-Ressourcendefinitionen als Container für den Richtlinien-Rego.
Die Einschränkungsvorlage definiert mithilfe des Schemas OpenAPI V3 auch, welche Parameter als Eingaben von Einschränkungen zulässig sind.
Verwenden Sie für das Basisschema denselben Namen wie für den Rego. Und zwar:
- Verwenden Sie denselben Dateinamen wie für Ihren Rego. Beispiel:
tf_compute_address_address_type_allowlist_constraint_v1.yaml
spec.crd.spec.names.kind
muss den Vorlagennamen enthaltenmetadata.name
muss den Vorlagennamen enthalten, muss aber kleingeschrieben werden
Platzieren Sie das Basisschema der Einschränkungsvorlage in policies/templates
.
Für das obige Beispiel:
# policies/templates/tf_compute_address_address_type_allowlist_constraint_v1.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: tfcomputeaddressaddresstypeallowlistconstraintv1
spec:
crd:
spec:
names:
kind: TFComputeAddressAddressTypeAllowlistConstraintV1
validation:
openAPIV3Schema:
properties:
allowed_address_types:
description: "A list of address_types allowed, for example: ['INTERNAL']"
type: array
items:
type: string
targets:
- target: validation.resourcechange.terraform.cloud.google.com
rego: |
#INLINE("validator/tf_compute_address_address_type_allowlist_constraint_v1.rego")
#ENDINLINE
Ihr Rego einbinden
In Anlehnung an das vorherige Beispiel sieht Ihr Verzeichnislayout nun folgendermaßen aus:
| policy-library/
|- validator/
||- tf_compute_address_address_type_allowlist_constraint_v1.rego
||- tf_compute_address_address_type_allowlist_constraint_v1_test.rego
|- policies
||- templates
|||- tf_compute_address_address_type_allowlist_constraint_v1.yaml
Wenn Sie das von Google bereitgestellte Repository für die Richtlinienbibliothek geklont haben, können Sie make build
ausführen, um Ihre Einschränkungsvorlagen in policies/templates
automatisch mit den in validator
definierten Rego zu aktualisieren.
Eine Einschränkung einrichten
Einschränkungen enthalten drei Informationen, die gcloud beta terraform vet
ordnungsgemäß erzwingen und Verstöße melden muss:
severity
:low
,medium
oderhigh
match
: Parameter, um zu bestimmen, ob eine Einschränkung für eine bestimmte Ressource gilt. Die folgenden Übereinstimmungsparameter werden unterstützt:addresses
: Eine Liste der Ressourcenadressen, die mithilfe des Glob-Stils einbezogen werden sollenexcludedAddresses
: (Optional) Eine Liste von Ressourcenadressen, die mithilfe des Glob-Stils ausgeschlossen werden sollen.
parameters
: Werte für die Eingabeparameter der Einschränkungsvorlage.
Achten Sie darauf, dass kind
den Namen der Einschränkungsvorlage enthält. Wir empfehlen, metadata.name
auf eine beschreibende Slug festzulegen.
Wenn Sie beispielsweise nur INTERNAL
-Adresstypen mit der vorherigen Beispieleinschränkungsvorlage zulassen möchten, schreiben Sie:
# policies/constraints/tf_compute_address_internal_only.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: TFComputeAddressAddressTypeAllowlistConstraintV1
metadata:
name: tf_compute_address_internal_only
spec:
severity: high
match:
addresses:
- "**"
parameters:
allowed_address_types:
- "INTERNAL"
Beispiele für Übereinstimmungen:
Adress-Matcher | Beschreibung |
---|---|
"module.**" | Alle Ressourcen in einem beliebigen Modul |
"module.my_module.**" | Alles im Modul "my_module" |
`**.google_compute_global_forwarding_rule.*` | Alle google_compute_global_forwarding_rule-Ressourcen in einem beliebigen Modul |
`module.my_module.google_compute_global_forwarding_rule.*` | Alle google_compute_global_forwarding_rule-Ressourcen in "my_module" |
Wenn eine Ressourcenadresse mit den Werten in addresses
und excludedAddresses
übereinstimmt, wird sie ausgeschlossen.
Beschränkungen
Die Daten eines Terraform-Plans liefern nach dem Anwenden die beste verfügbare Darstellung des tatsächlichen Status. In vielen Fällen ist der Zustand nach dem Anwenden jedoch möglicherweise nicht bekannt, da er serverseitig berechnet wird.
Das Erstellen von CAI-Herkunftspfaden ist Teil des Prozesses, wenn Richtlinien validiert werden. Dabei wird das Standardprojekt verwendet, um unbekannte Projekt-IDs zu umgehen. Wenn kein Standardprojekt angegeben ist, wird der Herkunftspfad standardmäßig auf organizations/unknown
gesetzt.
Sie können unbekannte Herkunft verbieten, indem Sie die folgende Einschränkung hinzufügen:
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: {}
Unterstützte Ressourcen
Sie können Einschränkungen für die Ressourcenänderung für jede Terraform-Ressource von jedem Terraform-Anbieter erstellen.