Change Surfers

Review Test Academy 2019

El pasado día 26 de noviembre asistí al evento de Test Academy, un evento orientado a tener un día de aprendizaje y puesta en común de diferentes técnicas sobre la gestión de test, el testing ágil y continuo, pruebas web automatizadas, testing de integración, testing en producción (sí, en producción) y testing exploratorio

Fue una gran oportunidad para aprender de unos magníficos ponentes, que profundizaron en los detalles de todos estos estos temas, lo que permitió poner en común dudas y diferentes abordajes del problema de asegurar la calidad del software construido.

El evento se estructuró en dos tracks paralelos en los que se llevaron a cabo una serie de master class, de hora y media de duración, lo que daba una amplia visión de los temas que se trataba. Así pues, estas fueron mis impresiones de las master class a las que asistí.

Testing Ágil + DevOps

Para empezar la mañana me uní a la master class de que dío Álvaro Díez sobre “Testing Ágil + DevOps”. Un repaso a las mejores prácticas de aseguramiento de la calidad del software entregado, a través de una visión holística de cómo este debe construirse dentro de un marco agilista.  

Empezando por la frase de Clay Shirky “la sociedad no cambia por cambiar de herramientas, cambia por cambiar los comportamientos”, Álvaro hizo una introducción al mindset agilista.

Como desde la ruptura de los silos entre desarrollo y operaciones podemos evolucionar a una concepción DevOps del desarrollo, e ir incluso más allá, al considerar la calidad del desarrollo y la entrega, a una cultura DevOpsQA.

Esta cultura llevaría aparejado dos elementos principales, la automatización, de tareas de forma desatendida y la monitorización de la evolución de los resultados de las mismas.

La forma de llevar a cabo la automatización es la definición de pipelines sobre servidores de CI/CD:

  • Análisis estático de código, con diferentes herramientas como kiwuan, sonar, … que aporten una detección temprana de problemas dentro del código.

  • Pruebas unitarias, usado para dirigir el desarrollo, no acoplado a la implementación, sino al comportamiento del sistema.

  • Pruebas funcionales, dirigido por las peticiones de negocio, con el fin de que establezcan una prueba de aceptación.

  • Evaluación de las pruebas, mediante test de mutación.

  • Pruebas de rendimiento y carga, para estudiar el comportamiento y estabilidad a largo plazo de nuestro sistema.

  • Pruebas de seguridad, para estudiar el comportamiento frente a ataques o aprovechamientos de sploits del sistema.

Y con toda esta información definición de unas Quality Gates, que determinen la idoneidad o no de la puesta en producción del software que desarrollamos, mediante la detección temprana de errores. Así como la elaboración de QA dashboard que muestren la salud del sistema en todo momento.

Ingeniería del caos y QA

Para seguir el día, fuí a la master class de Alex Soto, un referente en este tipo de técnicas. 

Pruebas en producción. Sí, sí en producción, porque a pesar de nuestros esfuerzos de poner a prueba el sistema en la fases tempranas del desarrollo, para obtener un feedback rápido, hay situaciones que sólo se dan en producción y o no podemos emularlas o incluso desconocemos los mecanismos por lo que se producen. Son situaciones que se producen como resultado de uno o varios problemas que se dan en el sistema, en un momento dado.

Por ejemplo, en una arquitectura de microservicios, ¿que pasa si caen uno o varios servicios?, ¿cómo se comportará todo el sistema en su conjunto?. O algo simple como modificar la fecha del servidor, ¿cómo afecta al sistema?, ¿y si caduca un certificado?.

A pesar de tener un nombre muy exótico, ingeniería del caos o caos testing, es una técnica basada en una concepción científica del proceso de testing. Es decir, elaboramos una hipótesis, llevaremos a cabo un experimento y corroboramos la hipótesis establecida y llevaremos a cabo las acciones correctoras necesarias.

Para ello se establecen varias fases:

  • Estado inicial: partimos de un estado estable del sistema, donde todo funciona correctamente y cumple con las especificaciones del mismo.

  • Hipótesis: nos preguntaremos por cosas que no sabemos cómo van a impactar en el sistema en producción, como las antes descritas.

  • Ejecución: llevaremos a cabo la introducción de errores deliberados en el sistema. Este experimento lo deberemos aislar, por ejemplo con canary release o dark canaries.

  • Validación: identificamos los problemas comprandolos con el estado inicial.

  • Corrección: y llevaremos a cabo las acciones correctoras necesarias.

Algo muy importante a tener en cuenta es que este procedimiento se debe de llevar a cabo con el conocimiento del mismo por parte de todos los impactados por él. Por ejemplo, no deben llevarlo a cabo personas de desarrollo sin que la gente de operaciones esté alertada. 

Varias son las herramientas que se especializan en llevar a cabo esta técnica de testing como Istio, que permite automatizar las acciones sobre kubernetes, chaos toolkit, que tiene plugins para acceder a servicios de google cloud, AWS, kubernetes, etc,  …

Y por supuesto, todo esto se basa en tener un botón (mecanismos rápidos) de poner el sistema de nuevo en un estado estable. No podemos introducir caos, que por alguna razón crezca descontroladamente y no podamos parar y volver a una situación estable.

Automatización de Pruebas

Después de comer, con las pilas cargadas, fui a la master class de Francisco Guerrero, donde hizo una descripción de qué es un framework de automatización de pruebas, y de que debe proveer. 

Un framework de automatización de pruebas es un conjunto de herramientas y librerías integradas, que permite crear, ejecutar y reportar casos de prueba de forma más sencilla y eficiente por parte de los usuarios del mismo, disminuyendo así el coste del mantenimiento de estos casos de prueba.

Son muchas las herramientas de testing a integrar para la creación de casos de prueba:

  • pruebas de UI: selenium, cypress, ...

  • pruebas de API: soupUI, postman, karate, ...

  • pruebas de rendimiento: gatling, jmeter, …

  • pruebas centradas en la aceptación de usuario: cucumber, gauge, ...

Un buen framework de pruebas las debe conseguir:

  • que la automatización de pruebas sea fácil, tanto la creación del caso de prueba a automatizar con a su mantenimiento.

  • que crear y gestionar la infraestructura necesaria para soportar la ejecución de pruebas automáticas.

  • garantizar que el rendimiento de la ejecución de las pruebas es bueno y optimizar los tiempos de ejecución.

  • automatizar progresivamente las pruebas manuales y por tanto dar más tiempo a los testers manuales para diseñar y ejecutar pruebas manuales más complejas, hacer testing exploratorio, etc ..

Elementos de la arquitectura de un framework de pruebas:

  • módulo de API: maneja elementos de autenticación, comunicación de red, ...

  • módulo de UI: integración con selenium, modelado de page objects, ...

  • módulo de datos: provee de usuarios y datos para cada uno de los casos de prueba.

  • módulo de reporte: permite la generación de informes en diferentes formatos (html, xml, json) y la inclusión de elementos como

  • módulo de paralelización: maneja la ejecución concurrente de casos de prueba, disponibilizado el uso de selenium grid.

Y no hay que olvidar integrar en el framework a resto de perfiles y roles no técnicos de la organización bajo una herramienta de BDD, como cucumber o , la cual permite compartir el conocimiento mediante la discusión sobre ejemplos.

Pruebas de Seguridad

Para acabar la jornada me uní a la master class de testing de seguridad, otro elemento del testing al que no se le presta la atención adecuada durante todo el ciclo de construcción del software. 

Así, igual que antes hablamos de DevOpsQA, como la inclusión de la cultura de la calidad del código durante los primeros pasos de su desarrollo, Rodrigo Jiménez aboga por una cultura DevSecOps, donde se incluya los aspectos de seguridad durante todo el ciclo de desarrollo. 

Proponiendo una serie de herramientas a aplicar en las diferentes fases del desarrollo, como:

Seguridad en los repositorios de código: vigilando que no se añadan credenciales (passwords o tokens) en los repositorios de código: GITROB, GIT-SECRETS.

Seguridad en el FrontEnd: aspectos a vigilar

  • QA: Elementos correctos en formularios y Logouts correctos.

  • Cifrado de las comunicaciones en tránsito con TLS/SSL.

  • Configuración segura de servidores Web, ej: nginx, apache.

  • SAST: Análisis de código del frontal (retireJS, nodejsScan).

  • Protección de servicios WEB (WAF).

  • Restricción de métodos http, responder a los definidos por contrato.

  • No mostrar secretos en la URL, es decir, no incluir keys internas.

Seguridad en el BackEnd:

  • QA: Testing de seguridad: prevención de inyecciones o escaneos. Pruebas funcionales (de permisos, de las cabeceras seguridad...).

  • SAST: análisis de seguridad del código fuente de aplicativos software. Ejemplo: Kiuwan, Sonatype, Bandit, Checkmarx, Findbugs, etc.

  • DAST: análisis de seguridad dinámico de aplicativos software. Ejemplo: ZAProxy (OWASP).

  • Librerías de desarrollo: análisis de seguridad entre dependencias de librerías. Ejemplo. Dependency-check, Snyk, retireJS, etc.

Seguridad en la Bases de datos:

  • Cambiar valores por defecto: Claves. Passwords. Configuración.

  • Punto único de acceso.

  • Cifrado de datos: Cifrado en reposo. Cifrado en tránsito.

  • Programación Backup’s.

  • Protección contra Inyecciones de código.

  • Perfilado de usuarios.

  • Inhabilitar servicios/usuarios que no se usen.

Seguridad de Contenedores:

  • DockerIgnore: - limpieza en la construcción.

  • From desde versiones específicas. Evitar el uso del tag: latest.

  • Usar imágenes de orígenes confiables: Docker Content Trust / Notary.

  • Puertos abiertos: ofrecer los servicios mínimos necesarios hacia fuera.

  • No definir secretos en abierto.

  • Aplicación de los parches de seguridad necesarios.

  • Políticas de seguridad habilitadas en contenedores.

  • Usuarios solo con los privilegios necesarios.

  • Gestión de un único proceso por contenedor.

  • Herramientas de análisis de vulnerabilidades sobre contenedores: Clair, Dadga, Anchore, Twistlock ...

Seguridad de Comunicaciones:

  • Protocolos de autenticación (basic auth, OAuth1-2, JSON web tokens, APIKeys).

  • Cifrado de los datos en tránsito: TLS/SSL. SSH. VPN.

  • Evitar comunicaciones en texto claro: HTTP. TELNET. VNC.

Seguridad de Credenciales/autenticación:

  • Fortaleza de credenciales / autenticación: Complejidad de Contraseñas. Doble Factor (ej: google authenticator). Rotación contraseñas. No almacenar las contraseñas en claro (hash + salt). Almacenamiento de forma segura (vault, docker secrets). No compartir credenciales entre personas ni procesos. (trazabilidad). Las credenciales no deben viajar en las URLs (https://example.com/controller//action?apiKey=a53f435643de32). Protocolos de autenticación: basic auth, OAuth1-2, JSON web tokens, API Keys, certificados, etc.

  • Ciclo de vida de las credenciales. Gestión de bajas de cuentas/recuperación.

  • Perfilado de usuarios (RBAC). Mínimo permiso necesario.

Y, como no, dentro del desarrollo moderno de software se describió la inclusión de análisis de seguridad en los pipelines de integración continuo y despliegue continuo.

Y con esto se acabó la jornada. Fue un intenso día de aprendizaje, tanto de las master class, como de las conversaciones surgidas a partir de los problemas expuestos por los ponentes y las diferentes visiones que los asistentes a dichas master class.