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_user
17version_added: '2.8'
18short_description: Create, modify or delete FlashArray local user account
19description:
20- Create, modify or delete local users on a Pure Storage FlashArray.
21author:
22- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
23options:
24  state:
25    description:
26    - Create, delete or update local user account
27    default: present
28    type: str
29    choices: [ absent, present ]
30  name:
31    description:
32    - The name of the local user account
33    type: str
34  role:
35    description:
36    - Sets the local user's access level to the array
37    type: str
38    choices: [ readonly, storage_admin, array_admin ]
39  password:
40    description:
41    - Password for the local user.
42    type: str
43  old_password:
44    description:
45    - If changing an existing password, you must provide the old password for security
46    type: str
47  api:
48    description:
49    - Define whether to create an API token for this user
50    - Token can be exposed using the I(debug) module
51    type: bool
52    default: false
53extends_documentation_fragment:
54- purestorage.fa
55'''
56
57EXAMPLES = r'''
58- name: Create new user ansible with API token
59  purefa_user:
60    name: ansible
61    password: apassword
62    role: storage_admin
63    api: true
64    fa_url: 10.10.10.2
65    api_token: e31060a7-21fc-e277-6240-25983c6c4592
66  register: result
67
68  debug:
69    msg: "API Token: {{ result['user_info']['user_api'] }}"
70
71- name: Change role type for existing user
72  purefa_user:
73    name: ansible
74    role: array_admin
75    state: update
76    fa_url: 10.10.10.2
77    api_token: e31060a7-21fc-e277-6240-25983c6c4592
78
79- name: Change password type for existing user (NOT IDEMPOTENT)
80  purefa_user:
81    name: ansible
82    password: anewpassword
83    old_password: apassword
84    fa_url: 10.10.10.2
85    api_token: e31060a7-21fc-e277-6240-25983c6c4592
86
87- name: Change API token for existing user
88  purefa_user:
89    name: ansible
90    api: true
91    state: update
92    fa_url: 10.10.10.2
93    api_token: e31060a7-21fc-e277-6240-25983c6c4592
94  register: result
95
96  debug:
97    msg: "API Token: {{ result['user_info']['user_api'] }}"
98'''
99
100RETURN = r'''
101'''
102
103
104from ansible.module_utils.basic import AnsibleModule
105from ansible.module_utils.pure import get_system, purefa_argument_spec
106
107MIN_REQUIRED_API_VERSION = '1.14'
108
109
110def get_user(module, array):
111    """Return Local User Account or None"""
112    user = None
113    users = array.list_admins()
114    for acct in range(0, len(users)):
115        if users[acct]['name'] == module.params['name']:
116            user = users[acct]
117    return user
118
119
120def create_user(module, array):
121    """Create or Update Local User Account"""
122    changed = False
123    user = get_user(module, array)
124    role = module.params['role']
125    api_changed = False
126    role_changed = False
127    passwd_changed = False
128    user_token = {}
129    if not user:
130        try:
131            if not role:
132                role = 'readonly'
133            array.create_admin(module.params['name'], role=role,
134                               password=module.params['password'])
135            if module.params['api']:
136                try:
137                    user_token['user_api'] = array.create_api_token(module.params['name'])['api_token']
138                except Exception:
139                    array.delete_user(module.params['name'])
140                    module.fail_json(msg='Local User {0}: Creation failed'.format(module.params['name']))
141            changed = True
142        except Exception:
143            module.fail_json(msg='Local User {0}: Creation failed'.format(module.params['name']))
144    else:
145        if module.params['password'] and not module.params['old_password']:
146            changed = False
147            module.exit_json(changed=changed)
148        if module.params['password'] and module.params['old_password']:
149            if module.params['old_password'] and (module.params['password'] != module.params['old_password']):
150                try:
151                    array.set_admin(module.params['name'], password=module.params['password'],
152                                    old_password=module.params['old_password'])
153                    passwd_changed = True
154                except Exception:
155                    module.fail_json(msg='Local User {0}: Password reset failed. '
156                                     'Check old password.'.format(module.params['name']))
157            else:
158                module.fail_json(msg='Local User Account {0}: Password change failed - '
159                                 'Check both old and new passwords'.format(module.params['name']))
160        if module.params['api']:
161            try:
162                if not array.get_api_token(module.params['name'])['api_token'] is None:
163                    array.delete_api_token(module.params['name'])
164                user_token['user_api'] = array.create_api_token(module.params['name'])['api_token']
165                api_changed = True
166            except Exception:
167                module.fail_json(msg='Local User {0}: API token change failed'.format(module.params['name']))
168        if module.params['role'] != user['role']:
169            try:
170                array.set_admin(module.params['name'], role=module.params['role'])
171                role_changed = True
172            except Exception:
173                module.fail_json(msg='Local User {0}: Role changed failed'.format(module.params['name']))
174        if passwd_changed or role_changed or api_changed:
175            changed = True
176    module.exit_json(changed=changed, user_info=user_token)
177
178
179def delete_user(module, array):
180    """Delete Local User Account"""
181    changed = False
182    if get_user(module, array):
183        try:
184            array.delete_admin(module.params['name'])
185            changed = True
186        except Exception:
187            module.fail_json(msg='Object Store Account {0}: Deletion failed'.format(module.params['name']))
188    module.exit_json(changed=changed)
189
190
191def main():
192    argument_spec = purefa_argument_spec()
193    argument_spec.update(dict(
194        name=dict(required=True, type='str'),
195        role=dict(type='str', choices=['readonly', 'storage_admin', 'array_admin']),
196        state=dict(type='str', default='present', choices=['absent', 'present']),
197        password=dict(type='str', no_log=True),
198        old_password=dict(type='str', no_log=True),
199        api=dict(type='bool', default=False),
200    ))
201
202    module = AnsibleModule(argument_spec,
203                           supports_check_mode=False)
204
205    state = module.params['state']
206    array = get_system(module)
207    api_version = array._list_available_rest_versions()
208
209    if MIN_REQUIRED_API_VERSION not in api_version:
210        module.fail_json(msg='FlashArray REST version not supported. '
211                             'Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
212
213    if state == 'absent':
214        delete_user(module, array)
215    elif state == 'present':
216        create_user(module, array)
217    else:
218        module.exit_json(changed=False)
219
220
221if __name__ == '__main__':
222    main()
223