Compartilhar via


Verificações de política de artefatos

Serviços do Azure DevOps

As políticas de artefato são aplicadas antes da implantação em ambientes críticos de produção. Essas políticas são avaliadas em relação a todos os artefatos implantáveis na execução de pipeline em questão e impedem a implantação se os artefatos não estiverem em conformidade. Adicionar uma verificação para avaliar o Artefato requer que a política personalizada seja configurada. Este guia descreve como as políticas personalizadas podem ser criadas.

Observação

Atualmente, os tipos de artefato com suporte são para imagens de contêiner e ambientes do Kubernetes

Pré-requisitos

Use Rego para definir uma política que seja fácil de ler e escrever.

Familiarize-se com a linguagem de consulta Rego . Noções básicas servem.

Para dar suporte a modelos de documentos estruturados como JSON, o Rego estende o Datalog. Consultas Rego são afirmações sobre dados armazenados no OPA. Essas consultas podem ser usadas para definir políticas que enumeram instâncias de dados que violam o estado esperado do sistema.

Criando políticas personalizadas

Abaixo estão as políticas de exemplo compartilhadas. Com base em seus requisitos, você pode criar seu próprio conjunto de políticas.

Verificar projeto/pipeline específico

Essa política verifica se as imagens foram criadas pelo Azure Pipelines e pelo Pipeline-foo. Para que isso funcione, a definição de pipeline deve substituir o campo de nome para algo como: AzureDevOps_$(BuildDefinitionName)_$(Date:yyyyyMMdd)$(Rev:.r). Veja mais sobre como nomear execuções de pipeline aqui.

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

Verificar registros permitidos

Essa política verifica se as imagens são somente de repositórios 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], "/@")
}

Verificar portas proibidas

Essa política verifica se há portas proibidas expostas na imagem do contêiner.

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

Verificar implantações anteriores

Essa política verifica se a imagem foi pré-implantada em um/mais ambientes antes de ser implantada em ambientes/recursos específicos com Check configurado.

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