Error de autenticación en actualizaciones de PMM de Percona
En nuestro día a día, donde la tecnología y los sistemas informáticos desempeñan un papel fundamental en la operación empresarial, es esencial contar con herramientas de monitorización y observabilidad robustas que nos permitan garantizar la eficiencia y la disponibilidad de nuestros sistemas críticos. En esta ocasión, nos sumergimos en el mundo de la gestión de la monitorización, donde el Percona Monitoring y Management (PMM) ha emergido como una solución valiosa.
Como sistema de monitorización que ha demostrado su valía en numerosas ocasiones, implementamos PMM para mantener un control minucioso sobre el rendimiento y el estado de nuestras bases de datos y sistemas. A lo largo de los años, hemos confiado en las actualizaciones periódicas de PMM para acceder a nuevas funcionalidades, mejoras de seguridad y correcciones de errores cruciales. Sin embargo, como todo en la tecnología, incluso las actualizaciones más prometedoras pueden venir acompañadas de desafíos inesperados.
Esta semana hemos explorado un problema que ha capturado nuestra atención durante las últimas actualizaciones de PMM, llevándonos a descubrir un obstáculo que merece un análisis. A través de este artículo, os hablamos sobre los desafíos encontrados al realizar actualizaciones de PMM y otros problemas detectados.
En la mayoría de los casos, cuando realizamos la implementación de PMM en nuestros clientes, optamos por la solución paquetizada de PMM Server (con todos los componentes que necesita: grafana, prometheus, victoriametrics, pmm-agent, etc.) en una imagen de Docker: https://hub.docker.com/r/percona/pmm-server
A partir de la versión 2 de pmm-client, el método de cambio de contraseña del usuario administrador (“admin”) se modificó. Actualmente, la propia imagen de Docker PMM Server, contiene el ejecutable “change-admin-password” el cual se encarga de realizar el cambio de contraseña en todos los componentes de pmm-server que lo requieran.
Desde entonces, detectamos en numerosas ocasiones que el cambio de contraseña fallaba. Al cambiarla e ingresar con la nueva contraseña, ésta era errónea (obteníamos un login fallido). Utilizando la contraseña anterior, también obteníamos un login fallido.
En esta ocasión, realizamos una migración de PMM Server 2.9 a 2.33, sin actualizaciones intermedias.
En dicha actualización, era de crucial importancia que las métricas recolectadas en los meses anteriores no se perdieran. Para conseguir esto, aunque no está relacionado directamente con los problemas detectados, únicamente teníamos que tener en cuenta que había que reutilizar el volumen de Docker montado en el contenedor con la versión 2.9 y montarlo en este otro con la versión 2.33.
En el proceso de actualización de la imagen, no hubo ningún problema. No obstante, no pudimos realizar login en el dashboard (Grafana) y todos los agentes indicaban errores de autenticación al enviar las métricas.
Mediante el comando change-admin-password, realizamos un cambio de la password del usuario que se empleaba en los shipper y el resultado del comando fue correcto, indicando que la contraseña había sido cambiada correctamente. Sin embargo, seguíamos obteniendo un error de login fallido.
Durante la investigación del problema, se realizaron varias pruebas, reiniciando el contenedor tras los cambios de contraseña, se analizaron logs, etc.
En dicha revisión, observamos que uno de los logs generados por el contenedor (concretamente, en el volumen montado en Docker desde el anfitrión en /srv), en el log de Grafana (/srv/logs/grafana.log) había una gran cantidad de trazas continuas con el mensaje: “Too many consecutive incorrect login attempts for user - login for user temporarily blocked”, seguido de la IP remota que había realizado el intento de login.
Al detectar el mensaje, entendimos que se estaban realizando bloqueos de inicio de sesión temporales para el usuario en cuestión. Aparentemente, cuando éste estaba “bloqueado temporalmente” daba igual que se realizara un intento de sesión con contraseña y usuario válidos, el bloqueo seguía afectándole.
Viendo la cantidad de intentos de inicio de sesión, procedimos a parar los agentes pmm2-client de toda la plataforma. Tras esto, vimos que dichos intentos de sesión se habían reducido pero no habían cesado del todo proviniendo de 127.0.0.1. Esto nos llamó la atención.
Indagando un poco más, accedimos al contenedor de PMM Server para echar un vistazo: “docker exec-ti pmm-server/bin/bash”
Pudimos analizar que los diferentes procesos necesarios para el funcionamiento de la solución de PMM Server corrían con Supervisord. Visto esto, mediante el uso de supervisorclt (y las configuraciones de /etc/supervisord/) pudimos ver los procesos configurados para ser ejecutados con este servicio.
Uno de los procesos corriendo con supervisord, era “pmm-agent”, el cliente de pmm2-client que envía las métricas del propio contenedor PMM Server en localhost (127.0.0.1) para ser registradas en el inventario junto con el resto de instancias.
Llegados a este punto, decidimos levantar un único cliente (en una de las instancias de la plataforma, evitando levantar el pmm2-client corriendo en el contenedor PMM Server), previa purga de paquetes y configuraciones.
Esta instalación se realizó manualmente para descartar que hubiese algún problema en nuestros procesos automatizados que se encargan de instalar y configurar tanto clientes como servidores PMM (procesos automatizados con Ansible).
La instalación del paquete pmm2-client se realizó correctamente. Tras esto, procedimos a añadir este cliente al inventario de PMM Server mediante el uso del binario “pmm-admin”:
pmm-admin config --server-insecure-tls --force
--server-url=https://<user>:<password>@<ip-pmm-server>
La ejecución del comando fue correcta. La salida del mismo (stdout) indicaba que el agente se había registrado correctamente, no obstante, empezamos a ver errores de login fallidos en el log de Grafana (log comentado anteriormente del contenedor PMM Server en /srv/logs/grafana.log).
¿Por qué ocurrió esto?
Además de estos errores, pudimos comprobar que éramos incapaces de iniciar sesión en Grafana, lo cual sí habíamos podido hacer mientras cesaron los errores de inicio de sesión, ya que, cuando un usuario tiene intentos de login fallidos, es bloqueado temporalmente, sea cual sea la IP de origen del intento de inicio de sesión.
Esto complicaba bastante nuestros análisis porque teníamos que esperar a que se eliminara ese bloqueo temporal para poder realizar nuevas pruebas, iniciar sesión en grafana, etc.
Durante este análisis fue interesante detectar en los logs de Grafana (/srv/grafana/grafana.db) que se estaba empleando una base de datos SQLite. Realizando un análisis sencillo del modelo de datos (ver tablas y estructura de las mismas), vimos la tabla “login_attempt”, la cual contenía la información de los intentos de inicio de sesión que veíamos reflejados en el log.
Pudimos eliminar el bloqueo del usuario, borrando los registros pertinentes en la tabla mencionada. Para ello, hicimos uso del comando:
> docker exec pmm-server sqlite3 /srv/grafana/grafana.db "delete from login_attempt"
Con la sentencia anterior borramos todos los registros de dicha tabla y bloqueos realizados, comportamiento válido en nuestro caso. ‘Hay que tener en cuenta indicar una cláusula “where” si se desea borrar registros concretos en vez de todos los registros’
A partir de este punto, por lo menos, tuvimos mayor agilidad a la hora de seguir realizando pruebas y análisis, sin tener que esperar que expirara el bloqueo temporal.
Continuando con el análisis, llegamos a la conclusión que el problema era la contraseña establecida.
Al cambiar en PMM Server la contraseña del usuario utilizado por los agentes de PMM (pmm2-client) todo funcionaba correctamente. Pero, ¿Por qué?
Si al registrar el cliente en el inventario, con el comando anteriormente indicado, obteníamos una respuesta correcta (por tanto un login correcto) ¿Por qué después, al enviar las métricas, el login era incorrecto? ¿Qué diferenciaba la nueva contraseña de la anterior?
Descubrimos que cuando el cliente de pmm-2client se registra en un servidor de PMM Server, el cliente crea un YAML, con las configuraciones del agente (normalmente en /usr/local/percona/pmm2/config/pmm-agent.yaml).
Por tanto, la respuesta a la llamada a PMM Server para incluir el agente en el inventario, utiliza la contraseña facilitada en el comando. Tras una autenticación correcta, los datos persisten en ese YAML (contraseña incluida), siendo éste utilizado en posteriores peticiones de envío de métricas.
Llegados a este punto, verificamos que ambas contraseñas, tanto la que nos generaba problemas como la posteriormente utilizada con la que el funcionamiento era correcto, estaban incluidas correctamente en el YAML en cuestión.
Pero, ¿cuál era la diferencia entre las contraseñas? Fue entonces cuando vimos que la contraseña que no funcionaba correctamente contenía una coma (,).
Tras intentar entrecomillar la contraseña y solucionarlo de varias formas, vimos que igualmente en la contraseña almacenada en YAML seguía sin estar entrecomillada, por lo que finalmente, tuvimos que eliminar dicho carácter de la contraseña.
Esperamos que este artículo sirva como una guía valiosa para otros profesionales y equipos que también se enfrentan a cuestiones similares. En este caso, compartimos nuestra experiencia y los aprendizajes obtenidos.