5

I have this idea for my Ansible inventory: I want to have only ONE vaulted value, a seed whicht gives birth to all the passwords I need in my inventory.

Something like this:

---

# I only have this to generate randomly, and vault
inventory_seed: "a strong random string" 

# Then all my other password are derived from this seed. 
# I feed the salted seed to a filter that creates a password directly sourced from the string I give him.

# will output, say, `wgSqz$@+SU^nw2;I` everytime I invoke ansible for the same inventory_hostname
machine_root_password: "{{ inventory_hostname + inventory_seed + 'root password' | to_strong_password }}"

# same: dp_password will be the same strong password everytime I invoke ansible
db_password:  "{{ inventory_seed + 'db password' | to_strong_password }}" 

# ... etc. All my inventory-specific passwords (and other keys) are derived from the same seed

This approach would help with the following issues:

  • I have many inventories, but only one set of roles.
  • I have to vault a new password for each and every inventory every time I introduce new passwords in a role.

Also I would expand this to generate keypairs, certificates and so on. Starting up a new inventory would be reduced to only specifying one or two vars instead of dozens.

Does this exist in the (comprehensive) Jinja / Ansible filters?

I am aware of the lookup( 'password', xxx) method, but this is not reproducible: it doesn't take a seed as input to output the same password if the same seed is provided. I also know that this is an often asked question here, but every time the password is saved locally which I don't want.

Will I have to implement this on my own?

How would you expand to generate other sensible but required data (X509 certs, keypairs, etc.)

karel
  • 5,489
  • 46
  • 45
  • 50
Gui13
  • 12,993
  • 17
  • 57
  • 104

2 Answers2

3

The solution is to use password_hash which can also be combined with a salt and a seed.

Here are some examples:

# uses a random salt
# -> output changes on each run
{{ 'rootpassword' | password_hash('sha512') }}

# uses a user defined salt
# -> output always stays the same
{{ 'rootpassword' | password_hash('sha512', 'secretsalt') }}

# creates a random numeric salt by using the inventory_hostname as a seed
# -> output is unique for every host and stays the same on each run
{{ 'rootpassword' | password_hash('sha512', 12345 | random(seed=inventory_hostname) | string) }}
F1ko
  • 3,326
  • 1
  • 9
  • 24
1

Reading your requirements it sound for me like an old fashioned codebook or one-time-pad (OTP). You may find more information @https://crypto.stackexchange.com/.

I want to have only ONE vaulted value ...

Whereby your one vaulted value would be the codebook, which could be in example a very long random string or file (How do I create a 1GB random file?). You could define a character set and make it as long as you like, hundreds of kilobytes. It could also be a huge text file or just a video.

a seed which gives birth to all the passwords

The seed would you be a pointer to a position in that codebook or file and by defining the length you can just read out passwords you like.

U880D
  • 8,601
  • 6
  • 24
  • 40