172 lines
6.8 KiB
Markdown
172 lines
6.8 KiB
Markdown
|
---
|
||
|
title: "Updating passwords with Ansible"
|
||
|
date: 2019-01-19T00:00:00+01:00
|
||
|
draft: false
|
||
|
share: false
|
||
|
---
|
||
|
|
||
|
I've recently migrated from [KeePassXC](https://keepassxc.org/) to [Bitwarden_RS](https://github.com/dani-garcia/bitwarden_rs) (which I highly recommend, by the way) to manage my passwords.
|
||
|
|
||
|
I figured it was an opportunity to update passwords I hadn't changed in... *years*. My Linux users' passwords were among those.
|
||
|
|
||
|
Instead of updating them manually on each machine, I thought there might be a way to do so with Ansible, and since it turns out there is, I thought I might as well share it here!
|
||
|
|
||
|
**Please be careful when it comes to password modification automation. You might end up locking yourself out of your servers.**
|
||
|
|
||
|
## Generating password hashes
|
||
|
|
||
|
First thing first, we'll need to generate `passwd` compatible password hashes for our users.
|
||
|
|
||
|
In this example, I'll generate a hash for the *P@ssw0rd* password :
|
||
|
```
|
||
|
mkpasswd -m sha-512
|
||
|
Password:
|
||
|
$6$wAVPV.Coc$o3FNxs9EPgXF54hv1BeKtfoMnLwE5VATL71jlHQHeVyCaevnnxfSp/x1UbJ00F3qlyyfUAmscuGXImoHmXBFa.
|
||
|
```
|
||
|
|
||
|
You might notice you'll get a different result if you run the same command again :
|
||
|
```
|
||
|
mkpasswd -m sha-512
|
||
|
Password:
|
||
|
$6$iFBWJD3300m$CYZJRSfZ4scHYNI9ggqe8WYef7Qym2Oi5ycgb64VsbU3.WM1GoJYlh1sawENTD7nrXVCthvs8LRPw1CVjzkP71
|
||
|
```
|
||
|
|
||
|
That's because, unless you specify it, the salt used by `mkpasswd` to encrypt the password is random.
|
||
|
|
||
|
You can choose a salt with the `-S` parameter if you want :
|
||
|
```
|
||
|
mkpasswd -m sha-512 -S hmmmsalt
|
||
|
Password:
|
||
|
$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/
|
||
|
|
||
|
mkpasswd -m sha-512 -S hmmmsalt
|
||
|
Password:
|
||
|
$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/
|
||
|
captainark@heimdall ~ %
|
||
|
```
|
||
|
|
||
|
## Ansible vault
|
||
|
|
||
|
Passwords are *secrets*. Even if there are hashed, you don't want them to be publicly accessible.
|
||
|
|
||
|
If, like me, your Ansible configuration is in a git repository, you should not commit them in an unencrypted file.
|
||
|
|
||
|
Ansible offers a way to encrypt a file containing variables with the `ansible-vault` command.
|
||
|
|
||
|
We first have to create a vault :
|
||
|
```
|
||
|
cd /your/ansible/project
|
||
|
mkdir -p group_vars/all/
|
||
|
ansible-vault create group_vars/all/vault.yml
|
||
|
New Vault password:
|
||
|
Confirm New Vault password:
|
||
|
```
|
||
|
|
||
|
As you can see, the command will ask you to provide a password for the vault. It will then open the file in your `$EDITOR` (that'll be `vim` if you're a cool kid).
|
||
|
|
||
|
The file is like any Ansible vault file. I'll create a variable for the `root` and `captainark` users in my case :
|
||
|
```yaml
|
||
|
vault_captainarkpwd: "$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/"
|
||
|
vault_rootpwd: "$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/"
|
||
|
```
|
||
|
|
||
|
An [Ansible best practice](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#variables-and-vaults) is to prepend all variables that are stored in a vault with the `vault_` prefix. It makes where they are stored clear when reading through a playbook.
|
||
|
|
||
|
Once saved, if you try to `cat` the file, you won't be able to see its actual content :
|
||
|
```
|
||
|
cat group_vars/all/vault.yml
|
||
|
$ANSIBLE_VAULT;1.1;AES256
|
||
|
32393530376537323233633636316330373136316265316662646437393533376135666232656366
|
||
|
3335623863333865666133666634633233616531636634370a663965356466383039326262313066
|
||
|
62633434396465313666333032663130343434326665386333323733633062613832653530393761
|
||
|
6333653338393231640a623938616634626462653965613766313335386136333362313033363735
|
||
|
64313662623039363365326639633231306335366432306361613837656364356464373837656565
|
||
|
61636538376262333762376235306337303531386638643632316361323037393230366537393132
|
||
|
35373861373863613666303531353737373130353330643535353238633665653236633130653064
|
||
|
39346330326566633262613535386633613565633566623934613066613238353739386133346535
|
||
|
64643762333462653966633363653439633037373161316663646261663764393332653732656335
|
||
|
61373462666336343533333162663637656236333739633065623939323937663137376431346231
|
||
|
38653338386539383663613230656165313566363733396134386366626430313235343264643938
|
||
|
64306163353437366362616166666565316663366163346565313436343537366330363932303038
|
||
|
37653138643165353138393466343063666535313933663066633832353331643838356539303533
|
||
|
61626237356538353261326136613239336662346337363331393037623863623433336432353461
|
||
|
32356136316339623139346330333235363331653634373836333730653436636563323134616337
|
||
|
36643433356133376138
|
||
|
```
|
||
|
|
||
|
To view the variables in the file, you can use the `ansible-vault view` command :
|
||
|
|
||
|
```yaml
|
||
|
ansible-vault view group_vars/all/vault.yml
|
||
|
Vault password:
|
||
|
vault_captainarkpwd: "$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/"
|
||
|
vault_rootpwd: "$6$hmmmsalt$RwZR2r9W5cSv5bVgeSFPX0rJiovWOD5kMDFey1xPR6JtasqQZqHTiuW5JoQ.0VCW6oNHJlgOYJ.auhl82gfX8/"
|
||
|
```
|
||
|
|
||
|
To edit the vault's content, you can use the `ansible-vault edit group_vars/all/vault.yml` command.
|
||
|
|
||
|
## The playbook
|
||
|
|
||
|
Now that our vault is ready, all that's left is to run the following playbook :
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
- hosts: all
|
||
|
become: yes
|
||
|
become_method: sudo
|
||
|
|
||
|
tasks:
|
||
|
- name: PASSWORDS | Check if the captainark user exists
|
||
|
shell: id -u captainark
|
||
|
register: captainark_exists
|
||
|
ignore_errors: true
|
||
|
|
||
|
- name: PASSWORDS | Update captainark password
|
||
|
user:
|
||
|
name: captainark
|
||
|
password: "{{ vault_captainarkpwd }}"
|
||
|
update_password: always
|
||
|
when: captainark_exists.rc == 0
|
||
|
|
||
|
- name: PASSWORDS | Create captainark user
|
||
|
user:
|
||
|
name: captainark
|
||
|
password: "{{ vault_captainarkpwd }}"
|
||
|
shell: /usr/bin/zsh
|
||
|
uid: 1000
|
||
|
groups: adm,sudo,apps
|
||
|
when: captainark_exists.rc != 0
|
||
|
|
||
|
- name: PASSWORDS | Update root password
|
||
|
user:
|
||
|
name: root
|
||
|
password: "{{ vault_rootpwd }}"
|
||
|
update_password: always
|
||
|
```
|
||
|
|
||
|
I've called this playbook `passwords.yml`. To run it, I simply execute the following command :
|
||
|
```
|
||
|
ansible-playbook passwords.yml --ask-vault-pass
|
||
|
```
|
||
|
|
||
|
The command asks for the vault password to decrypt its contents.
|
||
|
|
||
|
The playbook will first check if the `captainark` user exists, and it will update its password if it does. If it doesn't, the user will be created with the defined options.
|
||
|
|
||
|
Since the `root` user should always exist, the playbook changes its password without checking.
|
||
|
|
||
|
**N.B. :** If you've decided to store your vault somewhere else, you might need to add a task at the beginning of the playbook to load it, like so :
|
||
|
|
||
|
```yaml
|
||
|
- name: PASSWORDS | Load the vault
|
||
|
include_vars: /path/to/your/vault.yml
|
||
|
```
|
||
|
|
||
|
## Conclusion
|
||
|
|
||
|
That's all! As always, I hope someone finds this article useful!
|
||
|
|
||
|
If you do, please let me know in the comments here, on [Twitter](https://twitter.com/captainark) or on the [Fediverse](https://social.captainark.net/users/captainark/)!
|
||
|
|
||
|
Also, if you have any questions, feel free to hit me up on my [Rocket.Chat](https://chat.captainark.net) instance! Hopefully I'll write about it in the future!
|