1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3 4# (c) 2018, Simon Dodsley (simon@purestorage.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__metaclass__ = type 9 10ANSIBLE_METADATA = {'metadata_version': '1.1', 11 'status': ['preview'], 12 'supported_by': 'community'} 13 14DOCUMENTATION = r''' 15--- 16module: purefa_ds 17version_added: '2.6' 18short_description: Configure FlashArray Directory Service 19description: 20- Set or erase configuration for the directory service. There is no facility 21 to SSL certificates at this time. Use the FlashArray GUI for this 22 additional configuration work. 23- To modify an existing directory service configuration you must first delete 24 an existing configuration and then recreate with new settings. 25author: 26- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com> 27options: 28 state: 29 type: str 30 description: 31 - Create or delete directory service configuration 32 default: present 33 choices: [ absent, present ] 34 enable: 35 description: 36 - Whether to enable or disable directory service support. 37 default: false 38 type: bool 39 uri: 40 type: list 41 description: 42 - A list of up to 30 URIs of the directory servers. Each URI must include 43 the scheme ldap:// or ldaps:// (for LDAP over SSL), a hostname, and a 44 domain name or IP address. For example, ldap://ad.company.com configures 45 the directory service with the hostname "ad" in the domain "company.com" 46 while specifying the unencrypted LDAP protocol. 47 base_dn: 48 type: str 49 description: 50 - Sets the base of the Distinguished Name (DN) of the directory service 51 groups. The base should consist of only Domain Components (DCs). The 52 base_dn will populate with a default value when a URI is entered by 53 parsing domain components from the URI. The base DN should specify DC= 54 for each domain component and multiple DCs should be separated by commas. 55 required: true 56 bind_password: 57 type: str 58 description: 59 - Sets the password of the bind_user user name account. 60 bind_user: 61 type: str 62 description: 63 - Sets the user name that can be used to bind to and query the directory. 64 - For Active Directory, enter the username - often referred to as 65 sAMAccountName or User Logon Name - of the account that is used to 66 perform directory lookups. 67 - For OpenLDAP, enter the full DN of the user. 68 group_base: 69 type: str 70 description: 71 - Specifies where the configured groups are located in the directory 72 tree. This field consists of Organizational Units (OUs) that combine 73 with the base DN attribute and the configured group CNs to complete 74 the full Distinguished Name of the groups. The group base should 75 specify OU= for each OU and multiple OUs should be separated by commas. 76 The order of OUs is important and should get larger in scope from left 77 to right. Each OU should not exceed 64 characters in length. 78 - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module. 79 ro_group: 80 type: str 81 description: 82 - Sets the common Name (CN) of the configured directory service group 83 containing users with read-only privileges on the FlashArray. This 84 name should be just the Common Name of the group without the CN= 85 specifier. Common Names should not exceed 64 characters in length. 86 - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module. 87 sa_group: 88 type: str 89 description: 90 - Sets the common Name (CN) of the configured directory service group 91 containing administrators with storage-related privileges on the 92 FlashArray. This name should be just the Common Name of the group 93 without the CN= specifier. Common Names should not exceed 64 94 characters in length. 95 - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module. 96 aa_group: 97 type: str 98 description: 99 - Sets the common Name (CN) of the directory service group containing 100 administrators with full privileges when managing the FlashArray. 101 The name should be just the Common Name of the group without the 102 CN= specifier. Common Names should not exceed 64 characters in length. 103 - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module. 104extends_documentation_fragment: 105- purestorage.fa 106''' 107 108EXAMPLES = r''' 109- name: Delete existing directory service 110 purefa_ds: 111 state: absent 112 fa_url: 10.10.10.2 113 api_token: e31060a7-21fc-e277-6240-25983c6c4592 114 115- name: Create directory service (disabled) - Pre-5.2.0 116 purefa_ds: 117 uri: "ldap://lab.purestorage.com" 118 base_dn: "DC=lab,DC=purestorage,DC=com" 119 bind_user: Administrator 120 bind_password: password 121 group_base: "OU=Pure-Admin" 122 ro_group: PureReadOnly 123 sa_group: PureStorage 124 aa_group: PureAdmin 125 fa_url: 10.10.10.2 126 api_token: e31060a7-21fc-e277-6240-25983c6c4592 127 128- name: Create directory service (disabled) - 5.2.0 or higher 129 purefa_ds: 130 uri: "ldap://lab.purestorage.com" 131 base_dn: "DC=lab,DC=purestorage,DC=com" 132 bind_user: Administrator 133 bind_password: password 134 fa_url: 10.10.10.2 135 api_token: e31060a7-21fc-e277-6240-25983c6c4592 136 137- name: Enable existing directory service 138 purefa_ds: 139 enable: true 140 fa_url: 10.10.10.2 141 api_token: e31060a7-21fc-e277-6240-25983c6c4592 142 143- name: Disable existing directory service 144 purefa_ds: 145 enable: false 146 fa_url: 10.10.10.2 147 api_token: e31060a7-21fc-e277-6240-25983c6c4592 148 149- name: Create directory service (enabled) - Pre-5.2.0 150 purefa_ds: 151 enable: true 152 uri: "ldap://lab.purestorage.com" 153 base_dn: "DC=lab,DC=purestorage,DC=com" 154 bind_user: Administrator 155 bind_password: password 156 group_base: "OU=Pure-Admin" 157 ro_group: PureReadOnly 158 sa_group: PureStorage 159 aa_group: PureAdmin 160 fa_url: 10.10.10.2 161 api_token: e31060a7-21fc-e277-6240-25983c6c4592 162 163- name: Create directory service (enabled) - 5.2.0 or higher 164 purefa_ds: 165 enable: true 166 uri: "ldap://lab.purestorage.com" 167 base_dn: "DC=lab,DC=purestorage,DC=com" 168 bind_user: Administrator 169 bind_password: password 170 fa_url: 10.10.10.2 171 api_token: e31060a7-21fc-e277-6240-25983c6c4592 172''' 173 174RETURN = r''' 175''' 176 177from ansible.module_utils.basic import AnsibleModule 178from ansible.module_utils.pure import get_system, purefa_argument_spec 179 180 181DS_ROLE_REQUIRED_API_VERSION = '1.16' 182 183 184def update_ds(module, array): 185 """Update Directory Service""" 186 changed = False 187 module.exit_json(changed=changed) 188 189 190def enable_ds(module, array): 191 """Enable Directory Service""" 192 changed = False 193 try: 194 array.enable_directory_service() 195 changed = True 196 except Exception: 197 module.fail_json(msg='Enable Directory Service failed: Check Configuration') 198 module.exit_json(changed=changed) 199 200 201def disable_ds(module, array): 202 """Disable Directory Service""" 203 """Disable Directory Service""" 204 changed = False 205 try: 206 array.disable_directory_service() 207 changed = True 208 except Exception: 209 module.fail_json(msg='Disable Directory Service failed') 210 module.exit_json(changed=changed) 211 212 213def delete_ds(module, array): 214 """Delete Directory Service""" 215 changed = False 216 try: 217 api_version = array._list_available_rest_versions() 218 array.set_directory_service(enabled=False) 219 if DS_ROLE_REQUIRED_API_VERSION in api_version: 220 array.set_directory_service(uri=[''], 221 base_dn="", 222 bind_user="", 223 bind_password="", 224 certificate="") 225 changed = True 226 else: 227 array.set_directory_service(uri=[''], 228 base_dn="", 229 group_base="", 230 bind_user="", 231 bind_password="", 232 readonly_group="", 233 storage_admin_group="", 234 array_admin_group="", 235 certificate="") 236 changed = True 237 except Exception: 238 module.fail_json(msg='Delete Directory Service failed') 239 module.exit_json(changed=changed) 240 241 242def create_ds(module, array): 243 """Create Directory Service""" 244 changed = False 245 api_version = array._list_available_rest_versions() 246 if DS_ROLE_REQUIRED_API_VERSION in api_version: 247 if not module.params['role']: 248 module.fail_json(msg='At least one role must be configured') 249 try: 250 array.set_directory_service(uri=module.params['uri'], 251 base_dn=module.params['base_dn'], 252 bind_user=module.params['bind_user'], 253 bind_password=module.params['bind_password']) 254 array.set_directory_service(enabled=module.params['enable']) 255 changed = True 256 except Exception: 257 module.fail_json(msg='Create Directory Service failed: Check configuration') 258 else: 259 groups_rule = [not module.params['ro_group'], 260 not module.params['sa_group'], 261 not module.params['aa_group']] 262 263 if all(groups_rule): 264 module.fail_json(msg='At least one group must be configured') 265 try: 266 array.set_directory_service(uri=module.params['uri'], 267 base_dn=module.params['base_dn'], 268 group_base=module.params['group_base'], 269 bind_user=module.params['bind_user'], 270 bind_password=module.params['bind_password'], 271 readonly_group=module.params['ro_group'], 272 storage_admin_group=module.params['sa_group'], 273 array_admin_group=module.params['aa_group']) 274 array.set_directory_service(enabled=module.params['enable']) 275 changed = True 276 except Exception: 277 module.fail_json(msg='Create Directory Service failed: Check configuration') 278 module.exit_json(changed=changed) 279 280 281def main(): 282 argument_spec = purefa_argument_spec() 283 argument_spec.update(dict( 284 uri=dict(type='list'), 285 state=dict(type='str', default='present', choices=['absent', 'present']), 286 enable=dict(type='bool', default=False), 287 bind_password=dict(type='str', no_log=True), 288 bind_user=dict(type='str'), 289 base_dn=dict(type='str'), 290 group_base=dict(type='str'), 291 ro_group=dict(type='str'), 292 sa_group=dict(type='str'), 293 aa_group=dict(type='str'), 294 )) 295 296 required_together = [['uri', 'bind_password', 'bind_user', 297 'base_dn', 'group_base']] 298 299 module = AnsibleModule(argument_spec, 300 required_together=required_together, 301 supports_check_mode=False) 302 303 state = module.params['state'] 304 array = get_system(module) 305 ds_exists = False 306 dirserv = array.get_directory_service() 307 ds_enabled = dirserv['enabled'] 308 if dirserv['base_dn']: 309 ds_exists = True 310 311 if state == 'absent' and ds_exists: 312 delete_ds(module, array) 313 elif ds_exists and module.params['enable'] and ds_enabled: 314 update_ds(module, array) 315 elif ds_exists and not module.params['enable'] and ds_enabled: 316 disable_ds(module, array) 317 elif ds_exists and module.params['enable'] and not ds_enabled: 318 enable_ds(module, array) 319 elif not ds_exists and state == 'present': 320 create_ds(module, array) 321 else: 322 module.exit_json(changed=False) 323 324 325if __name__ == '__main__': 326 main() 327