Ansible vault without temp files

76 views
Skip to first unread message

Tiglath

unread,
Jun 29, 2021, 8:08:47 PM6/29/21
to Ansible Project

Quick question, please. 

A playbook. for each host generates a random password, sets it as root password on the host and stores, "<host>:< pwd>" in local Ansible vault file. 

How can I add new entries to the vault without creating a decrypted file ON DISK.

Ideally, I'd pipe the output of 'ansible-vault decrypt' output into a script that adds new data and then pipes it back to ansible-vault encrypt, so that the plain text only exists in memory.

Thanks 

Vladimir Botka

unread,
Jun 30, 2021, 3:54:13 AM6/30/21
to Tiglath, ansible...@googlegroups.com
On Tue, 29 Jun 2021 17:08:46 -0700 (PDT)
Tiglath <te...@tiglath.net> wrote:

> A playbook. for each host generates a random password, sets it as root
> password on the host and stores, "<host>:< pwd>" in local Ansible vault
> file.
>
> How can I add new entries to the vault without creating a decrypted file ON
> DISK.

Short answer
------------

Use the command below

- shell:
cmd: >
echo -n '{{ _mp_dict }}'|
ansible-vault encrypt_string
--stdin-name 'mp_dict' > my-pass-dict.vault
vars:
_mp_dict: "{{ _mp_dict|to_json }}"

Complete use-case
-----------------

* Let's start with empty plain-text

shell> cat my-pass-dict.vault
mp_dict:
dummy: dummy

* Read the file and display the dictionary

- hosts: alpha,beta,charlie
vars_files:
- my-pass-dict.vault
tasks:
- block:
- set_fact:
_mp_dict: "{{ mp_dict }}"
- debug:
var: _mp_dict
run_once: true

gives

_mp_dict:
dummy: dummy

* If the host is not in the dictionary create (and use) the password

- block:
- set_fact:
mp: "{{ lookup('password',
'/dev/null length=15 chars=ascii_letters') }}"
- debug:
var: mp
when: inventory_hostname not in _mp_dict

gives

ok: [beta] =>
mp: CdCXIQWsMqpRDao
ok: [alpha] =>
mp: XSLWBxbxPyDOhYs
ok: [charlie] =>
mp: vPvFieykftXzppi

* Create a dictionary of created passwords, update the dictionary and
encrypt the updated dictionary

- block:
- set_fact:
mp_add: "{{ dict(hostvars|dict2items|
selectattr('value.mp', 'defined')|
json_query('[].[key, value.mp]')|
list) }}"
- debug:
var: mp_add
- set_fact:
_mp_dict: "{{ _mp_dict|combine(mp_add) }}"
when: mp_add|list
- debug:
var: _mp_dict
- shell:
cmd: >
echo -n '{{ _mp_dict }}'|
ansible-vault encrypt_string
--stdin-name 'mp_dict' > my-pass-dict.vault
vars:
_mp_dict: "{{ _mp_dict|to_json }}"
when: mp_add|list
delegate_to: localhost
run_once: true

gives

mp_add:
alpha: XSLWBxbxPyDOhYs
beta: CdCXIQWsMqpRDao
charlie: vPvFieykftXzppi

_mp_dict:
alpha: XSLWBxbxPyDOhYs
beta: CdCXIQWsMqpRDao
charlie: vPvFieykftXzppi
dummy: dummy

Now the file my-pass-dict.vault comprises encrypted dictionary of the
hosts and passwords. The playbook is idempotent.


--
Vladimir Botka

Brian Coca

unread,
Jun 30, 2021, 10:05:33 AM6/30/21
to Ansible Project, Tiglath
now in filter:
https://github.com/ansible/ansible/pull/74998


----------
Brian Coca

Tiglath

unread,
Jun 30, 2021, 12:35:43 PM6/30/21
to Ansible Project
Thanks for taking the time.  

This is what I have:

What's missing is the code to do the actions in capitals. 

- hosts: all
  gather_facts: no
  <DECLARE EMPTY DICTIONARY>
  tasks:
      - name: generate random password.
        delegate_to: localhost
        command: "/home/ec2-user/genpwd.py"
        register: pwd

      - name: Update root user's password
        become: true
        user:
            name: root
            password:  "{{ pwd.stdout  |  password_hash('sha512')}}"
       <IF SUCCESSFUL ADD '<HOST>:<PWD>' TO DICTIONARY> 

   - post_tasks:
     delegate_to: localhost     
     <DECRYPT VAULT TO MEMORY, APPEND DICT AND ENCRYPT BACK TO VAULT>                               

  Many thanks. 
Reply all
Reply to author
Forward
0 new messages