# Introducción a las políticas de compilación


Las políticas de compilación te permiten validar las entradas de tus compilaciones
de Docker antes de que se ejecuten. Este tutorial te guiará en la creación de tu
primera política, enseñándote los conceptos básicos de Rego que necesitas a lo
largo del proceso.

## Qué aprenderás

Al finalizar este tutorial, comprenderás:

- Cómo crear y organizar archivos de políticas
- La sintaxis y patrones básicos de Rego
- Cómo escribir políticas que validen URLs, sumas de comprobación y imágenes
- Cómo se evalúan las políticas durante las compilaciones

## Requisitos previos

- Buildx versión 0.31 o posterior
- Familiaridad básica con Dockerfiles y compilación de imágenes

## Cómo funcionan las políticas

Cuando compilas una imagen, Buildx resuelve todas las entradas a las que hace
referencia tu Dockerfile: imágenes base de las instrucciones `FROM`, archivos de
las instrucciones `ADD` o `COPY` o contextos de compilación, y repositorios Git.
Antes de ejecutar la compilación, Buildx evalúa tus políticas frente a estas
entradas. Si alguna entrada viola una política, la compilación falla antes de que
se ejecute cualquier instrucción.

Las políticas se escriben en Rego, un lenguaje declarativo diseñado para expresar
reglas y restricciones. No necesitas saber Rego para comenzar; este tutorial te
enseña lo necesario.

## Crea tu primera política

Crea un nuevo directorio para este tutorial y añade un Dockerfile:

```console
$ mkdir tutorial-politicas
$ cd tutorial-politicas
```

Crea un `Dockerfile` que descargue un archivo con `ADD`:

```dockerfile
FROM scratch
ADD https://example.com/index.html /index.html
```

Ahora crea un archivo de política. Las políticas usan la extensión `.rego` y se
ubican junto a tu Dockerfile. Crea `Dockerfile.rego`:

```rego {title="Dockerfile.rego"}
package docker

default allow := false

allow if input.local
allow if {
  input.http.host == "example.com"
}

decision := {"allow": allow}
```

Guarda este archivo como `Dockerfile.rego` en el mismo directorio que tu
Dockerfile.

Analicemos lo que hace esta política:

- `package docker` - Todas las políticas de compilación deben comenzar con esta
  declaración de paquete
- `default allow := false` - Este ejemplo utiliza una regla de denegación por
  defecto: si las entradas no coinciden con una regla `allow`, la verificación
  de la política falla
- `allow if input.local` - La primera regla permite cualquier archivo local (tu
  contexto de compilación)
- `allow if { input.http.host == "example.com" }` - La segunda regla permite
  descargas HTTP desde `example.com`
- `decision := {"allow": allow}` - El objeto de decisión final le indica a Buildx
  si debe permitir o denegar la entrada

Esta política dice: "Solo permitir archivos locales y descargas HTTP desde
`example.com`". Rego evalúa todas las reglas de la política para determinar el
valor de retorno de la variable `decision` para cada entrada de compilación. Las
evaluaciones ocurren en paralelo y bajo demanda; el orden de las reglas de la
política no tiene importancia.

### Acerca de `input.local`

Verás `allow if input.local` en casi todas las políticas. Esta regla permite el
acceso a archivos locales, lo que incluye tu contexto de compilación
(normalmente, el directorio `.`) y, lo que es más importante, el propio
Dockerfile. Sin esta regla, Buildx no podría leer tu Dockerfile para iniciar la
compilación.

Incluso las compilaciones que no hacen referencia a ningún archivo del contexto de
compilación a menudo necesitan `input.local` porque el Dockerfile es un archivo
local. La política se evalúa antes de que comience la compilación, y denegar el
acceso local significa denegar el acceso al Dockerfile.

En casos poco comunes, es posible que desees políticas de archivos locales más
estrictas; por ejemplo, en compilaciones de CI donde el contexto de compilación
utiliza una URL de Git directamente. En estos casos, podrías querer denegar las
fuentes locales para evitar que archivos sin seguimiento o cambios no registrados
formen parte de tu compilación.

## Carga automática de políticas

Buildx carga automáticamente las políticas que coinciden con el nombre de tu
Dockerfile. Cuando compilas con `Dockerfile`, Buildx busca `Dockerfile.rego` en el
mismo directorio. Para un archivo llamado `app.Dockerfile`, busca
`app.Dockerfile.rego`.

Esta carga automática significa que no necesitas ninguna bandera de línea de
comandos en la mayoría de los casos: simplemente crea el archivo de política y
compila.

El archivo de política debe estar en el mismo directorio que el Dockerfile. Si
Buildx no puede encontrar una política coincidente, la compilación continúa sin
la evaluación de la política (a menos que utilices `--policy strict=true`).

Para obtener más control sobre la carga de políticas, consulta la
[Guía de uso](/build/policies/usage/).

## Ejecuta una compilación con tu política

Compila la imagen con la evaluación de políticas habilitada:

```console
$ docker build .
```

La compilación se realiza con éxito porque la URL de tu Dockerfile coincide con
la política. Ahora intenta cambiar la URL en tu Dockerfile por otra cosa:

```dockerfile
FROM scratch
ADD https://api.github.com/users/octocat /user.json
```

Compila de nuevo:

```console
$ docker build .
```

Esta vez la compilación falla debido a una violación de la política. El nombre
de host `api.github.com` no coincide con la regla de tu política, por lo que
Buildx lo rechaza antes de ejecutar cualquier paso de compilación.

## Depuración de fallas de políticas

Si tu compilación falla debido a una violación de la política, utiliza
`--progress=plain` para ver exactamente qué salió mal:

```console
$ docker buildx build --progress=plain .
```

Esto muestra todas las verificaciones de políticas, los datos de entrada para
cada fuente y las decisiones de permitir/denegar. Para obtener una guía de
depuración completa, consulta [Depuración](/build/policies/debugging/).

## Añadir mensajes de error útiles

Cuando una política deniega una entrada, los usuarios ven un mensaje de error
genérico. Puedes proporcionar mensajes personalizados que expliquen por qué se
denegó la compilación:

```rego {title="Dockerfile.rego"}
package docker

default allow := false

allow if input.local
allow if {
  input.http.host == "example.com"
  input.http.schema == "https"
}

deny_msg contains msg if {
  not allow
  input.http
  msg := "solo se permiten descargas HTTPS desde example.com"
}

decision := {"allow": allow, "deny_msg": deny_msg}
```

Now, cuando se deniegue una compilación, los usuarios verán tu mensaje
personalizado explicando qué salió mal:

```console
$ docker buildx build .
Policy: solo se permiten descargas HTTPS desde example.com
ERROR: failed to build: ... source not allowed by policy
```

La regla `deny_msg` utiliza `contains` para añadir mensajes a un conjunto. Puedes
añadir múltiples mensajes de denegación para diferentes condiciones de falla para
ayudar a los usuarios a comprender exactamente qué debe cambiar.

## Entender las reglas de Rego

Las políticas de Rego se construyen a partir de reglas. Una regla define cuándo
se permite algo. El patrón básico es:

```rego
allow if {
    condition_one
    condition_two
    condition_three
}
```

Todas las condiciones deben ser verdaderas para que la regla coincida. Piensa en
ello como una operación AND: la URL debe coincidir AND la suma de comprobación
debe coincidir AND cualquier otra condición que especifiques.

Puedes tener múltiples reglas `allow` en una sola política. Si alguna regla
coincide, la entrada se permite:

```rego
# Permitir descargas desde example.com
allow if {
    input.http.host == "example.com"
}

# También permitir descargas desde api.github.com
allow if {
    input.http.host == "api.github.com"
}
```

Esto funciona como un OR: la entrada puede coincidir con la primera regla OR con
la segunda regla.

## Acceder a los campos de entrada

El objeto `input` te da acceso a la información sobre las entradas de
compilación. La estructura depende del tipo de entrada:

- `input.http` - Archivos descargados con `ADD https://...`
- `input.image` - Imágenes de contenedor de `FROM` o `COPY --from`
- `input.git` - Repositorios de Git de `ADD git://...` o del contexto de compilación
- `input.local` - Contexto de archivos locales

Consulta la [Referencia de inputs](/build/policies/inputs/) para conocer todos los campos de
entrada disponibles.

Para las descargas HTTP, puedes acceder a:

| Clave               | Descripción                          | Ejemplo                          |
| ------------------- | ------------------------------------ | -------------------------------- |
| `input.http.url`    | La URL completa                      | `https://example.com/index.html` |
| `input.http.schema` | El protocolo (HTTP/HTTPS)            | `https`                          |
| `input.http.host`   | El nombre de host                    | `example.com`                    |
| `input.http.path`   | La ruta de la URL, incluyendo params | `/index.html`                    |

Actualiza tu política para requerir HTTPS:

```rego
package docker

default allow := false

allow if {
    input.http.host == "example.com"
    input.http.schema == "https"
}

decision := {"allow": allow}
```

Ahora la política requiere tanto que el nombre de host sea `example.com` como que
el protocolo sea HTTPS. Las URLs HTTP (sin TLS) fallarían la verificación de la
política.

## Coincidencia de patrones y cadenas

Rego proporciona [funciones integradas] para la coincidencia de patrones. Utiliza
`startswith()` para hacer coincidir prefijos de URL:

[funciones integradas]: https://www.openpolicyagent.org/docs/policy-language#built-in-functions

```rego
allow if {
    startswith(input.http.url, "https://example.com/")
}
```

Esto permite cualquier URL que comience con `https://example.com/`.

Utiliza `regex.match()` para patrones complejos:

```rego
allow if {
    regex.match(`^https://example\.com/.+\.json$`, input.http.url)
}
```

Esto coincide con URLs que:

- Comienzan con `https://example.com/`
- Terminan con `.json`
- Tienen al menos un carácter entre el dominio y la extensión

## Ubicación del archivo de política

Los archivos de políticas se ubican junto al Dockerfile que validan, utilizando
el patrón de nomenclatura `<nombre-dockerfile>.rego`:

```text
project/
├── Dockerfile           # Dockerfile principal
├── Dockerfile.rego      # Política para Dockerfile
├── lint.Dockerfile      # Dockerfile de análisis estático (linting)
└── lint.Dockerfile.rego # Política para lint.Dockerfile
```

Cuando compilas, Buildx carga automáticamente el archivo de política
correspondiente:

```console
$ docker buildx build -f Dockerfile .        # Carga Dockerfile.rego
$ docker buildx build -f lint.Dockerfile .   # Carga lint.Dockerfile.rego
```

## Siguientes pasos

Ahora comprendes cómo escribir políticas de compilación básicas para recursos
HTTP. Para continuar aprendiendo:

- Aplicar y probar políticas: [Uso de políticas de compilación](/build/policies/usage/)
- Aprender [Validación de imágenes](/build/policies/validate-images/) para validar imágenes
  de contenedor a partir de instrucciones `FROM`
- Aprender [Validación de Git](/build/policies/validate-git/) para validar repositorios de
  Git utilizados en compilaciones
- Consultar [Ejemplos de políticas](/build/policies/examples/) para políticas listas para
  copiar y pegar que cubren escenarios comunes
- Escribir pruebas unitarias para tus políticas: [Probar políticas de compilación](/build/policies/testing/)
- Depurar fallas de políticas: [Depuración](/build/policies/debugging/)
- Leer la [Referencia de inputs](/build/policies/inputs/) para conocer todos los campos de
  entrada disponibles
- Revisar las [Funciones integradas](/build/policies/built-ins/) para la verificación de
  firmas, atestaciones y otras comprobaciones de seguridad

