Get kv secret from the vault with playbook

Hello, I’m new to Ansible and I’m trying to get a secret that is in the HashiCorp Vault. The engine is KV and below is some information about my structure and playbook:

ansible --version
ansible 2.10.8

ansible-galaxy collection list

/usr/lib/python3/dist-packages/ansible_collections

Collection Version


amazon.aws 1.4.0
ansible.netcommon 1.5.0
ansible.posix 1.1.1
ansible.windows 1.4.0
arista.eos 1.3.0
awx.awx 14.1.0
azure.azcollection 1.4.0
check_point.mgmt 1.0.6
chocolatey.chocolatey 1.0.2
cisco.aci 1.1.1
cisco.asa 1.0.4
cisco.intersight 1.0.10
cisco.ios 1.3.0
cisco.iosxr 1.2.1
cisco.meraki 2.2.0
cisco.mso 1.1.0
cisco.nso 1.0.3
cisco.nxos 1.4.0
cisco.ucs 1.6.0
cloudscale_ch.cloud 1.3.1
community.aws 1.3.0
community.azure 1.0.0
community.crypto 1.4.0
community.digitalocean 1.0.0
community.docker 1.2.2
community.fortios 1.0.0
community.general 1.3.6
community.google 1.0.0
community.grafana 1.1.0
community.hashi_vault 1.1.0
community.hrobot 1.1.0
community.kubernetes 1.1.1
community.kubevirt 1.0.0
community.libvirt 1.0.0
community.mongodb 1.2.0
community.mysql 1.2.0
community.network 1.3.2
community.okd 1.0.0
community.postgresql 1.1.1
community.proxysql 1.0.0
community.rabbitmq 1.0.1
community.routeros 1.1.0
community.skydive 1.0.0
community.vmware 1.7.0
community.windows 1.3.0
community.zabbix 1.2.0
containers.podman 1.4.1
cyberark.conjur 1.1.0
cyberark.pas 1.0.5
dellemc.os10 1.0.2
dellemc.os6 1.0.6
dellemc.os9 1.0.3
f5networks.f5_modules 1.7.1
fortinet.fortimanager 1.0.5
fortinet.fortios 1.1.8
frr.frr 1.0.3
gluster.gluster 1.0.1
google.cloud 1.0.2
hetzner.hcloud 1.2.1
ibm.qradar 1.0.3
infinidat.infinibox 1.2.4
junipernetworks.junos 1.3.0
mellanox.onyx 1.0.0
netapp.aws 20.9.0
netapp.elementsw 20.11.0
netapp.ontap 20.12.0
netapp_eseries.santricity 1.1.0
netbox.netbox 1.2.1
ngine_io.cloudstack 1.2.0
ngine_io.exoscale 1.0.0
ngine_io.vultr 1.1.0
openstack.cloud 1.2.1
openvswitch.openvswitch 1.1.0
ovirt.ovirt 1.3.0
purestorage.flasharray 1.6.2
purestorage.flashblade 1.4.0
servicenow.servicenow 1.0.4
splunk.es 1.0.2
theforeman.foreman 1.5.1
vyos.vyos 1.1.1
wti.remote 1.0.1

/root/.ansible/collections/ansible_collections

Collection Version


community.hashi_vault 5.0.0

PLAYBOOK


  • name: GET SECRET FROM ANSIBLE
    hosts: localhost
    tasks:

    • name: GET
      community.hashi_vault.vault_kv2_get:
      url: https://10.10.10.1:8201
      path: network
      auth_method: token
      register: response

    equivalent API path is secret/data/hello

    • name: Display the results
      ansible.builtin.debug:
      msg:
      • “Secret: {{ response.secret }}”
      • “Data: {{ response.data }} (contains secret data & metadata in kv2)”
      • “Metadata: {{ response.metadata }}”
      • “Full response: {{ response.raw }}”
      • “Value of key ‘password’ in the secret: {{ response.secret.password }}”

The error:
PLAY [GET SECRET FROM ANSIBLE] ********************************************************************

TASK [Gathering Facts] ****************************************************************************
ok: [localhost]

TASK [GET] ****************************************************************************************
fatal: [localhost]: FAILED! => {“changed”: false, “module_stderr”: “/tmp/ansible_community.hashi_vault.vault_kv2_get_payload_sta93h4v/ansible_community.hashi_vault.vault_kv2_get_payload.zip/ansible_collections/community/hashi_vault/plugins/modules/vault_kv2_get.py:193: DeprecationWarning: The raise_on_deleted_version parameter will change its default value to False in hvac v3.0.0. The current default of True will presere previous behavior. To use the old behavior with no warning, explicitly set this value to True. See https://github.com/hvac/hvac/pull/907\nTraceback (most recent call last):\n File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 699, in urlopen\n httplib_response = self._make_request(\n File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 382, in _make_request\n self._validate_conn(conn)\n File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 1012, in validate_conn\n conn.connect()\n File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 411, in connect\n self.sock = ssl_wrap_socket(\n File "/usr/lib/python3/dist-packages/urllib3/util/ssl.py", line 453, in ssl_wrap_socket\n ssl_sock = ssl_wrap_socket_impl(sock, context, tls_in_tls)\n File "/usr/lib/python3/dist-packages/urllib3/util/ssl.py", line 495, in _ssl_wrap_socket_impl\n return ssl_context.wrap_socket(sock)\n File "/usr/lib/python3.10/ssl.py", line 513, in wrap_socket\n return self.sslsocket_class._create(\n File "/usr/lib/python3.10/ssl.py", line 1071, in _create\n self.do_handshake()\n File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake\n self._sslobj.do_handshake()\nssl.SSLError: [SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:1007)\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 486, in send\n resp = conn.urlopen(\n File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 755, in urlopen\n retries = retries.increment(\n File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 574, in increment\n raise MaxRetryError(_pool, url, error or ResponseError(cause))\nurllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host=‘10.10.10.1’, port=8201): Max retries exceeded with url: /v1/secret/data/network (Caused by SSLError(SSLError(1, ‘[SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:1007)’)))\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File "/root/.ansible/tmp/ansible-tmp-1699312824.8110907-36810-179953140324255/AnsiballZ_vault_kv2_get.py", line 102, in \n _ansiballz_main()\n File "/root/.ansible/tmp/ansible-tmp-1699312824.8110907-36810-179953140324255/AnsiballZ_vault_kv2_get.py", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/root/.ansible/tmp/ansible-tmp-1699312824.8110907-36810-179953140324255/AnsiballZ_vault_kv2_get.py", line 40, in invoke_module\n runpy.run_module(mod_name=‘ansible_collections.community.hashi_vault.plugins.modules.vault_kv2_get’, init_globals=None, run_name=‘main’, alter_sys=True)\n File "/usr/lib/python3.10/runpy.py", line 224, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File "/usr/lib/python3.10/runpy.py", line 96, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File "/usr/lib/python3.10/runpy.py", line 86, in _run_code\n exec(code, run_globals)\n File "/tmp/ansible_community.hashi_vault.vault_kv2_get_payload_sta93h4v/ansible_community.hashi_vault.vault_kv2_get_payload.zip/ansible_collections/community/hashi_vault/plugins/modules/vault_kv2_get.py", line 213, in \n File "/tmp/ansible_community.hashi_vault.vault_kv2_get_payload_sta93h4v/ansible_community.hashi_vault.vault_kv2_get_payload.zip/ansible_collections/community/hashi_vault/plugins/modules/vault_kv2_get.py", line 209, in main\n File "/tmp/ansible_community.hashi_vault.vault_kv2_get_payload_sta93h4v/ansible_community.hashi_vault.vault_kv2_get_payload.zip/ansible_collections/community/hashi_vault/plugins/modules/vault_kv2_get.py", line 193, in run_module\n File "/usr/local/lib/python3.10/dist-packages/hvac/api/secrets_engines/kv_v2.py", line 153, in read_secret_version\n return self._adapter.get(\n File "/usr/local/lib/python3.10/dist-packages/hvac/adapters.py", line 146, in get\n return self.request("get", url, **kwargs)\n File "/usr/local/lib/python3.10/dist-packages/hvac/adapters.py", line 408, in request\n response = super().request(*args, **kwargs)\n File "/usr/local/lib/python3.10/dist-packages/hvac/adapters.py", line 367, in request\n response = self.session.request(\n File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 589, in request\n resp = self.send(prep, **send_kwargs)\n File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 703, in send\n r = adapter.send(request, **kwargs)\n File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 517, in send\n raise SSLError(e, request=request)\nrequests.exceptions.SSLError: HTTPSConnectionPool(host=‘10.10.10.1’, port=8201): Max retries exceeded with url: /v1/secret/data/network (Caused by SSLError(SSLError(1, ‘[SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:1007)’)))\n”, “module_stdout”: “”, “msg”: “MODULE FAILURE\nSee stdout/stderr for the exact error”, “rc”: 1}

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

1 Like

Hi,

First off, I moved your post to Get Help category, which would be more appropriate IMO.

Now to your issue;

SSLError(e, request=request)\nrequests.exceptions.SSLError: HTTPSConnectionPool(host=‘10.10.10.1’, port=8201): Max retries exceeded with url: /v1/secret/data/network (Caused by SSLError(SSLError(1, ‘[SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:1007)

See if you can configure Vault to only accept TLS >v1 connections.

You could also disable cert validation on module parameters, which should bypass your issue, though it’s obviously not a good idea.

Finally, I don’t know this collection well; I’m wondering what is the difference between vault_kv2_get and vault_read modules; perhaps one would be more appropriate to use ?
I’m on mobile and getting ready for work, so I check that later.

Edit: There is also a possibility there is a proxy on the way, which might intercept / inspect TLS traffic. In any case, you could troubleshoot using curl -Iv and check headers, or openssl s_client library, showing certs presented by the server. Please tell if you need help on this matter.

And to answer my question about modules differences, it seems vault_read is more generic, as vault_kv2_get is specific to Vault kv v2 API (get operations).

4 Likes

Hi, I’m the maintainer of community.hashi_vault and that’s correct: vault_read is a generic “read” (HTTP GET) operation on a Vault path. It’s useful for interacting with Vault for an operation that we don’t (yet) have a more specific plugin for.

vault_kv2_get is the specific read plugin for version 2 of the KV secret engine, so it is more appropriate to use here, unless the OP is using KV version 1, in which case we have vault_kv1_get as well.

There are also lookup forms of these modules but I think it’s better to use the modules in many cases.


Anyway @jcdiniz-redtoor , I think @ptn is spot on about the issue being with the TLS transport, and you will either need to fix your Vault configuration/certificates, or ignore cert validation on the client (ansible) side.


EDIT: nwerker has a really good point that port does look strange.

5 Likes

@jcdiniz-redtoor

Just a little side note, supplementary to what @briantist all mentioned.

The Port 8201 seems odd as well. Normally this Port is for connection between the Vault Cluster Nodes and not for Clients to interact with the Vault API. This Port is usually 8200.

This is just a conjecture, not knowing your Vault Config.

3 Likes

Hey guys,

After researching more and reading some documentation I found a simpler way to use an Ansible playbook to obtain the secret:


  • name: GET SECRET FROM ANSIBLE
    hosts: localhost
    gather_facts: no
    tasks:
    • name: Return all secrets from a path
      debug:
      msg: “{{ lookup(‘hashi_vault’, ‘secret=network/data/devnet token=hvs.dTyHIkHAhsuh9087HhYoPkO09 url=https://10.10.10.1:8200’)}}”

Note: to bypass the certificate verification, just add: validate_certs=no after the url, staying in this format:

msg: “{{ lookup(‘hashi_vault’, ‘secret=network/data/devnet token=hvs.RFtmJhr5V9UlmmesEcl5aPo3 url=https://172.16.91.1:8200 validate_certs=no’)}}”

The TLS error was resolved only by generating a self-signed certificate and indicating its CA to the vault.

About port 8201 it was an error in my configuration.

I believe that for my testing environment this playbook is enough, but for a production environment it doesn’t seem right to have the token shown in the playbook, is there a suggestion on how to “hide” this token safely and still be used by the playbook ?

Thank you very much guys!

1 Like

The token loading mechanism is documented here:
https://docs.ansible.com/ansible/latest/collections/community/hashi_vault/hashi_vault_lookup.html#parameter-token

It’s the same for all the community.hashi_vault Modules (lookup, read etc.). Preferably you use env vars for this (on playbook or host level). In an AWX or AAP context you could use a custom credential type that you define that injects env vars during Job run.

Either way I’d make sure to secure the token further (maybe via. ansible-vault) or checkout the other Auth Methods provided by the collection.

5 Likes

@nwerker covered your authentication question I think. There are many options for you to choose from there.

But as I mentioned I would encourage you not to use lookups unless you really need them: Lookup guide — Ansible Documentation

Furthermore, I would specifically discourage you from using the hashi_vault lookup, even if you wanted to use a lookup: Migrating from the hashi_vault lookup — Ansible Documentation

5 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.