Skip to content

Instantly share code, notes, and snippets.

@mchubby
Last active October 2, 2022 16:21
Show Gist options
  • Save mchubby/3cb173f09be474b6ebff521339c94fb5 to your computer and use it in GitHub Desktop.
Save mchubby/3cb173f09be474b6ebff521339c94fb5 to your computer and use it in GitHub Desktop.

Revisions

  1. mchubby revised this gist Oct 21, 2019. 1 changed file with 61 additions and 20 deletions.
    81 changes: 61 additions & 20 deletions Ansible-vault-id-script.md
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,15 @@
    Base OS = Ubuntu 19.10

    Relevant config item : https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-vault-id-match

    ### Prequisites + Software Versions

    ```bash
    $ sudo apt install ansible python3-passlib python3-keyring python3-keyrings.alt wget curl
    ```

    ```bash
    $ python3 -V
    Python 3.7.5rc1
    ```

    ```bash
    $ ansible --version
    ansible 2.8.3
    config file = /etc/ansible/ansible.cfg
    @@ -20,6 +19,10 @@ ansible 2.8.3
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    ```

    ### Create playbook dir and config (--vault-id is an executable Python script)

    Notice how we set `vault_id_match = True` in the config

    ```bash
    $ mkdir work; cd $_
    $ mkdir vars
    @@ -54,9 +57,11 @@ vault_identity_list = second@~/work/vault-keyring-client.py, first@~/work/vault-
    EOF
    ```

    ### Create labeled secret and set it to a variable

    ```bash
    $ ansible-vault encrypt_string --vault-id first@~/work/vault-keyring-client.py
    Please enter password for encrypted keyring:
    Please enter password for encrypted keyring: user
    Reading plaintext input from stdin. (ctrl-d to end input)
    password
    !vault |
    @@ -81,6 +86,8 @@ mypassword: !vault |
    EOF
    ```

    ### Create playbook

    ```bash
    $ cat > ~/work/play.yml <<'EOF'
    # Main playbook
    @@ -94,6 +101,13 @@ $ cat > ~/work/play.yml <<'EOF'
    EOF
    ```

    ## Invokation 1: Pass unlabelled expects Python script to be called with --vault-id first

    Expectation: since `vault_id_match` is True, the script should be called as little as possible (once with --vault-id first)

    Note how used .cfg is our own.


    ```bash
    $ ansible-playbook -vvvvv -i localhost, play.yml --vault-id ~/work/vault-keyring-client.py
    ansible-playbook 2.8.3
    @@ -103,6 +117,14 @@ ansible-playbook 2.8.3
    executable location = /usr/bin/ansible-playbook
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    Using /home/user/work/ansible.cfg as config file
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id second
    Please enter password for encrypted keyring: user
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id first
    Please enter password for encrypted keyring: user
    Reading vault password file: /home/user/work/vault-keyring-client.py
    The vault password file /home/user/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id None
    @@ -112,6 +134,10 @@ key="ansible" for user="user" via backend="chainer ChainerBackend"\n'
    ERROR! Vault password client script /home/user/work/vault-keyring-client.py did not find a secret for vault-id=None: b'vault-keyring-client could not find key="ansible" for user="user" via backend="chainer ChainerBackend"\n'
    ```

    ## Invokation 2: Do not pass any vault-id, let vault_identity_list be processed

    This one succeeds only if `vault_id_match` is True.

    ```bash
    $ ansible-playbook -vvvvv -i localhost, play.yml
    ansible-playbook 2.8.3
    @@ -124,11 +150,11 @@ Using /home/user/work/ansible.cfg as config file
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id second
    Please enter password for encrypted keyring:
    Please enter password for encrypted keyring: user
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id first
    Please enter password for encrypted keyring:
    Please enter password for encrypted keyring: user
    setting up inventory plugins
    Set default localhost to localhost
    Parsed localhost, inventory source with host_list plugin
    @@ -191,19 +217,34 @@ PLAY RECAP *********************************************************************
    localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    ```


    # Invokation 3: vault_identity_list as plain script


    ```bash
    $ grep -r --color vault_id_match /usr/lib/python3/dist-packages/ansible
    /usr/lib/python3/dist-packages/ansible/config/base.yml: - {key: vault_id_match, section: defaults}
    /usr/lib/python3/dist-packages/ansible/config/base.yml: yaml: {key: defaults.vault_id_match}
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: encrypt_vault_id_matchers = [encrypt_vault_id]
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: encrypt_secret = match_best_secret(secrets, encrypt_vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: _vault_id_matchers = [_vault_id for _vault_id, dummy in secrets]
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: best_secret = match_best_secret(secrets, _vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers = []
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers.append(vault_id)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: _matches = match_secrets(self.secrets, vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers.extend([_vault_id for _vault_id, _dummy in self.secrets if _vault_id != vault_id])
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: matched_secrets = match_secrets(self.secrets, vault_id_matchers)
    Binary file /usr/lib/python3/dist-packages/ansible/parsing/vault/__pycache__/__init__.cpython-37.pyc matches
    $ cat > ~/work/ansible.cfg <<'EOF'
    [defaults]
    transport = local
    vault_id_match = True
    vault_identity_list = ~/work/vault-keyring-client.py
    EOF

    $ ansible-playbook -vvvvv -i localhost, play.yml
    ansible-playbook 2.8.3
    config file = /home/user/work/ansible.cfg
    configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = /usr/lib/python3/dist-packages/ansible
    executable location = /usr/bin/ansible-playbook
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    Using /home/user/work/ansible.cfg as config file
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id None
    [WARNING]: Error in vault password file loading (None): Vault password client script /home/user/work/vault-keyring-client.py did not find a secret for vault-id=None: b'vault-keyring-client could not find
    key="ansible" for user="user" via backend="chainer ChainerBackend"\n'

    ERROR! Vault password client script /home/user/work/vault-keyring-client.py did not find a secret for vault-id=None: b'vault-keyring-client could not find key="ansible" for user="user" via backend="chainer ChainerBackend"\n'
    ```


  2. mchubby created this gist Oct 21, 2019.
    209 changes: 209 additions & 0 deletions Ansible-vault-id-script.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,209 @@
    Base OS = Ubuntu 19.10


    ```bash
    $ sudo apt install ansible python3-passlib python3-keyring python3-keyrings.alt wget curl
    ```

    ```bash
    $ python3 -V
    Python 3.7.5rc1
    ```

    ```bash
    $ ansible --version
    ansible 2.8.3
    config file = /etc/ansible/ansible.cfg
    configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = /usr/lib/python3/dist-packages/ansible
    executable location = /usr/bin/ansible
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    ```

    ```bash
    $ mkdir work; cd $_
    $ mkdir vars
    $ curl https://raw.githubusercontent.com/alibaba/ansible-provider-docs/master/contrib/vault/vault-keyring-client.py | sed 's/env python$/env python3/' > ~/work/vault-keyring-client.py
    $ chmod u+x ~/work/vault-keyring-client.py
    ```

    ```bash
    $ ~/work/vault-keyring-client.py --vault-id first --set
    Storing password in "user" user keyring using key name: first
    Password: first
    Confirm password: first
    Please set a password for your new keyring: user
    Please confirm the password: user
    ```

    ```bash
    $ ~/work/vault-keyring-client.py --vault-id second --set
    Storing password in "user" user keyring using key name: second
    Password: second
    Confirm password: second
    Please enter password for encrypted keyring: user
    ```

    ```bash
    $ cat > ~/work/ansible.cfg <<'EOF'
    [defaults]
    transport = local
    vault_id_match = True
    vault_identity_list = second@~/work/vault-keyring-client.py, first@~/work/vault-keyring-client.py
    EOF
    ```

    ```bash
    $ ansible-vault encrypt_string --vault-id first@~/work/vault-keyring-client.py
    Please enter password for encrypted keyring:
    Reading plaintext input from stdin. (ctrl-d to end input)
    password
    !vault |
    $ANSIBLE_VAULT;1.2;AES256;first
    62666538353333306637633030373538373232326637323138643864663338383838323639623035
    3034383530306263376466656663396335373335663038390a326236306539323461663630613933
    30393465333035396666623138623963363238336666373762636632633938313937393165656664
    3136393238623836610a376332353266383435623061633265313963366235653966326437306530
    3766
    Encryption successful

    $ cat > ~/work/vars/main.yml <<'EOF'
    # variables for current playbook
    ---
    mypassword: !vault |
    $ANSIBLE_VAULT;1.2;AES256;first
    62666538353333306637633030373538373232326637323138643864663338383838323639623035
    3034383530306263376466656663396335373335663038390a326236306539323461663630613933
    30393465333035396666623138623963363238336666373762636632633938313937393165656664
    3136393238623836610a376332353266383435623061633265313963366235653966326437306530
    3766
    EOF
    ```

    ```bash
    $ cat > ~/work/play.yml <<'EOF'
    # Main playbook
    ---
    - hosts: localhost
    vars_files: vars/main.yml
    tasks:
    - debug:
    msg: "Hello {{ inventory_hostname }}: {{ mypassword | mandatory }}"
    EOF
    ```

    ```bash
    $ ansible-playbook -vvvvv -i localhost, play.yml --vault-id ~/work/vault-keyring-client.py
    ansible-playbook 2.8.3
    config file = /home/user/work/ansible.cfg
    configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = /usr/lib/python3/dist-packages/ansible
    executable location = /usr/bin/ansible-playbook
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    Using /home/user/work/ansible.cfg as config file
    Reading vault password file: /home/user/work/vault-keyring-client.py
    The vault password file /home/user/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id None
    [WARNING]: Error in vault password file loading (None): Vault password client script /home/user/work/vault-keyring-client.py did not find a secret for vault-id=None: b'vault-keyring-client could not find
    key="ansible" for user="user" via backend="chainer ChainerBackend"\n'

    ERROR! Vault password client script /home/user/work/vault-keyring-client.py did not find a secret for vault-id=None: b'vault-keyring-client could not find key="ansible" for user="user" via backend="chainer ChainerBackend"\n'
    ```

    ```bash
    $ ansible-playbook -vvvvv -i localhost, play.yml
    ansible-playbook 2.8.3
    config file = /home/user/work/ansible.cfg
    configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = /usr/lib/python3/dist-packages/ansible
    executable location = /usr/bin/ansible-playbook
    python version = 3.7.5rc1 (default, Oct 8 2019, 16:47:45) [GCC 9.2.1 20191008]
    Using /home/user/work/ansible.cfg as config file
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id second
    Please enter password for encrypted keyring:
    Reading vault password file: ~/work/vault-keyring-client.py
    The vault password file ~/work/vault-keyring-client.py is a client script.
    Executing vault password client script: /home/user/work/vault-keyring-client.py --vault-id first
    Please enter password for encrypted keyring:
    setting up inventory plugins
    Set default localhost to localhost
    Parsed localhost, inventory source with host_list plugin
    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/docker.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/iocage.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/jail.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/kubectl.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/libvirt_lxc.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/lxd.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/oc.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/connection/zone.py) as it seems to be invalid: No module named 'distutils.spawn'

    Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/callback/osx_say.py) as it seems to be invalid: No module named 'distutils.spawn'

    [WARNING]: Skipping plugin (/usr/lib/python3/dist-packages/ansible/plugins/callback/say.py) as it seems to be invalid: No module named 'distutils.spawn'


    PLAYBOOK: play.yml ********************************************************************************************************************************************************************************************
    Positional arguments: play.yml
    verbosity: 5
    connection: local
    timeout: 10
    become_method: sudo
    tags: ('all',)
    inventory: ('localhost,',)
    forks: 5
    1 plays in play.yml
    Read vars_file 'vars/main.yml'
    Read vars_file 'vars/main.yml'
    Read vars_file 'vars/main.yml'

    (snipped...)

    ok: [localhost]
    META: ran handlers
    Read vars_file 'vars/main.yml'

    TASK [debug] **************************************************************************************************************************************************************************************************
    task path: /home/user/work/play.yml:6
    Found a vault_id (first) in the vaulttext
    We have a secret associated with vault id (first), will try to use to decrypt None
    Trying to use vault secret=(ClientScriptVaultSecret(filename='/home/user/work/vault-keyring-client.py', vault_id='first')) id=first to decrypt None
    Trying secret ClientScriptVaultSecret(filename='/home/user/work/vault-keyring-client.py', vault_id='first') for vault_id=first
    Decrypt successful with secret=ClientScriptVaultSecret(filename='/home/user/work/vault-keyring-client.py', vault_id='first') and vault_id=first
    ok: [localhost] => {
    "msg": "Hello localhost: password\n"
    }
    META: ran handlers
    META: ran handlers

    PLAY RECAP ****************************************************************************************************************************************************************************************************
    localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    ```

    ```bash
    $ grep -r --color vault_id_match /usr/lib/python3/dist-packages/ansible
    /usr/lib/python3/dist-packages/ansible/config/base.yml: - {key: vault_id_match, section: defaults}
    /usr/lib/python3/dist-packages/ansible/config/base.yml: yaml: {key: defaults.vault_id_match}
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: encrypt_vault_id_matchers = [encrypt_vault_id]
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: encrypt_secret = match_best_secret(secrets, encrypt_vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: _vault_id_matchers = [_vault_id for _vault_id, dummy in secrets]
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: best_secret = match_best_secret(secrets, _vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers = []
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers.append(vault_id)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: _matches = match_secrets(self.secrets, vault_id_matchers)
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: vault_id_matchers.extend([_vault_id for _vault_id, _dummy in self.secrets if _vault_id != vault_id])
    /usr/lib/python3/dist-packages/ansible/parsing/vault/__init__.py: matched_secrets = match_secrets(self.secrets, vault_id_matchers)
    Binary file /usr/lib/python3/dist-packages/ansible/parsing/vault/__pycache__/__init__.cpython-37.pyc matches
    ```