Sprawdzanie zasad artefaktów

Usługa Azure DevOps Services

Zasady artefaktów są wymuszane przed wdrożeniem w krytycznych środowiskach, takich jak produkcja. Te zasady są oceniane względem wszystkich artefaktów możliwych do wdrożenia w danym przebiegu potoku i blokują wdrożenie, jeśli artefakty nie są zgodne. Dodanie sprawdzania w celu oceny artefaktu wymaga skonfigurowania zasad niestandardowych. W tym przewodniku opisano sposób tworzenia zasad niestandardowych.

Uwaga

Obecnie obsługiwane typy artefaktów są przeznaczone dla obrazów kontenerów i środowisk Kubernetes

Wymagania wstępne

Użyj programu Rego do definiowania zasad, które są łatwe do odczytania i zapisu.

Zapoznaj się z językiem zapytań Rego . Podstawy to zrobią.

Aby obsługiwać modele dokumentów strukturalnych, takie jak JSON, Rego rozszerza dziennik danych. Zapytania Rego to aseracje dotyczące danych przechowywanych w usłudze OPA. Te zapytania mogą służyć do definiowania zasad wyliczających wystąpienia danych naruszających oczekiwany stan systemu.

Tworzenie zasad niestandardowych

Poniżej przedstawiono udostępnione przykładowe zasady. Na podstawie wymagań możesz utworzyć własny zestaw zasad.

Sprawdzanie określonego projektu/potoku

Te zasady sprawdzają, czy obrazy są tworzone przez usługi Azure Pipelines i Pipeline-foo. Aby to zadziałało, definicja potoku powinna zastąpić pole nazwy na przykład: AzureDevOps_$(BuildDefinitionName)_$(Date:yyyMMMdd)$(Rev:.r). Więcej informacji na temat nazewnictwa przebiegów potoków można znaleźć tutaj.

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], "/@")
}

Sprawdzanie dozwolonych rejestrów

Te zasady sprawdzają, czy obrazy pochodzą tylko z dozwolonych rejestrów.

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], "/@")
}

Sprawdzanie zabronionych portów

Te zasady sprawdzają wszystkie niedozwolone porty uwidocznione w obrazie kontenera.

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], "/@")
}

Sprawdzanie wcześniejszych wdrożeń

Te zasady sprawdzają, czy obraz został wstępnie wdrożony w co najmniej jednym środowisku przed wdrożeniem w określonym środowisku/zasobach przy użyciu opcji Sprawdź skonfigurowane.

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], "/@")
}