aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xlibrary/rabbitmq_user_3_7_9.py315
-rw-r--r--tasks/rabbitmq_users.yml19
2 files changed, 323 insertions, 11 deletions
diff --git a/library/rabbitmq_user_3_7_9.py b/library/rabbitmq_user_3_7_9.py
new file mode 100755
index 0000000..5be78b7
--- /dev/null
+++ b/library/rabbitmq_user_3_7_9.py
@@ -0,0 +1,315 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# (c) 2013, Chatham Financial <oss@chathamfinancial.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
10
11ANSIBLE_METADATA = {'metadata_version': '1.1',
12 'status': ['preview'],
13 'supported_by': 'community'}
14
15
16DOCUMENTATION = '''
17---
18module: rabbitmq_user_3_7_9
19short_description: Adds or removes users to RabbitMQ
20description:
21 - Add or remove users to RabbitMQ and assign permissions
22version_added: "1.1"
23author: '"Chris Hoffman (@chrishoffman)"'
24options:
25 user:
26 description:
27 - Name of user to add
28 required: true
29 default: null
30 aliases: [username, name]
31 password:
32 description:
33 - Password of user to add.
34 - To change the password of an existing user, you must also specify
35 C(force=yes).
36 required: false
37 default: null
38 tags:
39 description:
40 - User tags specified as comma delimited
41 required: false
42 default: null
43 permissions:
44 description:
45 - a list of dicts, each dict contains vhost, configure_priv, write_priv, and read_priv,
46 and represents a permission rule for that vhost.
47 - This option should be preferable when you care about all permissions of the user.
48 - You should use vhost, configure_priv, write_priv, and read_priv options instead
49 if you care about permissions for just some vhosts.
50 required: false
51 default: []
52 vhost:
53 description:
54 - vhost to apply access privileges.
55 - This option will be ignored when permissions option is used.
56 required: false
57 default: /
58 node:
59 description:
60 - erlang node name of the rabbit we wish to configure
61 required: false
62 default: rabbit
63 version_added: "1.2"
64 configure_priv:
65 description:
66 - Regular expression to restrict configure actions on a resource
67 for the specified vhost.
68 - By default all actions are restricted.
69 - This option will be ignored when permissions option is used.
70 required: false
71 default: ^$
72 write_priv:
73 description:
74 - Regular expression to restrict configure actions on a resource
75 for the specified vhost.
76 - By default all actions are restricted.
77 - This option will be ignored when permissions option is used.
78 required: false
79 default: ^$
80 read_priv:
81 description:
82 - Regular expression to restrict configure actions on a resource
83 for the specified vhost.
84 - By default all actions are restricted.
85 - This option will be ignored when permissions option is used.
86 required: false
87 default: ^$
88 force:
89 description:
90 - Deletes and recreates the user.
91 required: false
92 default: "no"
93 choices: [ "yes", "no" ]
94 state:
95 description:
96 - Specify if user is to be added or removed
97 required: false
98 default: present
99 choices: [present, absent]
100'''
101
102EXAMPLES = '''
103# Add user to server and assign full access control on / vhost.
104# The user might have permission rules for other vhost but you don't care.
105- rabbitmq_user_3_7_9:
106 user: joe
107 password: changeme
108 vhost: /
109 configure_priv: .*
110 read_priv: .*
111 write_priv: .*
112 state: present
113
114# Add user to server and assign full access control on / vhost.
115# The user doesn't have permission rules for other vhosts
116- rabbitmq_user_3_7_9:
117 user: joe
118 password: changeme
119 permissions:
120 - vhost: /
121 configure_priv: .*
122 read_priv: .*
123 write_priv: .*
124 state: present
125'''
126
127from ansible.module_utils.basic import AnsibleModule
128
129
130class RabbitMqUser(object):
131 def __init__(self, module, username, password, tags, permissions,
132 node, bulk_permissions=False):
133 self.module = module
134 self.username = username
135 self.password = password
136 self.node = node
137 if not tags:
138 self.tags = list()
139 else:
140 self.tags = tags.split(',')
141
142 self.permissions = permissions
143 self.bulk_permissions = bulk_permissions
144
145 self._tags = None
146 self._permissions = []
147 self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True)
148
149 def _exec(self, args, run_in_check_mode=False):
150 if not self.module.check_mode or run_in_check_mode:
151 cmd = [self._rabbitmqctl, '-q']
152 if self.node is not None:
153 cmd.extend(['-n', self.node])
154 rc, out, err = self.module.run_command(cmd + args, check_rc=True)
155 return out.splitlines() if len(out.strip()) else []
156 return list()
157
158 def get(self):
159 users = self._exec(self._list_args(['list_users']), True)
160
161 for user_tag in users:
162 if '\t' not in user_tag:
163 continue
164
165 user, tags = user_tag.split('\t')
166
167 if user == self.username:
168 for c in ['[', ']', ' ']:
169 tags = tags.replace(c, '')
170
171 if tags != '':
172 self._tags = tags.split(',')
173 else:
174 self._tags = list()
175
176 self._permissions = self._get_permissions()
177 return True
178 return False
179
180 def _get_permissions(self):
181 perms_out = self._exec(self._list_args(['list_user_permissions', self.username]), True)
182
183 perms_list = list()
184 for perm in perms_out:
185 vhost, configure_priv, write_priv, read_priv = perm.split('\t')
186 if not self.bulk_permissions:
187 if vhost == self.permissions[0]['vhost']:
188 perms_list.append(dict(vhost=vhost, configure_priv=configure_priv,
189 write_priv=write_priv, read_priv=read_priv))
190 break
191 else:
192 perms_list.append(dict(vhost=vhost, configure_priv=configure_priv,
193 write_priv=write_priv, read_priv=read_priv))
194 return perms_list
195
196 '''
197 Monkey Patching the 'rabbitmq_user_3_7_9' ansible module for 3.7.9 rabbit version
198 where headers were added in the output
199 Cf: https://github.com/rabbitmq/rabbitmq-cli/issues/264
200 '''
201 def _list_args(self, args):
202 return args + ['--no-table-headers']
203
204 def add(self):
205 if self.password is not None:
206 self._exec(['add_user', self.username, self.password])
207 else:
208 self._exec(['add_user', self.username, ''])
209 self._exec(['clear_password', self.username])
210
211 def delete(self):
212 self._exec(['delete_user', self.username])
213
214 def set_tags(self):
215 self._exec(['set_user_tags', self.username] + self.tags)
216
217 def set_permissions(self):
218 for permission in self._permissions:
219 if permission not in self.permissions:
220 cmd = ['clear_permissions', '-p']
221 cmd.append(permission['vhost'])
222 cmd.append(self.username)
223 self._exec(cmd)
224 for permission in self.permissions:
225 if permission not in self._permissions:
226 cmd = ['set_permissions', '-p']
227 cmd.append(permission['vhost'])
228 cmd.append(self.username)
229 cmd.append(permission['configure_priv'])
230 cmd.append(permission['write_priv'])
231 cmd.append(permission['read_priv'])
232 self._exec(cmd)
233
234 def has_tags_modifications(self):
235 return set(self.tags) != set(self._tags)
236
237 def has_permissions_modifications(self):
238 return sorted(self._permissions) != sorted(self.permissions)
239
240
241def main():
242 arg_spec = dict(
243 user=dict(required=True, aliases=['username', 'name']),
244 password=dict(default=None, no_log=True),
245 tags=dict(default=None),
246 permissions=dict(default=list(), type='list'),
247 vhost=dict(default='/'),
248 configure_priv=dict(default='^$'),
249 write_priv=dict(default='^$'),
250 read_priv=dict(default='^$'),
251 force=dict(default='no', type='bool'),
252 state=dict(default='present', choices=['present', 'absent']),
253 node=dict(default=None)
254 )
255 module = AnsibleModule(
256 argument_spec=arg_spec,
257 supports_check_mode=True
258 )
259
260 username = module.params['user']
261 password = module.params['password']
262 tags = module.params['tags']
263 permissions = module.params['permissions']
264 vhost = module.params['vhost']
265 configure_priv = module.params['configure_priv']
266 write_priv = module.params['write_priv']
267 read_priv = module.params['read_priv']
268 force = module.params['force']
269 state = module.params['state']
270 node = module.params['node']
271
272 bulk_permissions = True
273 if not permissions:
274 perm = {
275 'vhost': vhost,
276 'configure_priv': configure_priv,
277 'write_priv': write_priv,
278 'read_priv': read_priv
279 }
280 permissions.append(perm)
281 bulk_permissions = False
282
283 rabbitmq_user_3_7_9 = RabbitMqUser(module, username, password, tags, permissions,
284 node, bulk_permissions=bulk_permissions)
285
286 result = dict(changed=False, user=username, state=state)
287
288 if rabbitmq_user_3_7_9.get():
289 if state == 'absent':
290 rabbitmq_user_3_7_9.delete()
291 result['changed'] = True
292 else:
293 if force:
294 rabbitmq_user_3_7_9.delete()
295 rabbitmq_user_3_7_9.add()
296 rabbitmq_user_3_7_9.get()
297 result['changed'] = True
298
299 if rabbitmq_user_3_7_9.has_tags_modifications():
300 rabbitmq_user_3_7_9.set_tags()
301 result['changed'] = True
302
303 if rabbitmq_user_3_7_9.has_permissions_modifications():
304 rabbitmq_user_3_7_9.set_permissions()
305 result['changed'] = True
306 elif state == 'present':
307 rabbitmq_user_3_7_9.add()
308 rabbitmq_user_3_7_9.set_tags()
309 rabbitmq_user_3_7_9.set_permissions()
310 result['changed'] = True
311
312 module.exit_json(**result)
313
314if __name__ == '__main__':
315 main()
diff --git a/tasks/rabbitmq_users.yml b/tasks/rabbitmq_users.yml
index 7bba65e..d09d624 100644
--- a/tasks/rabbitmq_users.yml
+++ b/tasks/rabbitmq_users.yml
@@ -10,15 +10,14 @@
10 tags: "{{ item['tags']|default(omit) }}" 10 tags: "{{ item['tags']|default(omit) }}"
11 permissions: "{{ item['permissions']|default(omit) }}" 11 permissions: "{{ item['permissions']|default(omit) }}"
12 state: present 12 state: present
13 run_once: rabbitmq_enable_clustering is defined and rabbitmq_enable_clustering
14 delegate_to: "{{ rabbitmq_master|default(omit) }}"
13 become: true 15 become: true
14 with_items: "{{ rabbitmq_users }}" 16 with_items: "{{ rabbitmq_users }}"
15 when: > 17 when: rabbitmq_debian_version is version('3.7.9', '<')
16 (rabbitmq_enable_clustering is defined and
17 not rabbitmq_enable_clustering) or
18 rabbitmq_enable_clustering is not defined
19 18
20- name: rabbitmq_users | creating rabbitmq users 19- name: rabbitmq_users | creating rabbitmq users (rabbit >= 3.7.9)
21 rabbitmq_user: 20 rabbitmq_user_3_7_9:
22 name: "{{ item['name'] }}" 21 name: "{{ item['name'] }}"
23 password: "{{ item['password'] }}" 22 password: "{{ item['password'] }}"
24 vhost: "{{ item['vhost']|default(omit) }}" 23 vhost: "{{ item['vhost']|default(omit) }}"
@@ -28,10 +27,8 @@
28 tags: "{{ item['tags']|default(omit) }}" 27 tags: "{{ item['tags']|default(omit) }}"
29 permissions: "{{ item['permissions']|default(omit) }}" 28 permissions: "{{ item['permissions']|default(omit) }}"
30 state: present 29 state: present
31 run_once: yes 30 run_once: rabbitmq_enable_clustering is defined and rabbitmq_enable_clustering
32 delegate_to: "{{ rabbitmq_master }}" 31 delegate_to: "{{ rabbitmq_master|default(omit) }}"
33 become: true 32 become: true
34 with_items: "{{ rabbitmq_users }}" 33 with_items: "{{ rabbitmq_users }}"
35 when: > 34 when: rabbitmq_debian_version is version('3.7.9', '>=')
36 rabbitmq_enable_clustering is defined and
37 rabbitmq_enable_clustering