Protege el desarrollo de tus aplicaciones de Kubernetes con Snyk y Tilt
11 de enero de 2021
0 minutos de lecturaDesarrollar aplicaciones de Kubernetes puede ser difícil. A menudo trabajamos con arquitecturas de microservicios que tienen muchas piezas en movimiento, además de desarrollar la configuración del clúster para conectarlas y crear flujos de trabajo de iteración y pruebas rápidas. Todo esto puede volverse complicado y difícil de gestionar para los equipos de ingeniería.
Aquí es donde entran en juego herramientas como Tilt.
¿Qué es Tilt?
Tilt es una excelente herramienta para desarrolladores que trabajan con aplicaciones de Kubernetes. Ofrece un flujo de trabajo de implementación local altamente configurable que se actualiza en tiempo real mientras trabajas. En lugar de administrar un conjunto centralizado de entornos en los que trabaja todo el equipo, Tilt ofrece a cada desarrollador su propio entorno local, con implementaciones muy rápidas y la posibilidad de personalizar su flujo de trabajo.
Tilt se configura mediante un archivo Tilftfile basado en Starlark y ofrece una interfaz gráfica y un entorno de CLI personalizables, junto con una API completa. Esto te da mucha flexibilidad para definir tus flujos de trabajo y la información que quieres ver mientras desarrollas tu aplicación. Tilt también admite extensiones personalizadas, lo que te ofrece aún más opciones para configurar y ejecutar tu entorno de desarrollo.
Mi colega Shai Mendel contribuyó una extensión para Tilt que permite ejecutar Snyk desde tu Tiltfile. Hace poco dediqué algo de tiempo a actualizar la extensión y explorar las distintas formas en que Snyk puede integrarse en tus flujos de trabajo de Tilt. Veamos cómo funciona.
Cómo empezar
Lo primero que queremos hacer es implementar un clúster de Kubernetes localmente, junto con un registro. Tilt ofrece una herramienta que facilita mucho esta tarea. Ctlptl admite varias formas de ejecutar Kubernetes localmente, como miniKube, Kind y Docker Desktop. Yo usaré Kind, que primero debes instalar.
Este comando implementará un clúster de Kubernetes con Kind y también implementará un registro en tu Docker local, además de configurar todo lo necesario para que Kubernetes lo use. Cuando el comando termine, podremos ver en Docker que se implementaron ambos:
A continuación, clonaré una aplicación de ejemplo para usarla en las pruebas. Usaré el ejemplo de Node.js que ofrece Tilt. Esta aplicación incluye varios Tiltfiles de ejemplo con buenas prácticas para usar Tilt, además de una publicación de blog que los explica
Para esta publicación, usaremos el ejemplo de Dockerfile optimizado. Veamos el Tiltfile proporcionado:
Si analizamos lo que hace este Tiltfile, usa la función docker_build para crear example-node-js-image a partir del Dockerfile de esta carpeta. También crea un recurso k8s_yaml mediante el archivo kubernetes.yaml y lo asocia con un recurso k8s_resource, con un reenvío de puerto al puerto 8000. También define un recurso local_resource, que escribe la hora actual en un archivo y crea una dependencia entre este y k8s_resource. Esto significa que siempre se ejecutará antes de actualizar el recurso y permite medir el tiempo de implementación. Puedes leer más sobre todas las funciones que admite la API de Tiltfile en la documentación.
También tenemos un Dockerfile que instala las dependencias que necesita nuestra aplicación con yarn:
Y nuestra aplicación es una aplicación de Node.js muy sencilla que solo muestra una página web en el puerto 8000:
Ahora que implementamos el clúster, podemos iniciar Tilt. Desde la carpeta que contiene nuestro Tiltfile, solo tenemos que ejecutar:
Con Tilt ejecutándose en la terminal, podemos presionar la barra espaciadora para abrir la interfaz de Tilt en el navegador.

Tilt ejecutará el Tiltfile y activará todos los recursos definidos; en nuestro caso, creará la imagen, la implementará en Kubernetes y creará un reenvío de puerto para acceder a la aplicación.
Con kubectl podemos ver que el pod que ejecuta la aplicación está en ejecución:
Si ahora vamos a http://localhost:8000, podremos ver la aplicación:

Una vez que Tilt está en ejecución, cualquier cambio que hagamos en los directorios y archivos supervisados volverá a ejecutar el Tiltfile y creará e implementará automáticamente la aplicación.
Ahora veamos cómo integrar Snyk en este flujo de trabajo. Si aún no lo hiciste, tendrás que instalar la CLI de Snyk y registrarte para obtener una cuenta gratuita de Snyk.
Lo primero que debemos hacer es cargar la extensión de Snyk, lo cual hacemos en el Tiltfile:
Al hacerlo, verás que Tilt vuelve a ejecutar el Tiltfile automáticamente. En la carpeta de nuestra aplicación aparecerá un directorio tilt_modules que contiene la extensión de Snyk. Las extensiones son Tiltfiles que se cargan en el Tiltfile principal.
Ahora que cargamos la extensión de Snyk, podemos usarla para agregar Snyk a nuestro flujo de trabajo de Tilt. La extensión admite los tres modos disponibles en la CLI de Snyk, así que podemos analizar contenedores, dependencias de paquetes y archivos de infraestructura como código, en este caso, archivos YAML de Kubernetes. Además, está diseñada para ofrecer la mayor flexibilidad posible y permitirte crear distintos flujos de trabajo en Tilt.
Primero, veamos cómo analizar nuestro YAML de Kubernetes. En el Tiltfile, llamamos a la extensión de Snyk y la configuramos para analizar el archivo kubernetes.yaml:
La extensión admite varios argumentos; puedes consultar toda la documentación en el README. Aquí seleccionamos kubernetes.yaml, especificamos que queremos un análisis de IaC, asignamos un nombre a este recurso, definimos el modo como informativo y configuramos el activador como manual. La marca de modo puede ser info o gate. En el modo info, el comando siempre termina con un código de retorno cero, incluso si encuentra vulnerabilidades, por lo que no se considera un error en la interfaz de Tilt. Si configuramos el activador como auto, el análisis se ejecutará cada vez que Tilt detecte cambios en kubernetes.yaml. En el modo manual, tendremos que iniciarlo desde la interfaz de Tilt.
Cuando guardamos el Tiltfile, vemos un nuevo enlace en la barra lateral de la interfaz de Tilt, titulado snyk-iac-manual.

Esta opción tiene un botón de actualizar, lo que indica que podemos ejecutarla manualmente. Vamos a hacerlo.

Al ejecutarla, vemos que se llama a la CLI de Snyk para analizar kubernetes.yaml y que los resultados del análisis aparecen en la interfaz. Aunque identificamos varios posibles problemas de seguridad en ese archivo, la prueba sigue apareciendo como completada correctamente porque configuramos el modo informativo. Veamos qué ocurre si lo configuramos en modo gate. En el Tiltfile, cambia la configuración de esta comprobación:
Lo primero que vemos en la interfaz después de que se vuelve a ejecutar el Tiltfile es que el botón de actualizar de nuestra comprobación manual está resaltado, lo que significa que no está sincronizada con las demás etapas y hay que actualizarla.

Ahora volvamos a ejecutar la configuración actualizada:

Como ahora configuramos el recurso en modo gate, Tilt lo detecta como un error de compilación.
Ahora veamos las opciones para integrar el análisis de contenedores en nuestro flujo de trabajo de Tilt. Algo importante que debes tener en cuenta es que Tilt usa etiquetas inmutables. Por eso, cada compilación recibe una etiqueta única que también se transfiere a Kubernetes. Esto acelera el proceso de implementación. Puedes leer más detalles aquí.
De forma predeterminada, al usar la función docker_build, verás muchas de estas etiquetas inmutables al consultar las imágenes en Docker:
Esto también plantea un desafío a la hora de analizarlas, ya que actualmente no hay una función integrada que permita acceder a estas etiquetas desde otras partes del Tiltfile, y necesitamos conocer la etiqueta de la imagen para analizarla con Snyk.
Sin embargo, tenemos un par de opciones para hacerlo. Tilt ofrece una función para definir tus propios pasos de compilación, que podemos usar para crear nuestro flujo de trabajo.
Primero, veamos cómo configurar un paso de análisis manual. Para ello, haremos que la etiqueta de nuestra imagen sea mutable: fijaremos la etiqueta para que todas nuestras compilaciones tengan la misma. Luego, Tilt volverá a etiquetar la compilación con una etiqueta inmutable antes de implementarla.
En nuestro Tiltfile, eliminemos la función docker_build y reemplazémosla por una custom_build:
Aquí llamaremos a Docker, igual que lo haría la función docker_build, pero agregaremos la variable de entorno especial $EXPECTED_REF y también especificamos tag=’dev’,, que Tilt usará para asignar un valor a esa variable. Cuando guardemos el Tiltfile, veremos que Tilt creó una imagen con una etiqueta mutable y luego le asignó otra etiqueta:
Aquí definimos como destino la etiqueta conocida, especificamos el modo de contenedor, asignamos un nombre al análisis, definimos el modo como informativo y, como tenemos el Dockerfile en nuestro directorio, también podemos agregarlo al argumento extra_opts para obtener sugerencias sobre la imagen base.

Ahora tenemos el análisis manual de contenedores en la barra lateral y podemos ejecutarlo.

Ya iniciamos manualmente el análisis de contenedores, pero ¿qué pasa si queremos que se ejecute automáticamente en cada compilación de Tilt? Este caso es un poco más complicado, ya que Tilt no ofrece una gestión muy desarrollada de las dependencias previas o posteriores a la compilación. Podríamos llamar a Snyk directamente desde la función custom_build, pero el objetivo de diseño de la extensión es ofrecer a los usuarios una forma flexible de integrar los análisis de Snyk en sus flujos de trabajo.
Primero, modifiquemos nuestra función custom_build. Quitaremos el argumento tag=’dev’, con lo que $EXPECTED_REF recibirá la etiqueta inmutable que Tilt genera automáticamente. Luego, en cada compilación, tomaremos esa etiqueta y la escribiremos en un archivo en nuestro sistema de archivos. Usamos printf para evitar que se agreguen saltos de línea al final de la etiqueta cuando la escribimos en el archivo.
También agregaremos una función para obtener la etiqueta del archivo. La función read_file devuelve un blob, así que tenemos que convertirlo en una cadena y quitar los saltos de línea:
Luego llamaremos a la extensión de Snyk, configuraremos el destino con el resultado de nuestra función get_tag, estableceremos el activador en auto y crearemos una dependencia del archivo en el sistema de archivos para que la extensión se ejecute cada vez que cambie.
Cuando volvemos a guardar el Tiltfile, vemos que cada vez que se ejecuta nuestra compilación, también se inicia automáticamente el
análisis de Snyk.

Por último, veamos cómo analizar las dependencias del código fuente de nuestra aplicación. Como se trata de una aplicación de Node.js que usa yarn como administrador de paquetes, tenemos un archivo yarn.lock en la carpeta que muestra las versiones de los módulos que usamos.
Podemos analizarlo automáticamente con Snyk para buscar vulnerabilidades:

En este caso, la aplicación es muy sencilla y ninguna de sus dependencias tiene vulnerabilidades, así que todo está bien.
Tilt es una herramienta fantástica que puede acelerar considerablemente el desarrollo local de aplicaciones basadas en microservicios para Kubernetes. Además, ofrece muchísimas opciones de configuración para que puedas crear el flujo de trabajo que mejor se adapte a ti.
En esta publicación, vimos las distintas formas de integrar los análisis de Snyk en tus flujos de trabajo de Tilt mediante la extensión de Snyk para Tilt, para garantizar la seguridad de tus aplicaciones nativas de la nube y sus configuraciones. Regístrate para obtener una cuenta gratuita de Snyk y pruébala.
Empieza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.


