DSV lookup plugin for Ansible

DSV has lookup plugin for Ansible in the delinea.core collection. The collection is certified and available in Ansible Galaxy.

To install delinea.core collection run:

Copy
ansible-galaxy collection install delinea.core

Use ansible-galaxy collection list to verify the installation. Example:

Copy
$ ansible-galaxy collection list delinea.core

# /root/.ansible/collections/ansible_collections
Collection   Version
------------ -------
delinea.core 1.0.0
$

Source code of the delinea.core collection is available on GitHub: DelineaXPM/ansible-core-collection.

Requirements

The DSV lookup plugin depends on version 0.0.1 of Python DSV SDK. To install it run:

Copy
pip install python-dsv-sdk==0.0.1

Authentication

Only available option for authentication is via client credentials, i.e. client id and client secret. Read more about client credentials here.

Usage

The DSV lookup plugin can be used to access data from DSV and then store it in variables within your playbook.

Use "ansible-doc" to display all available configuration options:

Copy
ansible-doc --type lookup delinea.core.dsv

Recommended way to use the plugin is to configure it with environment variables and then set only path to a secret in the playbook file:

Copy
vars:
    my_secret: "{{ lookup('delinea.core.dsv', '<path to secret>') }}"

Also you can set only client id and client secert as env vars and provide tenant name as a named argument:

Copy
vars:
    my_secret: "{{ lookup('delinea.core.dsv', '<path to secret>', tenant='<tenant name>') }}"

Another option available from Ansible 1.5 is the Ansible Vault. Using it you can store client credentials for DSV in encrypted files.

Permissions

We strongly recommend using policies to control access to secrets needed by the plugin. The role tied to the client should only have read access to applicable secrets.

For example if name of the role used to generate client credentials is "ansible-role" and in your playbook you have:

Copy
vars:
    dsv_secret_one: "{{ lookup('delinea.core.dsv', 'playbooks:example:one') }}"
    dsv_secret_two: "{{ lookup('delinea.core.dsv', 'playbooks:example:two') }}"

Then for this role create a policy with only read action allowed:

Copy
dsv policy create \
    --path 'secrets:playbooks:example' \
    --subjects 'roles:ansible-role' \
    --actions 'read' \
    --resources 'secrets:playbooks:example:one,secrets:playbooks:example:two'

Example

The example shows how you can use DSV lookup plugin to read secret from DSV and store in a playbook variable.

To prepare DSV for this example, you need to:

  • create a secret

    Copy
    dsv secret create --path 'mysecret' --data '{"key": "1"}'
  • create a role

    Copy
    dsv role create --name 'ansible-example'
  • generate client credentials

    Copy
    dsv client create --role 'ansible-example'
  • create a policy with permission that will allow role "ansible-example" to read "mysecret" secret

    Copy
    dsv policy create \
        --path 'secrets:mysecret' \    --resources 'secrets:mysecret' \    --subjects 'roles:ansible-example' \    --actions 'read'

This example requires Python and Ansible to be installed. To install Ansible follow official installation guide from Ansible docs.

Python 3.10 and the ansible-core version 2.13.5 are used.

Copy
$ ansible --version
ansible [core 2.13.5]
  < skipped for brevity >
  python version = 3.10.8 (main, Oct 13 2022, 22:36:54) [GCC 10.2.1 20210110]
  jinja version = 3.1.2
  libyaml = True

Install the delinea.core collection which includes DSV lookup plugin:

Copy
ansible-galaxy collection install delinea.core

Next, install Python DSV SDK:

Copy
pip install python-dsv-sdk==0.0.1

For security reasons we do not recommend passing client id and client secret directly as named arguments directly to lookup plugin from Ansible playbook. In this example set "DSV_CLIENT_ID" and "DSV_CLIENT_SECRET" env variables to your values of client id and client secret respectively.

Also set "DSV_TENANT" to your tenant name (e.g. "demo" for "https://demo.secretsvaultcloud.com")

Now create a simple playbook which reads secret "mysecret" from DSV, stores it in the "my_secret" variable and then prints "key" value from the secret's data.

Copy
cat <<EOF > dsv_playbook.yml
- hosts: localhost
  vars:
      my_secret: "{{ lookup( 'delinea.core.dsv', 'mysecret' ) }}"
  tasks:
    - debug: msg="Key retrieved from DSV = {{ my_secret["data"]["key"] }}"
EOF

Example of running the dsv_playbook.yml using ansible-playbook:

Copy
$ ansible-playbook dsvlookup.yml
< skipped for brevity >

TASK [debug] ********************************************************************************************************************
ok: [localhost] => {
    "msg": "Key retrieved from DSV = 1"
}

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

$

Please note that DSV lookup plugin is similar to reading a secret using DSV CLI. If you create a playbook like this:

Copy
cat <<EOF > dsv_playbook2.yml
- hosts: localhost
  tasks:
    - debug: msg="{{ lookup( 'delinea.core.dsv', 'mysecret' ) }}"
EOF

and run it, then the output will be similar to reading the secrets using CLI:

Copy
dsv secret read --path mysecret