Vault: Gestionar las credenciales de las DBs automáticamente

Vault es capaz de gestionar las credenciales de varias bases de datos automáticamente. Solo hace falta dar de alta la base de datos y configurar los roles.

Existen 2 tipos de roles; dinámicos y estáticos (estos no son soportados por todas las bases de datos). La diferencia entre ellos, es que el dinámico, por cada petición de lectura al secreto, genera un usuario y una contraseña nueva. En cambio, con el rol estático, siempre se utiliza el mismo usuario y solo es la contraseña la que rota pasado el tiempo establecido.

Esto, nos puede venir bien para añadir una seguridad extra al flujo de conexiones entre las aplicaciones y la base de datos. Haciendo que en caso de que las credenciales sean interceptadas, solo valgan para cierto tiempo. Y permita tracear de un modo mas fácil que se ha hecho con cada usuario (en el caso de que se utilicen roles dinámicos).

Vamos a dar por hecho que ya se dispone de un Vault desplegado y una base de datos, que en este caso, será un MySQL. Si no se ha desplegado Vault, podéis consultar como hacerlo aquí. Todos los comandos se ejecutarán mediante la CLI de Vault.

MySQL

Antes de nada, vamos a crear un usuario con permisos (este usuario será el que le pasemos a Vault para no usar el de Root). Y una base de datos para hacer las pruebas.

CREATE DATABASE vault_test;
CREATE USER 'vault-user'@'%' IDENTIFIED BY 'vault-password';
GRANT ALL PRIVILEGES ON * . * TO 'vault-user'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Vault

Secret Engine

Para empezar, vamos a crear el secret engine. Que en este caso, será uno de tipo database

vault secrets enable \
        -path=mysql \
        database

Y configuraremos la base de datos que vamos a utilizar. Aquí solo hay que cambiar el endpoint de la base de datos, el username y password

vault write mysql/config/mysql-production \
        plugin_name=mysql-database-plugin \
        connection_url="{{username}}:{{password}}@tcp(mysql:3306)/" \
        allowed_roles="*" \
        username="vault-user" \
        password="vault-password"

Como buena práctica, vamos a rotar la contraseña del usuario que hemos establecido. De este modo, esta contraseña solo la sabrá Vault. Y en el caso de que necesitemos hacer algo con privilegios elevados, deberemos usar la de Root.

vault write -f mysql/rotate-root/mysql-production

Dynamic Roles

Como hemos dicho antes, existen 2 tipos de roles. El dinámico, es totalmente gestionado por Vault tanto el usuario como la contraseña. Y va rotando en base al TTL que se le establezca.

Los parámetros a tener en cuenta son los siguientes:

  • db_name: El nombre de la config que hemos seteado anteriormente
  • creation_statements: La/Las sentencias SQL que ejecutará vault para crear usuarios.
  • default_ttl: El tiempo que va a tardar en expirar la contraseña del usuario
vault write mysql/roles/mysql-dynamic \
        db_name="mysql-production" \
        creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON vault_test.* TO '{{name}}'@'%';" \
        default_ttl="1h" \
        max_ttl="24h"

Una vez aplicado, podremos obtener las credenciales mediante una consulta read. Esto generará un usuario en MySQL nuevo cada vez que se consulte.

vault read mysql/creds/mysql-dynamic

También podemos listar las leases que se han creado (cuando expiran, desaparecen)

vault list sys/leases/lookup/mysql/creds/mysql-dynamic

O también podemos renovarlas si lo necesitásemos

vault lease renew mysql/creds/mysql-dynamic/C46YFIbsp0yjUPgzl3SnoWdb

Static Roles

Como hemos dicho antes, en los Static Roles solo se rota la contraseña.

Para esto, vamos a crear un usuario llamado vault_static en MySQL.

CREATE USER 'vault_static'@'%' IDENTIFIED BY 'vault-password';
GRANT ALL PRIVILEGES ON * . * TO 'vault_static'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Una vez hecho esto, podemos crear el role. Los parámetros a rellenar son los siguientes:

  • db_name: El nombre de la configuración creada previamente
  • username: El usuario al que se le va a rotar la password
  • rotation_statements: La/Las sentencias SQL que se ejecutarán
  • rotation_period: El tiempo antes de la rotación de la contraseña
vault write mysql/static-roles/mysql-static \
        db_name="mysql-production" \
        username="vault_static" \
        rotation_statements="ALTER USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';" \
        rotation_period="1h"

Y podremos consultar la contraseña con el siguiente comando:

vault read mysql/static-creds/mysql-static
Key                    Value
---                    -----
last_vault_rotation    2020-05-24T17:40:06.16964457+02:00
password               A1a-KlPzLYFve25pyXKR
rotation_period        1m
ttl                    45m
username               vault_static

Pasado el TTL, rotará automáticamente la contraseña. En el caso de que se quiera forzar la rotación, se puede hacer con el siguiente comando:

vault write -f mysql/rotate-role/mysql-static

Una vez montado este flujo, las aplicaciones deberán interactuar con la API de Vault para obtener los secretos por lo que habrá que generar un approle con los permisos necesarios. Esto lo veremos en futuros posts.


Also published on Medium.

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *