Compartir a través de


Comprobaciones de directiva de artefactos

Azure DevOps Services

Las directivas de artefacto se aplican antes de su implementación en entornos críticos, como el entorno de producción. Estas directivas se evalúan en todos los artefactos que se pueden implementar en la ejecución de canalización determinada y bloquean la implementación si los artefactos no cumplen. Agregar una comprobación para evaluar un artefacto requiere que se configure la directiva personalizada. En esta guía, se describe cómo se pueden crear directivas personalizadas.

Nota:

Actualmente, los tipos de artefacto admitidos son para imágenes de contenedor y entornos de Kubernetes.

Requisitos previos

Use Rego para definir una directiva fácil de leer y escribir.

Familiarícese con el lenguaje de consulta Rego. Los conceptos básicos son suficientes.

Para admitir modelos de documentos estructurados como JSON, Rego amplía Datalog. Las consultas de Rego son aserciones en los datos almacenados en OPA. Estas consultas se pueden usar para definir directivas que enumeran instancias de datos que infringen el estado esperado del sistema.

Creación de directivas personalizadas

A continuación, se muestran las directivas de ejemplo compartidas. En función de sus requisitos, puede crear su propio conjunto de directivas.

Comprobación de proyectos o canalizaciones específicos

Esta directiva comprueba si las imágenes se crean con Azure Pipelines y Pipeline-foo. Para que esto funcione, la definición de canalización debe invalidar el campo de nombre en algo parecido a: AzureDevOps_$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r). Consulte más información sobre cómo asignar nombres a las ejecuciones de canalización aquí.

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

Comprobación de los registros permitidos

Esta directiva comprueba si las imágenes solo proceden de registros permitidos.

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

Comprobación de puertos prohibidos

Esta directiva comprueba si hay puertos prohibidos expuestos en la imagen de contenedor.

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

Comprobación de las implementaciones anteriores

Esta directiva comprueba si la imagen se ha implementado previamente en uno o varios de los entornos antes de implementarse en un entorno o recursos específicos con Comprobación configurada.

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