Skip to main content

Habilitar políticas como código (PaC) con OPA y Rego

Escrito por
blog feature snyk iac magenta

19 de enero de 2022

0 minutos de lectura

El Cambridge Dictionary define una política como: «un conjunto de ideas o un plan sobre qué hacer en situaciones particulares, que ha sido acordado oficialmente por un grupo de personas, una organización empresarial, un gobierno o un partido político». En el contexto del desarrollo de software, tu organización puede tener reglas sobre cómo se crea, configura, implementa y utiliza una política. Algunos ejemplos de políticas de software son:

Políticas de aplicaciones

  • Solo los usuarios internos pueden acceder a ciertos contextos de servicios web.

  • Las funciones regionales solo se mostrarán en las solicitudes de usuarios con direcciones IP de la misma ubicación geográfica.

  • Solo los usuarios con cargos gerenciales pueden realizar transacciones por encima de ciertos montos.

Políticas de compilación e implementación

  • Todas las bibliotecas de aplicaciones de código abierto deben usar una de las licencias aprobadas.

  • Todas las imágenes de contenedor deben descargarse de registros específicos.

  • Ningún Pod de Kubernetes debe ejecutarse en modo Privileged.

  • El token predeterminado de un ServiceAccount no debe montarse automáticamente en un contenedor.

Las políticas como código (PaC)consisten en definir políticas en código mediante un lenguaje declarativo de alto nivel, lo que permite automatizar su cumplimiento y administrarlas de forma centralizada. Esto reduce la necesidad de duplicar lógica en los servicios de tu aplicación, que están cada vez más distribuidos y pueden usar una amplia variedad de lenguajes y plataformas.

En este blog, veremos Open Policy Agent (OPA) y su lenguaje de reglas Rego, que pueden ayudarte a optimizar tus iniciativas de PaC, tanto para tus propias aplicaciones como para aplicar políticas a las cargas de trabajo en contenedores en Kubernetes.

Definición uniforme de políticas en servicios diversos

La aplicación de políticas suele implementarse directamente en el código. En los sistemas distribuidos actuales, es posible que se duplique la misma lógica. El problema puede agravarse si esos servicios distintos son desarrollados por diferentes equipos o con tecnologías diferentes.

Es fundamental contar con definiciones de políticas estandarizadas y herramientas para aplicarlas que puedan usar todos los equipos de tu organización, sin importar el lenguaje en el que estén escritas o los frameworks que utilicen. Las definiciones uniformes de políticas permiten una implementación sencilla y flexible, así como una gestión del cumplimiento más fácil para todas las personas involucradas.

Aplicación proactiva vs. reactiva de políticas de compilación e implementación

Las reglas de políticas de compilación e implementación suelen hacerse cumplir mediante una combinación de revisiones manuales de código, análisis estático (idealmente automatizado en tu pipeline de CI/CD) o, simplemente, la amenaza de medidas disciplinarias si alguien incumple la política. Estas prácticas son reactivas: nos alertan sobre las infracciones cuando se realiza algún tipo de auditoría. Puede funcionar, pero a menudo crea una relación conflictiva entre quienes definen las políticas y los desarrolladores, que quizá no sepan que existen esas reglas.

Implementar las políticas y hacerlas cumplir dentro del flujo de trabajo de los desarrolladores, como parte de sus procesos de compilación o como condición para la implementación, permite detener las infracciones en el momento en que se producen, en lugar de depender de auditorías tardías o revisiones manuales.

Aplicación uniforme de políticas en entornos diversos

Una vez que hayas unificado tus reglas de políticas en una plataforma compartida, podrás aplicarlas de manera uniforme en todos los entornos. Por ejemplo, si tu clúster de Kubernetes de desarrollo permite implementar cualquier cosa sin restricciones, pero tu clúster de producción tiene varias restricciones, es posible que los desarrolladores no se den cuenta de que implementaron algo que infringe las políticas hasta más adelante en el ciclo de vida del desarrollo de software (SDLC). Sin embargo, si todos los clústeres comparten el mismo conjunto de reglas, es mucho menos probable que esas infracciones lleguen al control de versiones, porque se habrían detectado durante las pruebas unitarias iniciales.

Open Policy Agent (OPA)

Open Policy Agent, al que normalmente se hace referencia por sus siglas OPA y se pronuncia «oh-pah», es un proyecto de código abierto que se graduó de la CNCF y que implementa un motor de políticas de propósito general. Se usa ampliamente tanto para las políticas de aplicaciones —especialmente en arquitecturas distribuidas de microservicios— como controlador de admisión de la API de Kubernetes, donde suele integrarse mediante el proyecto OPA Gatekeeper.

Las aplicaciones pueden delegar la validación de políticas a OPA, lo que elimina la necesidad de acoplar estrechamente esa lógica a su base de código. En la práctica, suele iniciarse un proceso de OPA junto al servicio de la aplicación, que expone una API REST con la que la aplicación se comunica. En una implementación de Kubernetes, esto suele hacerse mediante un contenedor sidecar en el mismo Pod que el contenedor del servicio, lo que proporciona una conexión «localhost» de latencia extremadamente baja, aunque también puede ejecutarse como un servicio externo. Hay otras formas de incluir OPA en tu aplicación; al momento de escribir este artículo, incluyen una API de Go, WebAssembly y un SDK para integrar OPA en una aplicación de Go.

Las políticas de OPA se escriben como un conjunto de reglas en un lenguaje llamado Rego.

Rego: el lenguaje de reglas de políticas de OPA

Rego es un lenguaje declarativo de alto nivel diseñado para implementar reglas sobre documentos estructurados, como JSON. En este artículo no podemos incluir un tutorial detallado sobre cómo escribir reglas Rego, pero te recomiendo consultar la documentación oficial y el excelente curso de aprendizaje de Styra, creadores de OPA y Rego.

Conceptos básicos de Rego

Rego trabaja con documentos de datos estructurados de varias maneras, pero el patrón más común consiste en que el proceso que lo invoca pase un documento, a menudo en formato JSON o YAML, como entrada. Después, las reglas se aplican comparando elementos de ese documento de entrada con expresiones.

Por ejemplo, supongamos que tenemos una política de validación de Pods de Kubernetes que devuelve true siempre que el valor de image de la entrada no termine en ":latest". Una implementación sencilla de esta política en Rego podría verse así:

package kubernetes.validating.images

import future.keywords.in

default allow = false

allow {
    input.kind == "Pod"
some container in input.spec.containers
not endswith(container.image, ":latest")
}

Si se ejecuta el siguiente JSON con esa política, se devolverá la respuesta { “allow”: false } porque ":latest" no está al final de la imagen.

{
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
        "name": "mypod",
        "labels": { "run": "mypod" }
    },
    "spec": {
        "containers": [
            {
                "name": "mypod",
                "image": "registry.mycorp.com/team-alpha/myapp:v1",
            }
        ]
    }
}

Recorrido de un ejemplo de Rego

Veamos el código Rego del ejemplo anterior:

package kubernetes.validating.images

Aquí declaramos a qué paquete pertenece la regla. Esto es similar a los sistemas de paquetes de otros lenguajes y sirve para agrupar reglas relacionadas en el mismo espacio de nombres.

import future.keywords.in

La palabra clave import le indica al analizador de Rego que incorpore la regla in del paquete future.keyworks al ámbito de esta política, para que se pueda hacer referencia a ella simplemente como in.

default allow = false

"Esto define el valor predeterminado de allow como "false" si ninguna otra expresión de asignación de la política lo establece de otro modo.

allow {
    input.kind == "Pod"
    some container in input.spec.containers
    not endswith(container.image, ":latest")
}

Aquí vemos la mayor parte de la lógica de la regla. Al ejecutarse, se asignará a allow el resultado de evaluar el contenido dentro de las llaves { }. Todas las expresiones dentro de esas llaves se ejecutan con un «AND» implícito, lo que significa que todas deben evaluarse como «true» para que allow se establezca en «true».

Puedes interpretar las tres líneas así: «Siempre que el valor de input.kind sea "Pod" y haya al menos algunos contenedores en input.spec, devuelve "true", a menos que alguno de los campos image de los contenedores termine en ":latest"».

Rego Playground

El proyecto OPA ofrece un entorno en línea para editar Rego llamado The Rego Playground, donde puedes experimentar con reglas y ejecutarlas con documentos de entrada cuando quieras. Es una excelente manera de probar tus ideas de reglas de forma interactiva y compartir tus experimentos con otras personas.

La interfaz de Rego Playground muestra una política de validación de imágenes de Kubernetes, una entrada JSON de Pod y un resultado que indica allow: true

El código Rego y el documento de entrada anteriores están disponibles en este ejemplo de Rego Playground. Ábrelo en otra pestaña, ejecútalo y experimenta con él.

Escribe políticas personalizadas con Snyk IaC y Rego

Snyk Infrastructure as Code (Snyk IaC) usa OPA para analizar políticas y puedes agregar tus propias políticas a los análisis con unos cuantos comandos sencillos. Para comenzar, consulta la documentación de Snyk IaC y nuestro artículo Desarrollo de reglas de IaC personalizadas con Snyk,.

Al comenzar con una cuenta gratuita de Snyk, puedes identificar y corregir errores de configuración de IaC al integrar sin problemas en tus flujos de trabajo verificaciones de seguridad, controles de políticas y recomendaciones de corrección fáciles de seguir para los desarrolladores.

Protege la infraestructura desde el origen

Snyk automatiza la seguridad y el cumplimiento de IaC en los flujos de trabajo, y detecta recursos con desviaciones de configuración y recursos faltantes.

Recursos para obtener más información

Ahora que tienes una idea general de OPA y Rego, y conoces algunas de sus aplicaciones, te invito a explorar las muchas maneras en que puedes aprovecharlos en tu software:

¡Gracias por leer y que te diviertas automatizando la aplicación de políticas!

Leer más

blog feature snyk container custom base recommendations
Blog

Presentamos Evo Agentic AppSec: seguridad al ritmo del desarrollo con IA

El desarrollo impulsado por IA supera el ritmo de los flujos de trabajo de seguridad tradicionales. Agentic AppSec de Snyk usa agentes de seguridad para encontrar, corregir y verificar vulnerabilidades de forma continua, mientras las personas definen el estándar.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Evo ADS Govern Agent Behavior ya está disponible: controla el uso de MCP

Evo ADS Govern Agent Behavior ya está disponible, comenzando con MCP Governance. Descubre, aprueba, monitorea, registra y bloquea el uso de servidores MCP en los principales agentes de programación con IA.