Validating image inputs
Las imágenes de contenedor son las entradas de compilación más comunes. Cada
instrucción FROM descarga una imagen, y las referencias COPY --from descargan
imágenes adicionales. Validar estas imágenes protege la cadena de suministro de
tu compilación frente a registros comprometidos, actualizaciones inesperadas e
imágenes base no autorizadas.
Esta guía te enseña a escribir políticas que validen las entradas de imágenes, avanzando desde la lista de permitidos básica hasta las comprobaciones de atestaciones avanzadas.
Requisitos previos
Debes comprender los conceptos básicos de las políticas a partir de la Introducción: la creación de archivos de políticas, la sintaxis básica de Rego y cómo se evalúan las políticas durante las compilaciones.
¿Qué son las entradas de imágenes?
Las entradas de imágenes provienen de dos instrucciones de Dockerfile:
# Instrucciones FROM
FROM alpine:3.22
FROM golang:1.25-alpine AS builder
# Referencias COPY --from
COPY --from=builder /app /app
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.confCada una de estas referencias desencadena la evaluación de una política. Tu política puede inspeccionar los metadatos de la imagen, verificar las atestaciones y aplicar restricciones antes de que continúe la compilación.
Lista de permitidos para repositorios específicos
La política de imágenes más simple restringe qué repositorios se pueden usar. Esto evita que los desarrolladores utilicen imágenes arbitrarias que no hayan sido revisadas.
Crea una política que solo permita Alpine:
package docker
default allow := false
allow if input.local
allow if {
input.image.repo == "alpine"
}
decision := {"allow": allow}Esta política:
- Deniega todas las entradas por defecto
- Permite el contexto de compilación local
- Permite cualquier imagen del repositorio
alpine(cualquier etiqueta o digest)
Pruébalo con un Dockerfile:
FROM alpine
RUN echo "hello"$ docker build .
La compilación se realiza con éxito. Intenta cambiar a FROM ubuntu:
$ docker build .
La compilación falla porque ubuntu no coincide con el repositorio permitido.
Comparar versiones semánticas
Restringe las imágenes a rangos de versiones específicos utilizando las funciones
semver de Rego:
package docker
default allow := false
allow if input.local
# Permitir Go 1.21 o posterior
allow if {
input.image.repo == "golang"
semver.is_valid(input.image.tag)
semver.compare(input.image.tag, "1.21.0") >= 0
}
decision := {"allow": allow}La función semver.compare(a, b) compara versiones semánticas y devuelve:
-1si la versiónaes menor queb0si las versiones son iguales1si la versiónaes mayor queb
Utiliza semver.is_valid() para comprobar si una etiqueta es una versión
semántica válida antes de compararla.
Restringir a rangos de versiones específicos:
allow if {
input.image.repo == "node"
version := input.image.tag
semver.is_valid(version)
semver.compare(version, "20.0.0") >= 0 # 20.0.0 o posterior
semver.compare(version, "21.0.0") < 0 # anterior a 21.0.0
}Esto permite únicamente las versiones de Node.js 20.x. El patrón funciona para cualquier imagen que utilice versionado semántico.
Estas funciones semver son funciones integradas estándar de Rego documentadas en
la referencia de políticas de OPA.
Requerir referencias por digest
Las etiquetas como alpine:3.22 pueden cambiar (alguien podría subir una nueva
imagen con la misma etiqueta). Los digests como alpine@sha256:abc123... son
inmutables.
Requerir que los usuarios proporcionen digests
Puedes exigir que los usuarios especifiquen siempre los digests en sus Dockerfiles:
package docker
default allow := false
allow if input.local
allow if {
input.image.isCanonical
}
decision := {"allow": allow}El campo isCanonical es true cuando la referencia del usuario incluye un
digest. Esta política permitiría:
FROM alpine@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412Pero rechazaría las referencias basadas únicamente en etiquetas como
FROM alpine:3.22.
Fijar a digests específicos
Alternativamente (o además), puedes validar que el digest real de una imagen coincida con un valor específico, independientemente de cómo haya escrito el usuario la referencia:
allow if {
input.image.repo == "alpine"
input.image.checksum == "sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
}
decision := {"allow": allow}Esto comprueba el digest de contenido real de la imagen descargada. Permitiría ambos casos:
FROM alpine:3.22
FROM alpine@sha256:4b7ce...Siempre y cuando la imagen resuelta tenga el digest especificado. Esto es útil para fijar imágenes base críticas a versiones conocidas como seguras.
Restringir registros
Controla desde qué registros pueden realizar descargas tus compilaciones. Esto ayuda a aplicar las políticas corporativas o a restringir las descargas a fuentes de confianza.
package docker
default allow := false
allow if input.local
# Permitir imágenes de Docker Hub
allow if {
input.image.host == "docker.io" # Docker Hub
input.image.repo == "alpine"
}
# Permitir imágenes de un registro interno
allow if {
input.image.host == "registry.company.com"
}
decision := {"allow": allow}El campo host contiene el nombre de host del registro. Las imágenes de Docker
Hub usan "docker.io" como valor de host. Prueba con:
FROM alpine # Permitido (Docker Hub)
FROM registry.company.com/myapp:latest # Permitido (registro de la empresa)
FROM ghcr.io/someorg/image:latest # Denegado (registro incorrecto)Utiliza fullRepo cuando necesites la ruta completa, incluido el registro:
allow if {
input.image.fullRepo == "docker.io/library/alpine"
}Validar restricciones de plataforma
Las imágenes multiarquitectura admiten diferentes sistemas operativos y arquitecturas de CPU. Puedes restringir las compilaciones a plataformas específicas:
package docker
default allow := false
allow if input.local
allow if {
input.image.os == "linux"
input.image.arch in ["amd64", "arm64"]
}
decision := {"allow": allow}Esta política:
- Define las arquitecturas compatibles en una lista
- Comprueba que
input.image.oscoincida con Linux - Verifica que
input.image.archse encuentre en la lista de compatibles
Los campos os y arch provienen del manifiesto de la imagen, reflejando la
plataforma real de la imagen. Esto funciona con la selección automática de
plataformas de Docker: las políticas validan lo que Buildx resuelve, no lo que
especificas.
Inspeccionar metadatos de imágenes
Las imágenes contienen metadatos como variables de entorno, etiquetas y directorios de trabajo. Puedes validarlos para asegurarte de que las imágenes cumplen con los requisitos.
Comprobar variables de entorno específicas:
package docker
default allow := false
allow if input.local
allow if {
input.image.repo == "golang"
input.image.workingDir == "/go"
some ver in input.image.env
startswith(ver, "GOLANG_VERSION=")
some toolchain in input.image.env
toolchain == "GOTOOLCHAIN=local"
}
decision := {"allow": allow}Esta política valida la imagen oficial de Go comprobando que:
- El directorio de trabajo es
/go - El entorno tiene configurado
GOLANG_VERSION - El entorno incluye
GOTOOLCHAIN=local
El campo input.image.env es un array de cadenas en formato CLAVE=VALOR.
Utiliza la iteración some de Rego para buscar en el array.
Comprobar etiquetas de imagen:
allow if {
input.image.labels["org.opencontainers.image.vendor"] == "Example Corp"
input.image.labels["org.opencontainers.image.version"] != ""
}El campo labels es un mapa, por lo que accedes a los valores utilizando la
notación de corchetes.
Requerir atestaciones y procedencia
Las imágenes modernas incluyen atestaciones: metadatos legibles por máquina sobre cómo se compiló la imagen. Las atestaciones de procedencia (provenance) describen el proceso de compilación, y las de SBOM enumeran el software interno.
Requerir procedencia:
package docker
default allow := false
allow if input.local
allow if {
input.image.hasProvenance
}
decision := {"allow": allow}El campo hasProvenance es true cuando la imagen tiene atestaciones de
procedencia o SBOM attestations.
Verificar firmas de GitHub Actions
Para imágenes compiladas con GitHub Actions, verifica que provengan de flujos de trabajo de confianza inspeccionando los metadatos de las firmas:
allow if {
input.image.repo == "myapp"
input.image.hasProvenance
some sig in input.image.signatures
valid_github_signature(sig)
}
# Asistente para validar la firma de GitHub Actions
valid_github_signature(sig) if {
sig.signer.certificateIssuer == "CN=sigstore-intermediate,O=sigstore.dev"
sig.signer.issuer == "https://token.actions.githubusercontent.com"
startswith(sig.signer.buildSignerURI, "https://github.com/myorg/")
sig.signer.runnerEnvironment == "github-hosted"
}
decision := {"allow": allow}Este patrón funciona con cualquier flujo de trabajo de GitHub Actions que utilice firmas sin clave (keyless) de Sigstore. Los metadatos de la firma proporcionan una prueba criptográfica del origen de la compilación. Para ver ejemplos completos de verificación de firmas, consulta Ejemplos de políticas.
Combinar múltiples comprobaciones
Las políticas reales a menudo combinan varias comprobaciones. Múltiples
condiciones en una sola regla allow significan AND: todas deben ser verdaderas:
package docker
default allow := false
allow if input.local
# Las imágenes de producción necesitan todo
allow if {
input.image.repo == "alpine"
input.image.isCanonical
input.image.hasProvenance
}
decision := {"allow": allow}Múltiples reglas allow significan OR: cualquier regla puede coincidir:
package docker
default allow := false
allow if input.local
# Permitir Alpine con comprobaciones estrictas
allow if {
input.image.repo == "alpine"
input.image.isCanonical
}
# Permitir Go con diferentes comprobaciones
allow if {
input.image.repo == "golang"
input.image.workingDir == "/go"
}
decision := {"allow": allow}Utiliza este patrón para aplicar diferentes requisitos a diferentes imágenes base.
Siguientes pasos
Ahora comprendes cómo validar imágenes de contenedor en las políticas de compilación. Para continuar aprendiendo:
- Aprende la Validación de repositorios Git para las entradas de código fuente
- Explora Ejemplos de políticas para conocer patrones de políticas completos
- Lee las Funciones integradas para la verificación de firmas y comprobación de atestaciones
- Consulta la Referencia de inputs para conocer todos los campos de imágenes disponibles