forked from ansible-collections/community.hashi_vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vault_list.py
183 lines (155 loc) · 6.16 KB
/
vault_list.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# (c) 2023, Tom Kivlin (@tomkivlin)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
name: vault_list
version_added: 4.1.0
author:
- Tom Kivlin (@tomkivlin)
short_description: Perform a list operation against HashiCorp Vault
requirements:
- C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
- For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
description:
- Performs a generic list operation against a given path in HashiCorp Vault.
seealso:
- module: community.hashi_vault.vault_list
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
options:
_terms:
description: Vault path(s) to be listed.
type: str
required: true
"""
EXAMPLES = """
- name: List all secrets at a path
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', 'secret/metadata', url='https://vault:8201') }}"
# For kv2, the path needs to follow the pattern 'mount_point/metadata' to list all secrets in that path
- name: List access policies
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', 'sys/policies/acl', url='https://vault:8201') }}"
- name: Perform multiple list operations with a single Vault login
vars:
paths:
- secret/metadata
- sys/policies/acl
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple list operations with a single Vault login in a loop
vars:
paths:
- secret/metadata
- sys/policies/acl
ansible.builtin.debug:
msg: '{{ item }}'
loop: "{{ query('community.hashi_vault.vault_list', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform list operations with a single Vault login in a loop (via with_)
vars:
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: '{{ user }}'
ansible_hashi_vault_password: '{{ pwd }}'
ansible.builtin.debug:
msg: '{{ item }}'
with_community.hashi_vault.vault_list:
- secret/metadata
- sys/policies/acl
- name: Create fact consisting of list of dictionaries each with secret name (e.g. username) and value of a key (e.g. 'password') within that secret
ansible.builtin.set_fact:
credentials: >-
{{
credentials
| default([]) + [
{
'username': item,
'password': lookup('community.hashi_vault.vault_kv2_get', item, engine_mount_point='vpn-users').secret.password
}
]
}}
loop: "{{ query('community.hashi_vault.vault_list', 'vpn-users/metadata')[0].data['keys'] }}"
no_log: true
- ansible.builtin.debug:
msg: "{{ credentials }}"
- name: Create the same as above without looping, and only 2 logins
vars:
secret_names: >-
{{
query('community.hashi_vault.vault_list', 'vpn-users/metadata')
| map(attribute='data')
| map(attribute='keys')
| flatten
}}
secret_values: >-
{{
lookup('community.hashi_vault.vault_kv2_get', *secret_names, engine_mount_point='vpn-users')
| map(attribute='secret')
| map(attribute='password')
| flatten
}}
credentials_dict: "{{ dict(secret_names | zip(secret_values)) }}"
ansible.builtin.set_fact:
credentials_dict: "{{ credentials_dict }}"
credentials_list: "{{ credentials_dict | dict2items(key_name='username', value_name='password') }}"
no_log: true
- ansible.builtin.debug:
msg:
- "Dictionary: {{ credentials_dict }}"
- "List: {{ credentials_list }}"
- name: List all userpass users and output the token policies for each user
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_read', 'auth/userpass/users/' + item).data.token_policies }}"
loop: "{{ query('community.hashi_vault.vault_list', 'auth/userpass/users')[0].data['keys'] }}"
"""
RETURN = """
_raw:
description:
- The raw result of the read against the given path.
type: list
elements: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
for term in terms:
try:
data = client.list(term)
except hvac.exceptions.Forbidden:
raise AnsibleError("Forbidden: Permission Denied to path '%s'." % term)
if data is None:
raise AnsibleError("The path '%s' doesn't seem to exist." % term)
ret.append(data)
return ret