Introducció a HashiCorp Vault i Ansible
En aquest article veurem com integrar HashiCorp Vault amb Ansible per gestionar secrets de forma segura en entorns DevOps. Aprendrem a crear un magatzem de secrets, definir polítiques d'accés, configurar l'autenticació i consumir credencials des d'un playbook d'Ansible en temps real.
Soc Òscar Mas i si estic segur que ja has llegit els meus altres posts de HashiCorp Vault, però per si un cas, tels deixo resumits a continuació:
- HashiCorp Vault: el guardià dels secrets en entorns DevOps. En Aquest post vam ensenyar les bases del producte i vam entendre per què Vault es una peça clau per deixar d'enviar contrasenyes en text pla i començar a gestionar els secrets de forma segura, centralitzada i xifrada.
- HashiCorp Vault: instal·lació amb Docker i treball amb secrets. Aquí ens vam posar a treballar i vam aixecar el nostre propi servidor de Vault, utilitzant Docker i vam aprendre a emmagatzemar-hi el nostre primer secret.
Ara que ja tenim el coneixement del producte i som capaços de desplegar el nostre propi servidor de Vault, és l'hora de fer el salt cap a l'automatització real. I ho farem amb una de les integracions més potents i famoses del mercat: Ansible.
Pel que desconegui Ansible, és una eina orientada a IaC (Infrastructure as Code) que ens permet automatitzar configuracions i desplegaments en la nostra infraestructura. Però, què passa amb les contrasenyes i claus de la infraestructura que Ansible necessita gestionar?, aquí és on entra en joc HashiCorp Vault.
Preparació del laboratori
En el laboratori farem servir dos equips:
- Equip: vault. És on hem instal·lat el nostre sistema de HashiCorp Vault.
- Equip: cli-ansible-vault. És des d'on llançarem els playbooks de Ansible. Aquest servidor consumirà els secrets del servidor de HashiCorp Vault.
El primer que farem és validar que el servei del servidor vault estigui "UnSelaed" i iniciarem sessió al servidor de HashiCorp Vault.
root@vault:~# docker exec -it vault ash / # vault status Key Value --- ----- ... ... Sealed false ... ... / # export VAULT_ADDR=http://127.0.0.1:8200 / # vault login s.KaU83zJXYPXaZZCfFkgT8eJX
Crear un secret a HashiCorp Vault
Ens crearem un espai de treball, tipus KV (Key-Value). Farem servir la version=2, que ens permet tenir un historial i control de versions dels secrets, i la ruta d'accés principal serà ansible.
/ # vault secrets enable -description="Secrets ansible DiBa" -version=2 -path=ansible kv
Crearem un secret, perquè després el pugi consumir Ansible:
/ # vault kv put ansible/myapp/config username='secret-username' password='secret-password'
Farem una consulta ràpida per validar que les dades s'han emmagatzemat correctament.
/ # vault kv get -format=json ansible/myapp/config
...
"password": "secret-password",
"username": "secret-username"
...
Crear una política d'accés per Ansible
Crearem una política anomenada policy-myapp que només permet llegir (read) aquest secret. Més endavant, l'Ansible farà servir aquesta política per connectar-se, assegurant-nos que no pugui xafardejar la resta de secrets que hi ha al HashiCorp Vault.
/ # vault policy write policy-myapp - <<EOF
path "ansible/data/myapp/config" {
capabilities = ["read"]
}
EOF
Farem un llistat per validar que la nostra nova política policy-myapp s'ha guardat correctament al sistema i ja està llesta per ser utilitzada.
/ # vault policy list default policy-myapp root
Configurar l'autenticació d'usuaris a HashiCorp Vault
Per defecte HashiCorp Vault només ens permet l'accés mitjançant token. Per això habilitarem els usuaris locals de Vault.
/ # vault auth enable userpass
Crearem un usuari anomenat oscar.mas amb la seva contrasenya (superpassword). El més important d'aquest comandament és el paràmetre policies=policy-myapp, que el que fa és aplicar aquesta política a l'usuari oscar.mas. Recordeu que aquesta política només deixa llegir secrets (read).
A partir d'aquí, ho tenim tot fet, però per seguretat validarem que l'usuari oscar.mas pugui accedir al secret des del mateix servidor de HashiCorp Vault:
/ # vault login -method=userpass username=oscar.mas password=superpassword
/ # vault kv get -format=json ansible/myapp/config
...
"password": "secret-password",
"username": "secret-username"
...
Instal·lar Ansible i el client de Vault
Ara canviem de màquina i ens situem al nostre client d'Ansible (cli-ansible-vault).
El primer que hem de fer és preparar l'entorn, instal·lant les eines necessàries i el client de Vault:
root@cli-ansible-vault:~# apt update && apt install -y ansible unzip python3-hvac
root@cli-ansible-vault:~# VAULT_RELEASE="1.19.4"
root@cli-ansible-vault:~# wget https://releases.hashicorp.com/vault/${VAULT_RELEASE}/vault_${VAULT_RELEASE}_linux_amd64.zip
root@cli-ansible-vault:~# unzip vault_${VAULT_RELEASE}_linux_amd64.zip
root@cli-ansible-vault:~# mv vault /usr/local/bin/
Un cop tenim el client de Vault instal·lat a la màquina d'Ansible, el següent pas és connectar-nos al nostre servidor de Vault. Per fer-ho, executem aquestes comandes:
root@cli-ansible-vault:~# export VAULT_ADDR=http://172.26.0.30 root@cli-ansible-vault:~# vault login -method=userpass username=oscar.mas password=superpassword
Connectar Ansible amb HashiCorp Vault
Un cop hàgim iniciat sessió, Vault ens donarà un Token que és el que farem per autenticar-nos amb HashiCorp Vault.
Perquè quedi clar: el login és simplement el mitjà que utilitzem per identificar-nos i què Vault ens entregui un Token. Aquest Token ens permetrà accedir-hi durant un temps predeterminat (anomenat TTL), que si no l'hem modificat, per defecte és de 32 dies (768 hores). Passat aquest temps, el token caducarà per seguretat, deixarem de tenir accés als secrets i haurem de fer el mateix procediment perquè ens doni un token nou.
Ara, perquè el sistema operatiu se'n recordi del Token i no haver-lo de posar cada cop, l'exportarem a una variable del sistema amb la següent comanda.
root@cli-ansible-vault:~# export VAULT_TOKEN="hvs.xxx"
Exemple de playbook d'Ansible amb HashiCorp Vault
I ara només queda llançar el nostre playbook:
root@cli-ansible-vault:~# ansible-playbook test-vault.yaml
PLAY [localhost] ******************************************************
TASK [HashiCorp Vault - Show username] ********************************
ok: [localhost] => {
"msg": "secret-username"
}
TASK [HashiCorp Vault - Show password] ********************************
ok: [localhost] => {
"msg": "secret-password"
}
TASK [HashiCorp Vault - Create file: /root/vault.secrets] *************
changed: [localhost]
PLAY RECAP ************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Si anem a comprovar el fitxer que ha creat Ansible, veurem que ha recuperat els secrets directament des de Vault en temps real i els ha posat al fitxer indicat:
root@cli-ansible-vault:~# cat vault.secrets Username: secret-username Password: secret-password
Us deixo el playbook que hem llançat, per poder acabar de fer el laboratori:
root@cli-ansible-vault:~# vim test-vault.yaml
---
- hosts: localhost
gather_facts: false
vars:
ansible_hashi_vault_url: "http://172.26.0.30"
ansible_hashi_vault_timeout: 5
ansible_hashi_vault_retries: 3
ansible_hashi_vault_auth_method: "token"
tasks:
- name: "HashiCorp Vault - Show username"
debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'ansible/data/myapp/config:username')}}"
- name: "HashiCorp Vault - Show password"
debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'ansible/data/myapp/config:password')}}"
- name: "HashiCorp Vault - Create file: /root/vault.secrets"
copy:
dest: "/root/vault.secrets"
content: |
Username: {{ lookup('community.hashi_vault.hashi_vault', 'ansible/data/myapp/config:username')}}
Password: {{ lookup('community.hashi_vault.hashi_vault', 'ansible/data/myapp/config:password')}}
Configurar el temps de vida (TTL) dels tokens
Com hem comentat abans, que un token duri 32 dies (768 hores) per defecte pot ser un risc de seguretat. Si voleu abaixar aquest temps de vida (TTL) a 24 hores, ho podeu fer fàcilment modificant la configuració del mètode d'autenticació userpass.
Primer, podem consultar la configuració actual per comprovar que, efectivament, està fixada a 32 dies(768 hores):
root@cli-ansible-vault:~# vault read sys/auth/userpass/tune Key Value --- ----- default_lease_ttl 768h ... ... max_lease_ttl 768h ... ...
Per modificar-ho, hem de llançar el comandament vault auth tune. És important actualitzar tant el temps per defecte (-default-lease-ttl) com el temps màxim permès (-max-lease-ttl):
root@cli-ansible-vault:~# vault auth tune -max-lease-ttl=24h userpass root@cli-ansible-vault:~# vault auth tune -default-lease-ttl=24h userpass
Si tornem a fer la consulta al sistema, veurem que els canvis s'han aplicat correctament:
root@cli-ansible-vault:~# vault read sys/auth/userpass/tune Key Value --- ----- default_lease_ttl 24h max_lease_ttl 24h
Espero que us serveixi d'ajuda o com a mínim d'inspiració, per començar a guardar els vostres secrets d'una manera més segura.