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

1#!/usr/bin/python 

2# -*- coding: utf-8 -*- 

3 

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) 

6 

7from __future__ import absolute_import, division, print_function 

8 

9__metaclass__ = type 

10 

11ANSIBLE_METADATA = { 

12 "metadata_version": "1.1", 

13 "status": ["preview"], 

14 "supported_by": "community", 

15} 

16 

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""" 

61 

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 

71 

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 

78 

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 

88 

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""" 

100 

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""" 

111 

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) 

124 

125CONTEXT_API_VERSION = "2.17" 

126 

127 

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])) 

140 

141 

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) 

207 

208 

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) 

274 

275 

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) 

318 

319 

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 ) 

340 

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 

351 

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) 

374 

375 module.exit_json(changed=False) 

376 

377 

378if __name__ == "__main__": 

379 main()