El objetivo de esta publicación es proporcionar credenciales de base de datos dinámicas/temporales sin tener que crearlas y administrarlas todas manualmente.
Solo voy a comenzar diciendo que esto es solo una prueba de concepto y que las mejores prácticas no se siguieron en absoluto. (principalmente de seguridad). Todos los procedimientos desde este punto son solo pruebas simples enfocadas en facilitar todas las tareas secundarias solo para ver que todo el proceso funciona.
Contenedores de prueba
Usaremos contenedores MariaDB y Vault, lanzados (rápidamente) como se especifica en las páginas oficiales de DockerHub de ambos proyectos.
- Bóveda
docker run --rm \
--name vault \
--cap-add=IPC_LOCK \
-e 'VAULT_LOCAL_CONFIG={"backend": {"file": {"path": "/vault/file"}}, "default_lease_ttl": "168h", "max_lease_ttl": "720h"}' \
-p 8200:8200 \
-d vault
Cuando Vault termina de iniciarse, podemos ver en los registros del contenedor lo siguiente:
Es posible que deba establecer la siguiente variable de entorno:
$ exportar VAULT_ADDR='http://0.0.0.0:8200
La clave de desbloqueo y el token raíz se muestran a continuación en caso de que desee
sellar/quitar el sello de Vault o volver a autenticarse.
Clave de apertura:kSUgoPDPyBrCGWc4s93CIlMUnDLZGcxdu4doYCkWSPs=
Ficha raíz:s.I6TnqhrgYh8uET91FUsNvIwV
¡El modo de desarrollo NO debe usarse en>instalaciones de producción!
Entonces, tenemos la dirección de nuestra bóveda y el token raíz.
- MariaDB
docker run --rm \
--name mariadb \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpw \
-d mariadb:latest
Y aquí tenemos nuestro usuario root y contraseña para MariaDB.
Debido a que el usuario raíz no debe usarse para nada, vamos a crear un usuario dedicado para las interacciones de la bóveda.
Inicie sesión en la base de datos usando mysql -h 127.0.0.1 -u root -p
y crea el usuario de la bóveda
grant CREATE USER, SELECT, INSERT, UPDATE ON *.* TO 'vault'@'%' identified by 'myvaultsecretpw' WITH GRANT OPTION;
Terraformar
Con todos los servicios ejecutándose y configurados, es hora de ocuparse de la parte de terraformación.
Una vez más, esto es solo un POC. Todas las contraseñas codificadas y débiles están destinadas a fines de prueba.
provider "vault" {
address = "http://localhost:8200"
#Token provided from vault container log
token = "s.I6TnqhrgYh8uET91FUsNvIwV"
}
resource "vault_auth_backend" "userpass" {
type = "userpass"
}
# USERS
resource "vault_generic_endpoint" "user_userro" {
depends_on = [vault_auth_backend.userpass]
path = "auth/userpass/users/userro"
ignore_absent_fields = true
data_json = <<EOT
{
"policies": ["db-ro"],
"password": "userro"
}
EOT
}
resource "vault_generic_endpoint" "user_userrw" {
depends_on = [vault_auth_backend.userpass]
path = "auth/userpass/users/userrw"
ignore_absent_fields = true
data_json = <<EOT
{
"policies": ["db-all", "db-ro"],
"password": "userrw"
}
EOT
}
# POLICIES
# Read-Only access policy
resource "vault_policy" "dbro" {
name = "db-ro"
policy = file("policies/dbro.hcl")
}
# All permissions access policy
resource "vault_policy" "dball" {
name = "db-all"
policy = file("policies/dball.hcl")
}
# DB
resource "vault_mount" "mariadb" {
path = "mariadb"
type = "database"
}
resource "vault_database_secret_backend_connection" "mariadb_connection" {
backend = vault_mount.mariadb.path
name = "mariadb"
allowed_roles = ["db-ro", "db-all"]
verify_connection = true
mysql{
connection_url = "{{username}}:{{password}}@tcp(192.168.11.71:3306)/"
}
# note that I have my database address hardcoded and I'm using my lan IP, since I'm running the mysql client directly from my host and vault/mariadb are running inside containers with their ports exposed.
data = {
username = "vault"
password = "myvaultsecretpw"
}
}
resource "vault_database_secret_backend_role" "role" {
backend = vault_mount.mariadb.path
name = "db-ro"
db_name = vault_database_secret_backend_connection.mariadb_connection.name
creation_statements = ["GRANT SELECT ON *.* TO '{{name}}'@'%' IDENTIFIED BY '{{password}}';"]
}
resource "vault_database_secret_backend_role" "role-all" {
backend = vault_mount.mariadb.path
name = "db-all"
db_name = vault_database_secret_backend_connection.mariadb_connection.name
creation_statements = ["GRANT ALL ON *.* TO '{{name}}'@'%' IDENTIFIED BY '{{password}}';"]
}
Archivos de políticas utilizados en la lista de códigos anterior:
- políticas/dball.hcl
path "mariadb/creds/db-all" {
policy = "read"
capabilities = ["list"]
}
- políticas/dbro.hcl
path "mariadb/creds/db-ro" {
policy = "read"
capabilities = ["list"]
}
Después de esto, el proceso habitual:
terraform init
terraform apply
Y tenemos todo listo para algunas pruebas.
Prueba
Prueba del usuario de RO
Iniciar sesión en la bóveda
$ vault login -method userpass username=userro
Password (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
(...)
solicitar credenciales de base de datos
$ vault read mariadb/creds/db-ro
Key Value
--- -----
lease_id mariadb/creds/db-ro/uGldyp0BAa2GhUlFyrEwuIbs
lease_duration 168h
lease_renewable true
password 8vykdcZNHp-I0pajVtoN
username v_userpass-d_db-ro_75wxnJaL69FW4
Iniciar sesión en la base de datos
(RECUERDA:¡¡¡El siguiente cmd es realmente una MALA PRÁCTICA !!! )
$ mysql -h 127.0.0.1 -u v_userpass-d_db-ro_75wxnJaL69FW4 -p'8vykdcZNHp-I0pajVtoN'
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 101
Server version: 10.3.13-MariaDB-1:10.3.13+maria~bionic mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
... tratar de hacer cosas
MariaDB [(none)]> create database my_database;
ERROR 1044 (42000): Access denied for user 'v_userpass-d_db-ro_75wxnJaL69FW4'@'%' to database 'my_database'
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| my_db |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
MariaDB [(none)]> use my_db;
Database changed
MariaDB [my_db]> show tables;
+-----------------+
| Tables_in_my_db |
+-----------------+
| my_table |
+-----------------+
1 row in set (0.00 sec)
MariaDB [my_db]> select * from my_table;
Empty set (0.00 sec)
MariaDB [my_db]>
Prueba del usuario RW
Iniciar sesión en la bóveda
$ vault login -method userpass username=userrw
Password (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
(...)
solicitar credenciales de base de datos
$ vault read mariadb/creds/db-all
Key Value
--- -----
lease_id mariadb/creds/db-all/GHRHvpuqa2ITP9tX54YHEePl
lease_duration 168h
lease_renewable true
password L--8mPBoprFZcaItINKI
username v_userpass-j_db-all_DMwlhs9nGxA8
Iniciar sesión en la base de datos
(RECUERDA OTRA VEZ:¡¡¡El siguiente cmd es una MALA PRÁCTICA !!! )
$ mysql -h 127.0.0.1 -u v_userpass-j_db-all_DMwlhs9nGxA8 -p'L--8mPBoprFZcaItINKI'
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 109
Server version: 10.3.13-MariaDB-1:10.3.13+maria~bionic mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
... tratar de hacer cosas
MariaDB [(none)]> create database my_database;
Query OK, 1 row affected (0.01 sec)
MariaDB [(none)]> use my_db;
Database changed
MariaDB [my_db]> create table the_table (i integer);
Query OK, 0 rows affected (0.03 sec)
MariaDB [my_db]> show tables;
+-----------------+
| Tables_in_my_db |
+-----------------+
| my_table |
| the_table |
+-----------------+
2 rows in set (0.00 sec)
Y eso es. Ahora tenemos la base para nuestros usuarios dinámicos/temporales de MariaDB.