Coverage for plugins/modules/purefb_userpolicy.py: 54%
119 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-30 17:06 -0400
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-30 17:06 -0400
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
4# (c) 2021, Simon Dodsley (simon@everpuredata.com)
5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7from __future__ import absolute_import, division, print_function
9__metaclass__ = type
11ANSIBLE_METADATA = {
12 "metadata_version": "1.1",
13 "status": ["preview"],
14 "supported_by": "community",
15}
17DOCUMENTATION = r"""
18---
19module: purefb_userpolicy
20version_added: '1.6.0'
21short_description: Manage FlashBlade Object Store User Access Policies
22description:
23- Add or Remove FlashBlade Object Store Access Policies for Account User
24author:
25- Everpure Ansible Team (@sdodsley) <pure-ansible-team@everpuredata.com>
26options:
27 name:
28 description:
29 - Name of the Object Store User
30 - The user to have the policy request applied to
31 type: str
32 account:
33 description:
34 - Name of the Object Store Account associated with the user
35 type: str
36 state:
37 description:
38 - Define whether the Access Policy should be added or deleted
39 - Option to list all available policies
40 default: present
41 choices: [ absent, present, show ]
42 type: str
43 policy:
44 description:
45 - Policies to added or deleted from the Object Store User
46 - Only valid policies can be used
47 - use I(list) to see available policies
48 type: list
49 elements: str
50 context:
51 description:
52 - Name of fleet member on which to perform the operation.
53 - This requires the array receiving the request is a member of a fleet
54 and the context name to be a member of the same fleet.
55 type: str
56 default: ""
57 version_added: "1.22.0"
58extends_documentation_fragment:
59- everpure.flashblade.everpure.fb
60"""
62EXAMPLES = r"""
63- name: List existng ruser access policies for a specific user
64 everpure.flashblade.purefb_userpolicy:
65 state: show
66 account: foo
67 name: bar
68 fb_url: 10.10.10.2
69 api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
70 register: policy_list
72- name: List all available user access policies
73 everpure.flashblade.purefb_userpolicy:
74 state: show
75 fb_url: 10.10.10.2
76 api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
77 register: policy_list
79- name: Add user access policies to account user foo/bar
80 everpure.flashblade.purefb_userpolicy:
81 name: bar
82 account: foo
83 policy:
84 - pure:policy/bucket-create
85 - pure:policy/bucket-delete
86 fb_url: 10.10.10.2
87 api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
89- name: Delete user access policies to account user foo/bar
90 everpure.flashblade.purefb_userpolicy:
91 name: bar
92 account: foo
93 policy:
94 - pure:policy/bucket-create
95 - pure:policy/bucket-delete
96 state: absent
97 fb_url: 10.10.10.2
98 api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
99"""
101RETURN = r"""
102policy_list:
103 description:
104 - Returns the list of access policies for a user
105 - If no user specified returns all available access policies
106 returned: always
107 type: list
108 elements: str
109 sample: ['pure:policy/object-list', 'pure:policy/bucket-list', 'pure:policy/object-read', 'pure:policy/bucket-delete', 'pure:policy/full-access']
110"""
112from ansible.module_utils.basic import AnsibleModule
113from ansible_collections.everpure.flashblade.plugins.module_utils.purefb import (
114 get_system,
115 purefb_argument_spec,
116)
117from ansible_collections.everpure.flashblade.plugins.module_utils.version import (
118 LooseVersion,
119)
120from ansible_collections.everpure.flashblade.plugins.module_utils.common import (
121 get_error_message,
122 get_rest_api_version,
123)
125CONTEXT_API_VERSION = "2.17"
128def _check_valid_policy(module, blade, policy):
129 api_version = get_rest_api_version(blade)
130 if (
131 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
132 and module.params["context"]
133 ):
134 return bool(
135 blade.get_object_store_access_policies(
136 names=[policy], context_names=[module.params["context"]]
137 )
138 )
139 return bool(blade.get_object_store_access_policies(names=[policy]))
142def add_policy(module, blade):
143 """Add a single or list of policies to an account user"""
144 changed = False
145 api_version = get_rest_api_version(blade)
146 user_policy_list = []
147 policy_list = module.params["policy"]
148 for policy in policy_list:
149 if not _check_valid_policy(module, blade, policy):
150 module.fail_json(msg="Policy {0} is not valid.".format(policy))
151 username = module.params["account"] + "/" + module.params["name"]
152 for policy in policy_list:
153 if (
154 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
155 and module.params["context"]
156 ):
157 res = blade.get_object_store_users_object_store_access_policies(
158 member_names=[username],
159 policy_names=[policy],
160 context_names=[module.params["context"]],
161 )
162 else:
163 res = blade.get_object_store_users_object_store_access_policies(
164 member_names=[username], policy_names=[policy]
165 )
166 if not list(res.items):
167 if not module.check_mode:
168 if (
169 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
170 and module.params["context"]
171 ):
172 res = blade.post_object_store_access_policies_object_store_users(
173 member_names=[username],
174 policy_names=[policy],
175 context_names=[module.params["context"]],
176 )
177 else:
178 res = blade.post_object_store_access_policies_object_store_users(
179 member_names=[username], policy_names=[policy]
180 )
181 if res.status_code != 200:
182 module.fail_json(
183 msg="Failed to add policy {0} to account user {1}. Error: {2}".format(
184 policy, username, get_error_message(res)
185 )
186 )
187 changed = True
188 if (
189 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
190 and module.params["context"]
191 ):
192 user_policies = list(
193 blade.get_object_store_access_policies_object_store_users(
194 member_names=[username],
195 context_names=[module.params["context"]],
196 ).items
197 )
198 else:
199 user_policies = list(
200 blade.get_object_store_access_policies_object_store_users(
201 member_names=[username]
202 ).items
203 )
204 for user_policy in user_policies:
205 user_policy_list.append(user_policy.policy.name)
206 module.exit_json(changed=changed, policy_list=user_policy_list)
209def remove_policy(module, blade):
210 """Remove a single or list of policies to an account user"""
211 changed = False
212 api_version = get_rest_api_version(blade)
213 user_policy_list = []
214 policy_list = module.params["policy"]
215 for policy in policy_list:
216 if not _check_valid_policy(module, blade, policy):
217 module.fail_json(msg="Policy {0} is not valid.".format(policy))
218 username = module.params["account"] + "/" + module.params["name"]
219 for policy in policy_list:
220 if (
221 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
222 and module.params["context"]
223 ):
224 res = blade.get_object_store_users_object_store_access_policies(
225 member_names=[username],
226 policy_names=[policy],
227 context_names=[module.params["context"]],
228 ).total_item_count
229 else:
230 res = blade.get_object_store_users_object_store_access_policies(
231 member_names=[username], policy_names=[policy]
232 ).total_item_count
233 if res == 1:
234 if not module.check_mode:
235 changed = True
236 if (
237 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
238 and module.params["context"]
239 ):
240 res = blade.delete_object_store_access_policies_object_store_users(
241 member_names=[username],
242 policy_names=[policy],
243 context_names=[module.params["context"]],
244 )
245 else:
246 res = blade.delete_object_store_access_policies_object_store_users(
247 member_names=[username], policy_names=[policy]
248 )
249 if (
250 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
251 and module.params["context"]
252 ):
253 user_policies = list(
254 blade.get_object_store_access_policies_object_store_users(
255 member_names=[username],
256 context_names=[module.params["context"]],
257 ).items
258 )
259 else:
260 user_policies = list(
261 blade.get_object_store_access_policies_object_store_users(
262 member_names=[username]
263 ).items
264 )
265 for user_policy in user_policies:
266 user_policy_list.append(user_policy.policy.name)
267 if res.status_code != 200:
268 module.fail_json(
269 msg="Failed to remove policy {0} from account user {1}. Error: {2}".format(
270 policy, username, get_error_message(res)
271 )
272 )
273 module.exit_json(changed=changed, policy_list=user_policy_list)
276def list_policy(module, blade):
277 """List Object Store User Access Policies"""
278 # Listing is read-only: it never changes the array, in or out of check mode.
279 changed = False
280 api_version = get_rest_api_version(blade)
281 policy_list = []
282 if module.params["account"] and module.params["name"]:
283 username = module.params["account"] + "/" + module.params["name"]
284 if (
285 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
286 and module.params["context"]
287 ):
288 res = blade.get_object_store_access_policies_object_store_users(
289 member_names=[username],
290 context_names=[module.params["context"]],
291 )
292 else:
293 res = blade.get_object_store_access_policies_object_store_users(
294 member_names=[username]
295 )
296 if res.status_code != 200:
297 module.fail_json(
298 msg="Failed to get access policies for account user {0}. "
299 "Error: {1}".format(username, get_error_message(res))
300 )
301 for user_policy in list(res.items):
302 policy_list.append(user_policy.policy.name)
303 else:
304 if (
305 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
306 and module.params["context"]
307 ):
308 policies = blade.get_object_store_access_policies(
309 context_names=[module.params["context"]]
310 )
311 else:
312 policies = blade.get_object_store_access_policies()
313 if policies.status_code != 200:
314 module.fail_json(msg="Failed to get Object Store User Access Policies")
315 for policy in list(policies.items):
316 policy_list.append(policy.name)
317 module.exit_json(changed=changed, policy_list=policy_list)
320def main():
321 argument_spec = purefb_argument_spec()
322 argument_spec.update(
323 dict(
324 state=dict(
325 type="str", default="present", choices=["absent", "present", "show"]
326 ),
327 name=dict(type="str"),
328 account=dict(type="str"),
329 policy=dict(type="list", elements="str"),
330 context=dict(type="str", default=""),
331 )
332 )
333 required_if = [
334 ["state", "present", ["name", "account", "policy"]],
335 ["state", "absent", ["name", "account", "policy"]],
336 ]
337 module = AnsibleModule(
338 argument_spec, required_if=required_if, supports_check_mode=True
339 )
341 blade = get_system(module)
342 api_version = get_rest_api_version(blade)
343 if (
344 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
345 and not module.params["context"]
346 ):
347 # If no context is provided set the context to the local array name
348 fleet_res = blade.get_fleets()
349 if fleet_res.status_code == 200 and list(fleet_res.items):
350 module.params["context"] = list(blade.get_arrays().items)[0].name
352 state = module.params["state"]
353 # state=show without account/name lists every policy on the array, so the
354 # user lookup (and its name concatenation) must only run when a user is named.
355 if module.params["account"] and module.params["name"]:
356 username = module.params["account"] + "/" + module.params["name"]
357 if (
358 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
359 and module.params["context"]
360 ):
361 user_res = blade.get_object_store_users(
362 names=[username], context_names=[module.params["context"]]
363 )
364 else:
365 user_res = blade.get_object_store_users(names=[username])
366 if user_res.status_code != 200:
367 module.fail_json(msg="Account User {0} does not exist".format(username))
368 if state == "show":
369 list_policy(module, blade)
370 elif state == "present":
371 add_policy(module, blade)
372 elif state == "absent":
373 remove_policy(module, blade)
375 module.exit_json(changed=False)
378if __name__ == "__main__":
379 main()