Artefaktrichtlinienüberprüfungen
Azure DevOps Services
Artefaktrichtlinien werden vor der Bereitstellung in kritischen Umgebungen wie der Produktion erzwungen. Diese Richtlinien werden anhand aller bereitstellungsfähigen Artefakte in der angegebenen Pipelineausführung ausgewertet und blockieren die Bereitstellung, wenn die Artefakte nicht übereinstimmen. Das Hinzufügen einer Überprüfung zum Auswerten des Artefakts erfordert die Konfiguration der benutzerdefinierten Richtlinie. In diesem Leitfaden wird beschrieben, wie benutzerdefinierte Richtlinien erstellt werden können.
Hinweis
Derzeit werden die unterstützten Artefakttypen für Containerimages und Kubernetes-Umgebungen verwendet.
Voraussetzungen
Verwenden Sie Rego zum Definieren einer Richtlinie, die einfach zu lesen und zu schreiben ist.
Machen Sie sich mit der Rego-Abfragesprache vertraut. Grundlagen werden erstellt.
Um strukturierte Dokumentmodelle wie JSON zu unterstützen, erweitert Rego Datalog. Regoabfragen sind Assertionen für in OPA gespeicherte Daten. Diese Abfragen können verwendet werden, um Richtlinien zu definieren, die Instanzen von Daten auflisten, die den erwarteten Zustand des Systems verletzen.
Erstellen benutzerdefinierter Richtlinien
Im Folgenden finden Sie die freigegebenen Beispielrichtlinien. Basierend auf Ihren Anforderungen können Sie Ihren eigenen Richtliniensatz erstellen.
Überprüfen eines bestimmten Projekts/einer bestimmten Pipeline
Mit dieser Richtlinie wird überprüft, ob die Images von Azure Pipelines und Pipeline-foo erstellt wurden. Damit dies funktioniert, sollte die Pipelinedefinition das Feld name in etwa in etwa überschreiben: AzureDevOps_$(BuildDefinitionName)_$(Date:yyyyMMMdd)$(Rev:.r). Weitere Informationen zum Benennen von Pipelineausführungen finden Sie hier.
allowedBuilder := "AzureDevOps_pipeline-foo"
checkBuilder[errors] {
trace("Check if images are built by Azure Pipelines")
resourceUri := values[index].build.resourceUri
image := fetchImage(resourceUri)
builder := values[index].build.build.provenance.builderVersion
trace(sprintf("%s: builder", [builder]))
not startswith(builder, "allowedBuilder")
errors := sprintf("%s: image not built by Azure Pipeline [%s]", [image,builder])
}
fetchRegistry(uri) = reg {
out := regex.find_n("//.*/", uri, 1)
reg = trim(out[0], "/")
}
fetchImage(uri) = img {
out := regex.find_n("/.*@", uri, 1)
img := trim(out[0], "/@")
}
Überprüfen zulässiger Registrierungen
Mit dieser Richtlinie wird überprüft, ob die Bilder nur von zulässigen Registrierungen stammen.
allowlist = {
"gcr.io/myrepo",
"raireg1.azurecr.io"
}
checkregistries[errors] {
trace(sprintf("Allowed registries: %s", [concat(", ", allowlist)]))
resourceUri := values[index].image.resourceUri
registry := fetchRegistry(resourceUri)
image := fetchImage(resourceUri)
not allowlist[registry]
errors := sprintf("%s: source registry not permitted", [image])
}
fetchRegistry(uri) = reg {
out := regex.find_n("//.*/", uri, 1)
reg = trim(out[0], "/")
}
fetchImage(uri) = img {
out := regex.find_n("/.*@", uri, 1)
img := trim(out[0], "/@")
}
Überprüfen verbotener Ports
Mit dieser Richtlinie wird auf alle verbotenen Ports überprüft, die im Containerimage verfügbar gemacht werden.
forbiddenPorts = {
"80",
"22"
}
checkExposedPorts[errors] {
trace(sprintf("Checking for forbidden exposed ports: %s", [concat(", ", forbiddenPorts)]))
layerInfos := values[index].image.image.layerInfo
layerInfos[x].directive == "EXPOSE"
resourceUri := values[index].image.resourceUri
image := fetchImage(resourceUri)
ports := layerInfos[x].arguments
trace(sprintf("exposed ports: %s", [ports]))
forbiddenPorts[ports]
errors := sprintf("%s: image exposes forbidden port %s", [image,ports])
}
fetchRegistry(uri) = reg {
out := regex.find_n("//.*/", uri, 1)
reg = trim(out[0], "/")
}
fetchImage(uri) = img {
out := regex.find_n("/.*@", uri, 1)
img := trim(out[0], "/@")
}
Überprüfen früherer Bereitstellungen
Mit dieser Richtlinie wird überprüft, ob das Image in einer oder mehreren Umgebungen vorab bereitgestellt wurde, bevor es in bestimmten Umgebungen/Ressourcen mit konfiguriertem Check bereitgestellt wurde.
predeployedEnvironments = {
"env/resource1",
"env2/resource3"
}
checkDeployedEnvironments[errors] {
trace(sprintf("Checking if the image has been pre-deployed to one of: [%s]", [concat(", ", predeployedEnvironments)]))
deployments := values[index].deployment
deployedAddress := deployments[i].deployment.address
trace(sprintf("deployed to : %s",[deployedAddress]))
resourceUri := deployments[i].resourceUri
image := fetchImage(resourceUri)
not predeployedEnvironments[deployedAddress]
trace(sprintf("%s: fails pre-deployed environment condition. found %s", [image,deployedAddress]))
errors := sprintf("image %s fails pre-deployed environment condition. found %s", [image,deployedAddress])
}
fetchRegistry(uri) = reg {
out := regex.find_n("//.*/", uri, 1)
reg = trim(out[0], "/")
}
fetchImage(uri) = img {
out := regex.find_n("/.*@", uri, 1)
img := trim(out[0], "/@")
}