Reglas OPA/WASM
Las reglas OPA (Open Policy Agent) usan el lenguaje Rego compilado a WebAssembly para lógica de políticas complejas que van más allá del simple matching de patrones.
Estructura
Las reglas OPA requieren dos archivos:
- Política Rego (
.rego
) - Lógica de la regla - Metadatos (
.wasm.json
) - Información de la regla
Ejemplo Real
Política Rego (docker-security.rego
)
rego
package audit.docker
# Detect containers running as root
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "USER"
contains(node.value, "root")
msg := "Container runs as root user - use a non-root user for security"
}
# Detect use of 'latest' tag in FROM
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "FROM"
contains(node.value, ":latest")
msg := "Using 'latest' tag is not recommended - specify exact version"
}
# Detect use of ADD instead of COPY
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "ADD"
msg := "Use COPY instead of ADD for local files"
}
# Detect privileged containers
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "RUN"
contains(node.value, "sudo")
msg := "Avoid using sudo in containers - not needed and security risk"
}
Metadatos (docker-security.wasm.json
)
json
{
"id": "opa.docker.security",
"severity": "HIGH",
"category": "docker",
"message": "Docker security violations detected",
"entrypoint": "data.audit.docker.deny",
"remediation": "Review Docker security best practices",
"description": "Detects common Docker security issues: root user, latest tags, ADD usage, and sudo in containers"
}
Proceso de Creación
1. Escribir la Política Rego
rego
package audit.security
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "USER"
contains(node.value, "root")
msg := "Container runs as root user"
}
2. Compilar a WebAssembly
bash
opa build -t wasm -e data.audit.security.deny policy.rego
3. Crear Metadatos
json
{
"id": "opa.docker.no-root",
"severity": "HIGH",
"category": "docker",
"message": "Container runs as root user",
"entrypoint": "data.audit.security.deny"
}
Sintaxis Rego
Estructura Básica
rego
package audit.category
deny[msg] if {
# Condiciones
condition1
condition2
msg := "Mensaje de error"
}
Acceso a Datos
rego
# Acceder a propiedades del input
input.file_type == "dockerfile"
input.nodes[_].path == "USER"
input.nodes[_].value
# Iterar sobre arrays
node := input.nodes[_]
Funciones Útiles
rego
# Verificar si contiene texto
contains(node.value, "root")
# Verificar si empieza con
startswith(node.value, "FROM")
# Verificar si termina con
endswith(node.value, ":latest")
Campos de Metadatos
Campo | Descripción |
---|---|
id | Identificador único de la regla |
severity | Nivel: CRITICAL, HIGH, MEDIUM, LOW |
category | Categoría del lenguaje/tecnología |
message | Mensaje principal de la regla |
entrypoint | Punto de entrada de la política (data.package.rule) |
remediation | Sugerencia de corrección |
description | Descripción detallada |
Casos de Uso
Validación de Docker
rego
package audit.docker
deny[msg] if {
input.file_type == "dockerfile"
node := input.nodes[_]
node.path == "FROM"
contains(node.value, ":latest")
msg := "Using 'latest' tag is not recommended"
}
Validación de Configuraciones
rego
package audit.config
deny[msg] if {
input.file_type == "yaml"
node := input.nodes[_]
node.path == "database.password"
node.value == "admin"
msg := "Default password detected"
}
Validación Compleja
rego
package audit.complex
deny[msg] if {
input.file_type == "dockerfile"
# Verificar que no use root
user_node := input.nodes[_]
user_node.path == "USER"
contains(user_node.value, "root")
# Y que no use latest
from_node := input.nodes[_]
from_node.path == "FROM"
contains(from_node.value, ":latest")
msg := "Container has multiple security issues"
}
Ventajas
✅ Perfecto para:
- Lógica de políticas complejas
- Validación de múltiples condiciones
- Análisis de relaciones entre datos
- Políticas reutilizables
- Lógica condicional avanzada
❌ Limitaciones:
- Curva de aprendizaje alta
- Rendimiento más lento
- Requiere compilación
- Más complejo de mantener
Diferencias con Otros Tipos
Aspecto | YAML | Semgrep | OPA |
---|---|---|---|
Complejidad | Baja | Media | Alta |
Lógica | No | Limitada | Completa |
Rendimiento | Alto | Medio | Bajo |
Flexibilidad | Baja | Alta | Muy Alta |
Mantenimiento | Fácil | Medio | Difícil |
Cuándo Usar OPA
✅ Usa OPA cuando:
- Necesitas lógica compleja
- Tienes múltiples condiciones
- Quieres políticas reutilizables
- Necesitas análisis de relaciones
- Tienes reglas de negocio específicas
❌ No uses OPA cuando:
- Solo necesitas matching simple
- Quieres máximo rendimiento
- Tienes patrones básicos
- No tienes experiencia con Rego
Próximos Pasos
- Reglas YAML - Para patrones simples
- Reglas JSON - Para configuraciones
- Reglas Semgrep - Para patrones complejos