Проверки соответствия политике артефактов

Azure DevOps Services

Политики артефактов применяются перед развертыванием в критически важных средах, таких как рабочая среда. Эти политики оцениваются по всем развертываемым артефактам в заданном запуске конвейера и блокируют развертывание, если артефакты не соответствуют требованиям. Для добавления проверка для оценки артефакта требуется настроить настраиваемую политику. В этом руководстве описывается, как можно создавать пользовательские политики.

Примечание

В настоящее время поддерживаются типы артефактов для образов контейнеров и сред Kubernetes.

Предварительные требования

Используйте Rego для определения легкой для чтения и записи политики.

Ознакомьтесь с языком запросов Rego . Основные сведения будут делать.

Для поддержки структурированных моделей документов, таких как JSON, Rego расширяет журнал данных. Запросы rego — это утверждения для данных, хранящихся в OPA. Эти запросы можно использовать для определения политик, которые перечисляют экземпляры данных, нарушающие ожидаемое состояние системы.

Создание настраиваемых политик

Ниже приведены примеры общих политик. В зависимости от ваших требований вы можете создать собственный набор политик.

Проверка конкретного проекта или конвейера

Эта политика проверяет, созданы ли образы с помощью Azure Pipelines и Pipeline-foo. Чтобы это работало, определение конвейера должно переопределить поле имени следующим образом: AzureDevOps_$(BuildDefinitionName)_$(Date:yyyyMdd)$(Rev:.r). Дополнительные сведения об именовании запусков конвейера см. здесь.

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

Проверка разрешенных реестров

Эта политика проверяет, относятся ли образы только к разрешенным реестрам.

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

Проверка запрещенных портов

Эта политика проверяет наличие запрещенных портов, предоставляемых в образе контейнера.

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

Проверка предыдущих развертываний

Эта политика проверяет, был ли образ предварительно развернут в одной или нескольких средах перед развертыванием в определенной среде или ресурсах с параметром Проверка настроена.

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