Herramientas de código abierto para probar código de Terraform
Stephane Jourdan
14 de mayo de 2020
0 minutos de lecturaNota del editor: Esta publicación apareció originalmente en CloudSkiff.com. CloudSkiff se unió a Snyk en octubre de 2021.
Las pruebas del código de Terraform son un tema recurrente del que seguimos escuchando. Muchas personas tienen dudas sobre cómo probar código de infraestructura, aunque no vemos que las pruebas se adopten mucho en la práctica. Para empezar, ¿deberías probar tu código? ¿Cuáles son las distintas estrategias para automatizar las pruebas y cuáles son las mejores herramientas de código abierto para hacerlo?
Probar el código de Terraform es fundamental y, sí, deberías hacerlo. Hay muchas formas de hacerlo. Es muy parecido a los procesos de ingeniería de software estándar. Proviene de la misma cultura, así que no es ninguna sorpresa.
Pruebas de código de Terraform: empieza con linters
Puedes ejecutar un linter directamente en tu laptop o en tu sistema de CI/CD para asegurarte de que los demás respeten ciertas convenciones de código o estándares.
Uno de los linters de Terraform que más me gusta se llama TFLint. Es de código abierto y está disponible en GitHub. Es un linter «a la manera de la infraestructura», lo que significa que analiza tu código de una forma que terraform validate no lo haría. terraform validate es un subcomando de Terraform. Básicamente, solo comprueba que la estructura sea válida, no que el contenido lo sea. Esto significa que, si solicitas un tipo de máquina de AWS incorrecto, terraform validate no lo detectará como un error, mientras que TFLint sí.
Así se vería un commit con errores:

Y así se detectaría y aparecería en tus registros:


Este linter también puede hacer un «análisis profundo», que va más allá de un análisis básico.
Imagina que necesitas solicitar una VM válida que ya existe, por ejemplo, una instancia T3 large. Si tu cuenta ya no tiene capacidad disponible (por ejemplo, porque ya lanzaste todas las VM que podías solicitar), el linter enviará una solicitud a la API de AWS para comprobar que lo que solicitas sea válido y que pueda ejecutarse dentro de los límites de tu cuenta. Hace todo lo que haría un linter adecuado durante el desarrollo —comprobar la calidad, las tabulaciones, etc.— y va más allá del validador y el formateador que puedes encontrar directamente en Terraform.
Un caso de uso habitual sería que hayas hecho todas tus pruebas en un entorno de staging y que los límites de AWS de ese entorno sean muy altos porque, con el tiempo, hiciste decenas de solicitudes cada vez que necesitabas probar algo. Así que quizá tengas cientos o incluso miles de instancias permitidas en cada región.
Pero luego decides promover un nuevo cambio a producción y quizá tu entorno de producción no tenga las mismas reglas ni los mismos límites de la cuenta de AWS. Entonces promoverás algo que no funcionará en producción.
El linter de análisis profundo se asegurará de que lo que estés a punto de promover o lanzar desde staging, desarrollo o cualquier otro entorno a producción realmente pueda ejecutarse con los permisos de tu cuenta.
Haz pruebas unitarias de tu código de Terraform con TDD
Un flujo de trabajo de ingeniería ágil adecuado comenzaría con el desarrollo guiado por pruebas (TDD).
Cuando empiezas a trabajar con TDD, escribes pruebas unitarias, por ejemplo: «Bueno, quiero crear mi VPC y se supone que debe tener este espacio de direcciones». El siguiente paso es escribir tu función (en Terraform se llama recurso) y luego ejecutarla. Como veremos más adelante, usaría cualquier herramienta derivada de RSpec para esto: Serverspec, InSpec… Tus pasos de TDD serían más o menos así:
Empieza por escribir la prueba: falla
Escribe el recurso y no falla porque se lanzará en un entorno aislado (sobre todo esa VPC).
Con este proceso, probarás lo que querías y luego lo destruirás. Puedes hacer exactamente lo mismo que harías en ingeniería, por ejemplo, en tu CI: ejecutar todas las pruebas en los pull request. Por cierto, decidir cuánta seguridad quieres al empezar a hacer pruebas es un tema delicado. Personalmente, ejecuto todas las pruebas antes de fusionar cualquier cosa, pero hago menos durante la fase del pull request, porque ejecutar todas las pruebas todo el tiempo, en cada commit, puede tardar mucho.
Haz pruebas de integración
Otra cosa que puedes hacer, bastante común en los procesos de QA, es aleatorizar elementos como las variables. Terratest es otra herramienta excelente para las pruebas de integración. Probablemente sea la más completa, pero también la más compleja.
Veamos esto con más detalle.
Terratest es una biblioteca de Go. Se necesitan conocimientos para dominarla (bueno, es Go…), pero te permite probar cualquier cosa que tenga una API, como AWS, Azure, Google Cloud, Kubernetes, imágenes de Docker, compilaciones de Packer… (Packer es la herramienta de HashiCorp para crear AMI: imágenes de disco de máquinas virtuales) e incluso charts de Helm.
Básicamente, solo tienes que crear el archivo resource_test.go, importar tus bibliotecas y ejecutarlo. Pero se necesita cierto nivel de conocimientos de Go y un conocimiento profundo de lo que quieres probar.
Aleatoriza elementos
Durante esta fase de integración, aleatorizaría elementos como los nombres de las regiones. Por lo general, siempre pruebas tu código en la misma región. Al aleatorizarla, obtendrás resultados distintos y te asegurarás de que funcione.
Quizá los nombres que usas sean únicos, al igual que los nombres de tus recursos. Por ejemplo, tu bucket de Amazon S3 debe ser único. El proceso es el mismo que en un proyecto de ingeniería:
Usa las herramientas
Analiza tu código con un linter
Haz pruebas unitarias de tus archivos
Aleatoriza esos elementos
Integra los resultados en tu CI
Agrega eso a tus pull request
Etiqueta tu código y tus versiones (por ejemplo, master)
Usa ramas de funcionalidades, fusiónalas con master y luego publica una versión del código
Otras herramientas que recomendamos para probar tu código de infraestructura
Mencioné todas las herramientas derivadas de RSpec para esto: Serverspec, InSpec… InSpec es de Chef, mientras que Serverspec, creo, cuenta más con el apoyo de la comunidad.
Serverspec está diseñado para pruebas unitarias, pero no se dedica exclusivamente a Terraform; es más general. Puedes probar cualquier cosa, desde infraestructura e imágenes de Docker hasta procesos que se ejecutan en un servidor y otros elementos similares. Además, es fácil de leer: se parece al inglés. Es realmente genérico porque no prueba el código directamente ni se corresponde de forma directa con el código de Terraform de tu repositorio de infraestructura, sino que prueba lo que se lanzó en la realidad. Por ejemplo, si agregas una nueva funcionalidad, quizá una base de datos en Google Cloud, y quieres comprobar que el puerto «5.4.3.2» esté abierto, puedes escribir y ejecutar esta prueba. Así tendrás la certeza, para siempre, de que algo responde en ese puerto. Serverspec puede ayudarte a hacerlo de forma rápida y sencilla.
Hay otra herramienta que me gusta mucho, llamada GOSS. Es de código abierto y muy buena. Es muy sencilla y está basada en YAML. No está pensada para probar código de Terraform, sino para probar los resultados. Por ejemplo, creaste un grupo de seguridad y quieres asegurarte de que el puerto 22 para SSH esté cerrado. Puedes probar eso, además de procesos, paquetes, resolutores DNS, usuarios… o comprobar si responde tu endpoint HTTP en Kubernetes, entre otras cosas.
Creo que incluso puede generar los resultados de las pruebas en un formato compatible con Nagios, así que también puedes ejecutarla como un punto /health en tu microservicio para asegurarte de que todo funcione correctamente. Es muy sencilla y ligera. Me gusta mucho esta herramienta. Funciona muy bien con archivos de Docker, etc.
Prueba tu código de Terraform
GOSS para tareas muy básicas y sencillas: usa YAML simple, es un binario simple y muy fácil de usar. Serverspec e InSpec para todas las pruebas unitarias, y todo es de código abierto.
Y, por supuesto, Terratest para la integración. Es muy completa. Integra todo eso en tu sistema de CI/CD, o al menos ejecútalo antes de distribuirlo o publicarlo. Si no, tendrás problemas, ¿no?
Para probar si tu código de Terraform tiene vulnerabilidades de seguridad, Snyk IaC puede analizar tus configuraciones de Terraform (¡y también las plantillas de Kubernetes, CloudFormation y ARM!) mientras programas, y ofrecerte correcciones guiadas para que puedas fusionar los cambios y seguir adelante. Puedes probar mientras escribes, monitorear los cambios en tus repositorios de Git y automatizar las pruebas en tus pipelines de compilación antes del despliegue. Empezar con un plan gratuito toma solo unos minutos, mientras que una filtración causada por una configuración incorrecta de IaC puede provocar daños para toda la vida. Regístrate y empieza a proteger tus configuraciones a continuación.
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.
