L'obiettivo di questo post è fornire credenziali di database dinamiche/temporanee senza doverle creare e gestire tutte manualmente.
Inizierò semplicemente dicendo che questa è solo una prova di concetto e le migliori pratiche non sono state affatto seguite. (soprattutto di sicurezza). Tutte le procedure da questo punto sono solo semplici test con l'obiettivo di semplificare tutte le attività secondarie solo per vedere l'intero processo funzionante.
Test dei contenitori
Utilizzeremo i contenitori MariaDB e Vault, lanciati (rapidamente) come specificato nelle pagine DockerHub ufficiali di entrambi i progetti.
- Vault
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
Al termine dell'avvio del vault, dai registri del contenitore possiamo vedere quanto segue:
Potrebbe essere necessario impostare la seguente variabile di ambiente:
$ export VAULT_ADDR='http://0.0.0.0:8200
La chiave di annullamento del sigillo e il token di root vengono visualizzati di seguito nel caso in cui lo desideri
sigilla/apri il Vault o autentica nuovamente.
Chiave di sblocco:kSUgoPDPyBrCGWc4s93CIlMUnDLZGcxdu4doYCkWSPs=
Token radice:s.I6TnqhrgYh8uET91FUsNvIwV
La modalità di sviluppo NON deve essere utilizzata nelle>installazioni di produzione!
Quindi, abbiamo il nostro indirizzo del vault e il token di root.
- MariaDB
docker run --rm \
--name mariadb \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpw \
-d mariadb:latest
E qui abbiamo il nostro utente root e la password per MariaDB.
Poiché l'utente root non dovrebbe essere utilizzato per nulla, creeremo un utente dedicato per le interazioni con il Vault.
Accedi al database usando mysql -h 127.0.0.1 -u root -p
e creare l'utente del vault
grant CREATE USER, SELECT, INSERT, UPDATE ON *.* TO 'vault'@'%' identified by 'myvaultsecretpw' WITH GRANT OPTION;
Terraforma
Con tutti i servizi in esecuzione e configurati, è ora di occuparsi della parte di terraform.
Ancora una volta, questo è solo un POC. Tutte le password hardcoded e deboli sono destinate a scopi di test.
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}}';"]
}
File delle norme utilizzati nell'elenco di codici precedente:
- policies/dball.hcl
path "mariadb/creds/db-all" {
policy = "read"
capabilities = ["list"]
}
- policies/dbro.hcl
path "mariadb/creds/db-ro" {
policy = "read"
capabilities = ["list"]
}
Dopo questo, il solito processo:
terraform init
terraform apply
E abbiamo tutto pronto per alcuni test.
Test
Testare l'utente RO
Accedi al caveau
$ 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.
(...)
richiedere le credenziali del DB
$ 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
Accedi a DB
(RICORDA:il prossimo cmd è davvero una CATTIVA PRATICA!!!)
$ 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)]>
... prova a fare cose
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]>
Testare l'utente RW
Accedi al caveau
$ 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.
(...)
richiedere le credenziali del DB
$ 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
Accedi a DB
(RICORDA ANCORA:Il prossimo cmd è davvero una CATTIVA PRATICA!!!)
$ 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)]>
... prova a fare cose
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)
E questo è tutto. Ora abbiamo la base per i nostri utenti dinamici/temporanei MariaDB.