Gui13
Gui13

Reputation: 13561

Generate reusable non-random but strong password with Ansible from a seed

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:

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.)

Upvotes: 5

Views: 837

Answers (3)

Bruno Casano
Bruno Casano

Reputation: 11

I use something like this.

    - name: Create idempotent secret
      ansible.builtin.set_fact:
        secret: "{{ lookup('ansible.builtin.password', '/dev/null seed={{ inventory_hostname  }} length=40 chars=ascii_letters') }}"

    - name: Debug
      ansible.builtin.debug:
        var: secret

More information available in the docs but I'm afraid the documentation is incorrect/outdated.

Upvotes: 0

U880D
U880D

Reputation: 12142

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.

Upvotes: 1

F1ko
F1ko

Reputation: 4294

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) }}

Upvotes: 3

Related Questions