Skip to main content

Verificación de los ID de AMI de AWS en Terraform con Regula y Open Policy Agent

Escrito por
blog hero iac drift purple

7 de octubre de 2021

0 minutos de lectura

La semana pasada anunciamos Fugue IaC, que permite a los equipos de ingeniería de la nube proteger su infraestructura como código (IaC) y el entorno de ejecución en la nube con las mismas políticas. Para ejecutar comprobaciones de IaC de forma local, Fugue desarrolló Regula, una herramienta de código abierto basada en Open Policy Agent (OPA).

Regula se puede usar con Fugue o sin él. Incluye cientos de reglas listas para usar, diseñadas para comprobar infraestructura como código (IaC) en Terraform y CloudFormation, así como manifiestos de Kubernetes. Estas reglas están alineadas con los CIS Benchmarks y cubren muchas vulnerabilidades de seguridad.

Sin embargo, a veces quieres aplicar políticas específicas de tu organización; por ejemplo, exigir que las instancias de Amazon EC2 usen AMI aprobadas. En casos como este, puedes escribir una regla personalizada con el lenguaje Rego de OPA, y Regula la aplicará a tu IaC. De esta manera, si tu IaC declara una AMI no aprobada, la comprobación de Regula fallará.

En esta publicación:

  • Escribiremos una regla personalizada para comprobar las AMI de AWS EC2 declaradas en Terraform y explicaremos el código Rego línea por línea.

  • Usaremos nuestra herramienta de código abierto Regula para probar la regla con un archivo de Terraform que no cumple con los requisitos.

  • Corregiremos el Terraform que no cumple con los requisitos.

Ten en cuenta que, aunque en esta publicación usamos Regula para comprobar Terraform HCL, también puedes usar exactamente la misma regla personalizada con Fugue SaaS para comprobar los recursos del entorno de ejecución en la nube. Esto es posible gracias al motor de políticas unificado de Fugue, que permite usar las mismas reglas en IaC y en tiempo de ejecución.

Encontrarás todo el código en este gist de GitHub.

¡Empecemos!

Primeros pasos

Descargar los archivos de código

En nuestro gist de GitHub, selecciona el botón Download ZIP y luego extrae los archivos. Hay dos archivos:

  • approved_ami.rego: una regla personalizada escrita en Rego

  • ami.tf: un archivo Terraform HCL que declara dos instancias EC2, una que cumple con los requisitos y otra que no

Instalar Regula

El siguiente paso es instalar Regula, si aún no lo hiciste. Si usas Homebrew, puedes ejecutar los siguientes comandos en la terminal:

brew tap fugue/regula
brew install regula

También puedes instalar un binario precompilado para tu plataforma o, si prefieres, ejecutar Regula con Docker.

Escribir la regla personalizada

Primero, determinaremos qué tipo de regla escribir. Regula tiene dos tipos de reglas: simples y avanzadas. Las reglas simples son útiles cuando compruebas un solo tipo de recurso. Las reglas avanzadas son mejores para lógica más compleja que involucra varios recursos o comprueba si faltan recursos.

Solo vamos a comprobar un tipo de recurso de Terraform, aws_instance, así que escribiremos una regla simple.

Declaración de paquete

Empecemos por lo básico. Todas las reglas de Regula deben incluir una declaración de paquete que comience con rules. y termine con un identificador breve (línea 4):

package rules.approved_ami

Metadatos

También podemos agregar algunos metadatos (líneas 6-18):

__rego__metadoc__ := {
  "id": "CUSTOM_0002",
  "title": "AWS EC2 instances must use approved AMIs",
  "description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
  "custom": {
    "controls": {
      "CORPORATE-POLICY": [
        "CORPORATE-POLICY_1.2"
      ]
    },
    "severity": "High"
  }
}

No es obligatorio, pero hace que los informes de Regula sean aún más informativos.

Tipo de recurso

A continuación, indicamos qué tipo de recurso de Terraform queremos comprobar (línea 20):

resource_type = "aws_instance"

Esta sintaxis significa que la entrada será una sola instancia de AWS EC2. Cuando Regula aplique la regla a nuestro Terraform, evaluará una instancia a la vez.

Conjunto de AMI aprobadas

Para simplificar, supongamos que tu organización aprobó estos dos ID de AMI:

  • ami-09e67e426f25ce0d7

  • ami-03d5c68bab01f3496

(Por si te da curiosidad, estos son los ID de Ubuntu Server 20.04 LTS HVM, SSD Volume Type en us-east-1 y us-west-2, respectivamente).

Ahora crearemos un conjunto con los ID de las AMI aprobadas. Lo llamaremos approved_amis (líneas 22-26):

approved_amis = {
  # Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
  "ami-09e67e426f25ce0d7", # us-east-1
  "ami-03d5c68bab01f3496" # us-west-2 
}

La regla deny

Por último, escribiremos una regla deny. ¡Aquí es donde está la lógica principal! La regla deny define las condiciones en las que un recurso debe fallar la comprobación.

Vamos a agregar un poco de complejidad y devolver un mensaje de error personalizado que indique el ID de la AMI no aprobada cuando una instancia no supere la comprobación de Regula.

Nuestra regla deny debe comprobar si el ID de AMI de la instancia que se está evaluando pertenece al conjunto de aprobadas. Si no pertenece, deny debe devolver un mensaje de error para ese recurso (es decir, generar un resultado de regla fallido). deny se define en las líneas 28-31:

deny[msg] {
  not approved_amis[input.ami]
  msg = sprintf("%s is not an approved AMI ID", [input.ami])
}

Veamos la lógica más de cerca:

not approved_amis[input.ami]

input.ami representa el atributo ami de cada instancia EC2 en el documento de entrada (tu archivo Terraform HCL o, más específicamente, su representación JSON, que Regula transforma en segundo plano).

not approved_amis[input.ami] se evaluará como true si el atributo ami de la instancia actual no pertenece al conjunto.

En conjunto, la regla deny dice: «Si input.ami no está en approved_amis, la comprobación de Regula debe fallar y devolver un mensaje de error».

Definimos el mensaje de error en esta línea:

msg = sprintf("%s is not an approved AMI ID", [input.ami])

Usa la función integrada de Rego sprintf para mostrar el valor de ami del recurso que se está evaluando.

¡Y esa es nuestra regla personalizada! Aquí está completa. ¡Ahora vamos a probar Regula!

Ejecutar la regla personalizada con Regula

Ahora probemos la regla con un archivo de Terraform sencillo. El Terraform HCL de nuestro gist de GitHub define dos instancias EC2: una instancia «buena» con el ID de AMI aprobado ami-09e67e426f25ce0d7 y una instancia «mala» con el ID de AMI nada sospechoso ami-totallylegitamiid.

Ejecutar Regula

En la terminal, usa cd para ir al directorio que contiene los archivos de código y ejecuta el siguiente comando:

regula run ami.tf --include approved_ami.rego --user-only

Este comando ejecuta nuestra regla personalizada en el archivo de Terraform. La opción --user-only indica que se aplique solo la regla personalizada; para esta publicación, excluimos la biblioteca de reglas integradas de Regula. (Aunque es recomendable usar las reglas integradas, que se incluyen de forma predeterminada al ejecutar regula run).

Veremos el siguiente resultado:

Salida de la terminal que muestra una infracción de la política de AMI de una instancia de AWS EC2: el ID de la AMI no está aprobado.

Como puedes ver, nuestro archivo de Terraform no superó la regla y mostró el mensaje ami-totallylegitamiid is not an approved AMI ID. ¡Excelente! Eso significa que nuestra regla personalizada funcionó. Regula nos indicó que la instancia aws_instance.bad (línea 13, columna 1) no tenía un ID de AMI aprobado.

Consultar un informe más detallado

Para obtener más detalles, veamos el informe completo, con formato JSON:

regula run ami.tf --include approved_ami.rego --user-only --format json

Aquí podemos ver todo el resultado, incluidos todos los resultados de las reglas. Observa que aws_instance.bad vuelve a tener un resultado FAIL, mientras que aws_instance.good tiene un resultado PASS:

{
  "rule_results": [
    {
      "controls": [
        "CORPORATE-POLICY_1.2"
      ],
      "filepath": "ami.tf",
      "input_type": "tf",
      "provider": "aws",
      "resource_id": "aws_instance.bad",
      "resource_type": "aws_instance",
      "rule_description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
      "rule_id": "CUSTOM_0002",
      "rule_message": "ami-totallylegitamiid is not an approved AMI ID",
      "rule_name": "approved_ami",
      "rule_result": "FAIL",
      "rule_severity": "High",
      "rule_summary": "AWS EC2 instances must use approved AMIs",
      "source_location": [
        {
          "path": "ami.tf",
          "line": 13,
          "column": 1
        }
      ]
    },
    {
      "controls": [
        "CORPORATE-POLICY_1.2"
      ],
      "filepath": "ami.tf",
      "input_type": "tf",
      "provider": "aws",
      "resource_id": "aws_instance.good",
      "resource_type": "aws_instance",
      "rule_description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
      "rule_id": "CUSTOM_0002",
      "rule_message": "",
      "rule_name": "approved_ami",
      "rule_result": "PASS",
      "rule_severity": "High",
      "rule_summary": "AWS EC2 instances must use approved AMIs",
      "source_location": [
        {
          "path": "ami.tf",
          "line": 8,
          "column": 1
        }
      ]
    }
  ],
  "summary": {
    "filepaths": [
      "ami.tf"
    ],
    "rule_results": {
      "FAIL": 1,
      "PASS": 1,
      "WAIVED": 0
    },
    "severities": {
      "Critical": 0,
      "High": 1,
      "Informational": 0,
      "Low": 0,
      "Medium": 0,
      "Unknown": 0
    }
  }
}

También puedes ver el resto de los metadatos que definimos antes en la regla.

Corregir el Terraform

Si quieres que Terraform cumpla con los requisitos, puedes editar ami.tf para reemplazar ami-totallylegitamiid por ami-09e67e426f25ce0d7 y volver a ejecutar Regula. Esta vez usaremos el formato de texto predeterminado:

regula run ami.tf --include approved_ami.rego --user-only

Y veremos el siguiente resultado:

No problems found.

¡Listo! Protegimos nuestra IaC de Terraform usando solo AMI aprobadas, como lo demuestra Regula.

Para seguir leyendo

En esta publicación, escribimos una regla personalizada en Rego, usamos Regula para comprobarla con un archivo Terraform HCL y corregimos el Terraform para que cumpliera con los requisitos.

Si quieres obtener más información sobre Regula, visita el sitio de documentación de Regula. Estos recursos también pueden ser útiles:

Seguridad de IaC diseñada para desarrolladores

Snyk protege tu infraestructura como código desde el ciclo de vida del desarrollo de software hasta el runtime en la nube con un motor unificado de políticas como código, para que todos los equipos puedan desarrollar, implementar y operar de forma segura.

Leer más

feature customer snowflake
Article

Seguridad desde el inicio: presentamos la integración de Snyk Studio con Snowflake Cortex Code

Snyk Studio se integra con Snowflake Cortex Code para analizar código generado por IA, dependencias y contenedores en busca de vulnerabilidades durante el desarrollo.

Article

Ataque a la cadena de suministro Miasma: código malicioso detectado en paquetes npm de @redhat-cloud-services

Un gusano de cadena de suministro llamado Miasma fue detectado en decenas de versiones npm de @redhat-cloud-services. El hook malicioso preinstall roba credenciales, sondea identidades en la nube y puede volver a publicar otros paquetes.

Blog

Vulnerabilidades RCE en el programador de tareas Qinglong explotadas para minar criptomonedas

Dos vulnerabilidades de omisión de autenticación (CVE-2026-3965, CVE-2026-4047) en el panel de programación de tareas Qinglong se explotaron para desplegar malware de minería de criptomonedas. Esto es lo que ocurrió, cómo funcionaron los ataques y qué deberían aprender de este incidente quienes operan aplicaciones autohospedadas.