OpenBao - Rotation des mots de passe
1. Description
Dans mon homelab, j'utilise un annuaire FreeIPA pour centraliser mes comptes et mots de passe utilisateur. Je suis authentifié via kerberos sur mes serveurs linux.
Les comptes de service sont par contre des comptes locaux avec un mot de passe local qui est différent par serveur et qui n'est pas centralisé sur l'annuaire LDAP FreeIPA.
L'objet de ce tutorial est d'écrire un playbook ansible pour faire une rotation automatique des mots de passe du compte de service packer présent sur mes serveurs linux : ce compte est inclus par défaut dans le template de mes VM linux.
En prérequis, il faut un serveur OpenBao et ansible fonctionnels :
- les mots de passe sont stockés dans OpenBao
- le playbook ansible regénère les mots de passe, les stocke dans OpenBao puis se connecte sur les serveurs pour changer le mot de passe
2. Installation de OpenBao sur la VM ansible
2.1. Installer OpenBao
$ wget https://github.com/openbao/openbao/releases/download/v2.2.2/bao_2.2.2_linux_amd64.rpm
$ sudo yum install bao_2.2.2_linux_amd64.rpm
2.2. Configurer les variables d'environnement
- Ajouter la ligne suivante dans le fichier ~/.bashrc
~/.bashrc
# BAO API address
export BAO_ADDR=https://openbao1.home.lab:8200
# BAO autocompletion
complete -C /usr/bin/bao bao
- Recharger les variables d'environnement
$ source ~/.bashrc
- Se logger sur OpenBao avec un token
$ bao login
Token (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 "bao login" again.
Future OpenBao requests will automatically use this token.
3. Activation du Secret Engine kv (key/value) v2
3.1. Activer le Secret Engine kv v2
$ bao secrets enable -version=2 kv
3.2. Créer une policy ansible-secret-servers_policy
- Cette policy permet de donner accès en lecture/écriture à l'arborescence
kv/serversdans laquelle seront stockés les mots de passe de mes serveurs - Créer le fichier
ansible-secret-servers_policy.hcl
ansible-secret-servers_policy.hcl
# file : ansible-secret-servers_policy.hcl
path "kv/data/servers/*" {
capabilities = ["create", "read", "list", "update"]
}
path "kv/metadata/servers/*" {
capabilities = ["list", "update"]
}
- Appliquer la policy
$ bao policy write ansible-secret-servers_policy ansible-secret-servers_policy.hcl
3.3. Générer un token utilisant la policy ansible-secret-servers_policy
- Générer un token utilisant la policy créée précédemment
$ bao token create -policy=ansible-secret-servers_policy -ttl=1h
- Pour exporter automatiquement le token dans la variable d'environnement
VAULT_TOKEN, créer le scriptgenerate-token-secret-server.sh
generate-token-secret-server.sh
#!/bin/bash
export VAULT_TOKEN=$(VAULT_TOKEN= bao token create -policy=ansible-secret-server_policy -ttl=1h -format=json | jq -r '.auth.client_token')
4. Création des mots de passe dans OpenBao
4.1. Créer un mot de passe pour chaque serveur linux
$ bao kv put servers/linux/wazuh1.home.lab/packer password=changeme
============ Secret Path ============
kv/data/servers/linux/wazuh1.home.lab/packer
$ bao kv put servers/linux/nautobot1.home.lab/packer password=changeme
============ Secret Path ============
kv/data/servers/linux/nautobot1.home.lab/packer
5. Configuration de ansible
5.1. Installer les packages python3-hvac et python3-passlib
$ sudo yum install python3-hvac python-passlib
6. Création du rôle ansible rotate-passwords
6.1. Créer le fichier roles/rotate-passwords/tasks/main.yml
roles/rotate-passwords/tasks/main.yml
---
# file: roles/rotate-passwords/tasks/main.yml
# description: rotate service accounts password for Linux servers
# usage: the openbao token must be stored in VAULT_TOKEN env variable
# author: TZ
- name: Générer un nouveau mot de passe pour {{ service_account}}
set_fact:
new_password: "{{ lookup('community.general.random_string', length=20, min_lower=1, min_upper=1, min_special=2, min_numeric=3, special='!@#$%&*()-_=+[]{}<>.,;:/?|', ignore_similar_chars=true) }}"
delegate_to: localhost
- name: Afficher le nouveau mot de passe de {{ service_account }}
ansible.builtin.debug:
msg: "{{ new_password | to_nice_yaml(indent=0) | trim }}"
- name: Changer le mot de passe de {{ service_account}} sur le serveur
ansible.builtin.user:
name: "{{ service_account }}"
update_password: "always"
password: "{{ new_password | password_hash('sha512') }}"
register: changed_password
become: true
- name: Préparer les données pour l'appel API OpenBao
set_fact:
secret_data:
data:
password: "{{ new_password }}"
changed_by: "{{ ansible_user_id }}"
changed_date: "{{ ansible_date_time.iso8601 }}"
delegate_to: localhost
- name: Mettre à jour le mot de passe de {{ service_account }} dans OpenBao
uri:
url: "{{ vault_address }}/v1/kv/data/servers/linux/{{ inventory_hostname }}/{{ service_account }}"
method: "POST"
headers:
X-Vault-Token: "{{ vault_token }}"
Content-Type: "application/json"
body: "{{ secret_data | to_json }}"
status_code: [200, 204]
validate_certs: true
delegate_to: localhost
when: not changed_password.failed
register: vault_update
6.2. Créer le fichier roles/rotate-passwords/defaults/main.yml
roles/rotate-passwords/defaults/main.yml
---
vault_address: "https://openbao1.home.lab:8200"
vault_token: "{{ lookup('env', 'VAULT_TOKEN') }}"
service_account: "packer"
7. Création du playbook playbooks/rotate-packer-password.yml
7.1. Créer le playbook playbooks/rotate-packer-password.yml
---
- name: Changer le mot de passe d'un compte de service sur tous les serveurs linux
hosts: all
gather_facts: true
vars:
vault_address: "https://openbao1.home.lab:8200"
vault_token: "{{ lookup('env', 'VAULT_TOKEN') }}"
service_account: "packer"
roles:
- rotate-passwords
7.2. Créer le playbook playbooks/rotate-ansible-password.yml
playbooks/rotate-ansible-password.yml
---
- name: Changer le mot de passe d'un compte de service sur tous les serveurs linux
hosts: all
gather_facts: true
vars:
vault_address: "https://openbao1.home.lab:8200"
vault_token: "{{ lookup('env', 'VAULT_TOKEN') }}"
service_account: "ansible"
roles:
- rotate-passwords
7.3. Exécuter le playbook playbooks/rotate-packer-password.yml
- Utiliser le script précédemment créé pour générer un token pour OpenBao et le stocker automatiquement dans la variable d'environnement
VAULT_TOKEN
$ source generate-token-secret-server.sh
- Exécuter le playbook
playbooks/rotate-packer-password.yml- Pour tester rapidement, je limite à un seul serveur avec le paramètre
--limit=nautobot1.home.lab
- Pour tester rapidement, je limite à un seul serveur avec le paramètre
$ ansible-playbook playbooks/rotate-packer-password.yml -K --limit=nautobot1.home.lab
BECOME password:
PLAY [Changer le mot de passe du compte de service sur tous les serveurs linux] ***********************************************************************************************
TASK [Gathering Facts] ************************************************************************
ok: [nautobot1.home.lab]
TASK [Générer un nouveau mot de passe pour packer] ********************************************
ok: [nautobot1.home.lab -> localhost]
TASK [Afficher le nouveau mot de passe de packer] *********************************************
ok: [nautobot1.home.lab] => {
"msg": "5V{4z635JwSvI{7V2WCx"
}
TASK [Changer le mot de passe de packer sur le serveur] ***************************************
changed: [nautobot1.home.lab]
TASK [Préparer les données de l'appel API OpenBao pour packer] ********************************
ok: [nautobot1.home.lab -> localhost]
TASK [Mettre à jour le mot de passe de packer dans OpenBao] ***********************************
ok: [nautobot1.home.lab -> localhost]
PLAY RECAP ************************************************************************************
nautobot1.home.lab : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- Exemple de résultat du playbook sur l'ensemble des serveurs de mon homelab

- Sur l'interface de OpenBao, on peut voir que l'ensemble des serveurs ont été créés

- Sur l'interface de OpenBao, vous pouvez voir le mot de passe, la date de dernier changement pour chaque serveur, par exemple
nautobot1.home.lab
