forked from rabbitmq/rabbitmq-website
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaccess-control.xml
534 lines (473 loc) · 20.7 KB
/
access-control.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
<?xml-stylesheet type="text/xml" href="page.xsl"?>
<!--
Copyright (c) 2007-2016 Pivotal Software, Inc.
All rights reserved. This program and the accompanying materials
are made available under the terms of the under the Apache License,
Version 2.0 (the "License”); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:doc="http://www.rabbitmq.com/namespaces/ad-hoc/doc"
xmlns:x="http://www.rabbitmq.com/2011/extensions">
<head>
<title>Access Control (Authentication, Authorisation) in RabbitMQ</title>
</head>
<body>
<doc:section name="intro">
<p>
This document describes authentication and authorisation machinery that
implements access control.
Authentication backends should not be confused with
<a href="http://www.rabbitmq.com/authentication.html">authentication mechanisms</a>
in AMQP 0-9-1.
</p>
</doc:section>
<doc:section name="terminology-and-definitions">
<doc:heading>Terminology and Definitions</doc:heading>
<p>
Authentication and authorisation are often confused or used
interchangeably. That's wrong and in RabbitMQ, the two are
separated. For the sake of simplicity, we'll define
authentication as "identifying who the user is" and
authorisation as "determining what the user is and isn't
allowed to do."
</p>
</doc:section>
<doc:section name="default-state">
<doc:heading>Default Virtual Host and User</doc:heading>
<p>
When the server first starts running, and detects that its
database is uninitialised or has been deleted, it
initialises a fresh database with the following resources:
</p>
<ul class="compact">
<li>
a virtual host named <code>/</code>
</li>
<li>
a user named <code>guest</code> with a default password of
<code>guest</code>, granted full access to the
<code>/</code> virtual host.
</li>
</ul>
<p>
It is advisable
to <a href="man/rabbitmqctl.1.man.html#delete_user">delete</a>
the <code>guest</code> user
or <a href="man/rabbitmqctl.1.man.html#change_password">change
the password</a> to something private, particularly if your
broker is accessible publicly.
</p>
</doc:section>
<doc:section name="loopback-users">
<doc:heading>"guest" user can only connect via localhost</doc:heading>
<p>
By default, the <code>guest</code> user is prohibited from
connecting to the broker remotely; it can only connect over
a loopback interface (i.e. <code>localhost</code>). This
applies both to AMQP 0-9-1 and to any other protocols enabled via
plugins. Any other users you create will not (by default) be
restricted in this way.
</p>
<p>
This is configured via the <code>loopback_users</code> item
in the <a href="configure.html#configuration-file">
configuration file</a>.
</p>
<p>
If you wish to allow the <code>guest</code> user to connect
from a remote host, you should set the
<code>loopback_users</code> configuration to
<code>none</code>. A complete <a href="/configure.html">RabbitMQ config file</a>
which does this would look like:
</p>
<pre class="sourcecode ini">
loopback_users = none
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config file format</a> (<code>rabbitmq.config</code>):
<pre class="sourcecode erlang">
[{rabbit, [{loopback_users, []}]}].
</pre>
</doc:section>
<doc:section name="access-control">
<doc:heading>How Permissions Work</doc:heading>
<p>
When a RabbitMQ client establishes a connection to a
server, it specifies a virtual host within which it intends
to operate. A first level of access control is enforced at
this point, with the server checking whether the user has
any permissions to access the virtual hosts, and rejecting
the connection attempt otherwise.
</p>
<p>
Resources, i.e. exchanges and queues, are named entities
inside a particular virtual host; the same name denotes a
different resource in each virtual host. A second level of
access control is enforced when certain operations are
performed on resources.
</p>
<p>
RabbitMQ distinguishes between <em>configure</em>,
<em>write</em> and <em>read</em> operations on a
resource. The <em>configure</em> operations create or
destroy resources, or alter their behaviour. The
<em>write</em> operations inject messages into a
resource. And the <em>read</em> operations retrieve messages
from a resource.
</p>
<p>
In order to perform an operation on a resource the user must
have been granted the appropriate permissions for it. The
following table shows what permissions on what type of
resource are required for all the AMQP commands which
perform permission checks.
<table>
<tr>
<th>AMQP 0-9-1 Operation</th>
<th></th>
<th>configure</th>
<th>write</th>
<th>read</th>
</tr>
<tr>
<td>exchange.declare</td><td>(passive=false)</td><td>exchange</td><td/><td/>
</tr>
<tr>
<td>exchange.declare</td><td>(passive=true)</td><td></td><td/><td/>
</tr>
<tr>
<td>exchange.declare</td><td>(with <a href="ae.html">AE</a>)</td><td>exchange</td><td>exchange (AE)</td><td>exchange</td>
</tr>
<tr>
<td>exchange.delete</td><td/><td>exchange</td><td/><td/>
</tr>
<tr>
<td>queue.declare</td><td>(passive=false)</td><td>queue</td><td/><td/>
</tr>
<tr>
<td>queue.declare</td><td>(passive=true)</td><td></td><td/><td/>
</tr>
<tr>
<td>queue.declare</td><td>(with <a href="dlx.html">DLX</a>)</td><td>queue</td><td>exchange (DLX)</td><td>queue</td>
</tr>
<tr>
<td>queue.delete</td><td/><td>queue</td><td/><td/>
</tr>
<tr>
<td>exchange.bind</td><td/><td/><td>exchange (destination)</td><td>exchange (source)</td>
</tr>
<tr>
<td>exchange.unbind</td><td/><td/><td>exchange (destination)</td><td>exchange (source)</td>
</tr>
<tr>
<td>queue.bind</td><td/><td/><td>queue</td><td>exchange</td>
</tr>
<tr>
<td>queue.unbind</td><td/><td/><td>queue</td><td>exchange</td>
</tr>
<tr>
<td>basic.publish</td><td/><td/><td>exchange</td><td/>
</tr>
<tr>
<td>basic.get</td><td/><td/><td/><td>queue</td>
</tr>
<tr>
<td>basic.consume</td><td/><td/><td/><td>queue</td>
</tr>
<tr>
<td>queue.purge</td><td/><td/><td/><td>queue</td>
</tr>
</table>
</p>
<p>
Permissions are expressed as a triple of regular expressions
- one each for configure, write and read - on per-vhost
basis. The user is granted the respective permission for
operations on all resources with names matching the regular
expressions. <i>(Note: For convenience RabbitMQ maps AMQP's
default exchange's blank name to 'amq.default' when
performing permission checks.)</i>
</p>
<p>
The regular expression <code>'^$'</code>, i.e. matching
nothing but the empty string, covers all resources and
effectively stops the user from performing any operation.
Standard AMQP resource names are prefixed with
<code>amq.</code> and server generated names are prefixed
with <code>amq.gen</code>. For example,
<code>'^(amq\.gen.*|amq\.default)$'</code> gives a user access to
server-generated names and the default exchange. The empty
string, <code>''</code> is a synonym for <code>'^$'</code>
and restricts permissions in the exact same way.
</p>
<p>
RabbitMQ may cache the results of access control checks on a
per-connection or per-channel basis. Hence changes to user
permissions may only take effect when the user reconnects.
</p>
<p>
For details of how to set up access control, please see the
<a href="man/rabbitmqctl.1.man.html#Access%20control">Access Control section</a>
of the <a href="man/rabbitmqctl.1.man.html">rabbitmqctl(1) man page</a>.
</p>
</doc:section>
<doc:section name="topic-authorisation">
<doc:heading>Topic Authorisation</doc:heading>
<p>
As of version 3.7.0, RabbitMQ supports topic authorisation for topic exchanges. The routing key of a message
published to a topic exchange is taken into account when
publishing authorisation is enforced (e.g. in RabbitMQ default authorisation backend,
the routing key is matched against a regular expression to decide whether the message can be
routed downstream or not).
Topic authorisation targets protocols like STOMP and MQTT, which are structured
around topics and use topic exchanges under the hood.
</p>
<p>
Topic authorisation is an additional layer on top of
existing checks for publishers. Publishing a
message to a topic-typed exchange will go through both the
<code>basic.publish</code> and the routing key checks.
The latter is never called if the former refuses access.
</p>
<p>
Topic authorisation can also be enforced for topic consumers.
Note that it works different for different protocols. The concept
of topic authorisation only really makes sense for the topic-oriented protocols such as MQTT
and STOMP. In AMQP 0-9-1, for example, consumers consume from queues
and thus the standard resource permissions apply. In addition for AMQP 0-9-1,
binding routing keys between an AMQP 0-9-1 topic exchange and
a queue/exchange are checked against the topic permissions configured, if any.
For more information about how RabbitMQ handles authorization for topics, please see
the <a href="stomp.html">STOMP</a> and <a href="mqtt.html">MQTT</a>
documentation guides.
</p>
<p>
When default authorisation backend is used, publishing to a
topic exchange or consuming from a topic is always authorised
if no topic permissions
are defined (which is the case on a fresh RabbitMQ
installation). With this authorisation backend, topic
authorisation as optional: you don't need to whitelist any
exchanges. To use topic authorisation therefore you need to opt in
and define topic permissions for one or more exchanges. For details please see the <a
href="man/rabbitmqctl.1.man.html#Access%20control">Access
Control section</a> of the <a
href="man/rabbitmqctl.1.man.html">rabbitmqctl(1) man
page</a>.
</p>
<p>
Internal (default) authorisation backend supports variable expansion
in permission patterns.
Three variables are supported: <code>username</code>, <code>vhost</code>,
and <code>client_id</code>. Note that <code>client_id</code> only
applies to MQTT. For example, if <code>tonyg</code> is the
connected user, the permission <code>^{username}-.*</code> is expanded to
<code>^tonyg-.*</code>
</p>
<p>
If a different authorisation backend (e.g. <a href="ldap.html">LDAP</a>,
<a href="https://github.com/rabbitmq/rabbitmq-auth-backend-http">HTTP</a>,
<a href="https://github.com/rabbitmq/rabbitmq-auth-backend-amqp">AMQP</a>) is used, please refer
to the documentation of those backends.
</p>
<p>
If a custom authorisation backend is used, topic
authorisation is enforced by implementing the
<code>check_topic_access</code> callback of the
<code>rabbit_authz_backend</code> behavior.
</p>
</doc:section>
<doc:section name="backends">
<doc:heading>Alternative Authentication and Authorisation Backends</doc:heading>
<p>
Authentication and authorisation are pluggable. Plugins can provide implementations
of
<ul>
<li>authentication ("authn") backends</li>
<li>authorisation ("authz") backends</li>
</ul>
It is possible for a plugin to provide both.
For example the internal, <a href="/ldap.html">LDAP</a>
and <a href="https://github.com/rabbitmq/rabbitmq-auth-backend-http">HTTP</a>
backends do so.
</p>
<p>
Some plugins, for example, the <a
href="https://github.com/gotthardp/rabbitmq-auth-backend-ip-range">Source
IP range one</a>, only provide an authorisation backend. Authentication
is supposed to be handled by the internal database, LDAP, etc.
</p>
<doc:subsection name="combined-backends">
<doc:heading>Combining Backends</doc:heading>
<p>
It is possible to use multiple backends for
<code>authn</code> or <code>authz</code> using the
<code>auth_backends</code> configuration key. When
several authentication backends are used then the first
positive result returned by a backend in the chain is
considered to be final. This should not be confused with
mixed backends (for example, using LDAP for authentication and internal
backend for authorisation).
</p>
<p>
The following example configures RabbitMQ to use the internal backend
only (and is the default):
</p>
<pre class="sourcecode ini">
# rabbitmq.conf
#
# 1 here is a backend name. It can be anything.
# Since we only really care about backend
# ordering, we use numbers throughout this guide.
#
# "internal" is an alias for rabbit_auth_backend_internal
auth_backends.1 = internal
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [rabbit_auth_backend_internal]}
]
}].
</pre>
<p>
The example above uses an alias, <code>internal</code> for <code>rabbit_auth_backend_internal</code>.
The following aliases are available:
<ul>
<li><code>internal</code> for <code>rabbit_auth_backend_internal</code></li>
<li><code>ldap</code> for <code>rabbit_auth_backend_ldap</code> (from the <a href="/ldap.html">LDAP plugin</a>)</li>
<li><code>http</code> for <code>rabbit_auth_backend_http</code> (from the <a href="https://github.com/rabbitmq/rabbitmq-auth-backend-http">HTTP auth backend plugin</a>)</li>
<li><code>amqp</code> for <code>rabbit_auth_backend_amqp</code> (from the <a href="https://github.com/rabbitmq/rabbitmq-auth-backend-amqp">AMQP 0-9-1 auth backend plugin</a>)</li>
<li><code>dummy</code> for <code>rabbit_auth_backend_dummy</code></li>
</ul>
When using third party plugins, providing a full module name is necessary.
</p>
<p>
The following example configures RabbitMQ to use the <a href="/ldap.html">LDAP backend</a>
for both authentication and authorisation. Internal database will not be consulted:
</p>
<pre class="sourcecode ini">
auth_backends.1 = ldap
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [rabbit_auth_backend_ldap]}
]
}].
</pre>
<p>
This will check LDAP first, and then fall back to the internal
database if the user cannot be authenticated through LDAP:
</p>
<pre class="sourcecode ini">
auth_backends.1 = ldap
auth_backends.2 = internal
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [rabbit_auth_backend_ldap, rabbit_auth_backend_internal]}
]
}].
</pre>
<p>
Same as above but will fall back to the <a
href="https://github.com/rabbitmq/rabbitmq-auth-backend-http">HTTP backend</a>
instead:
</p>
<pre class="sourcecode ini">
# rabbitmq.conf
#
auth_backends.1 = ldap
# uses module name instead of a short alias, "http"
auth_backends.2 = rabbit_auth_backend_http
# See HTTP backend docs for details
auth_http.user_path = http://my-authenticator-app/auth/user
auth_http.vhost_path = http://my-authenticator-app/auth/vhost
auth_http.resource_path = http://my-authenticator-app/auth/resource
auth_http.topic_path = http://my-authenticator-app/auth/topic
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [rabbit_auth_backend_ldap, rabbit_auth_backend_http]}
]
},
%% See HTTP backend docs for details
{rabbitmq_auth_backend_http,
[{user_path, "http://my-authenticator-app/auth/user"},
{vhost_path, "http://my-authenticator-app/auth/vhost"},
{resource_path, "http://my-authenticator-app/auth/resource"},
{topic_path, "http://my-authenticator-app/auth/topic"}]}].
</pre>
<p>
The following example configures RabbitMQ to use internal
database for authentication and <a
href="https://github.com/gotthardp/rabbitmq-auth-backend-ip-range">source
IP range backend</a> for authorisation:
</p>
<pre class="sourcecode ini">
# rabbitmq.conf
#
auth_backends.1.authn = internal
# uses module name because this backend is from a 3rd party
auth_backends.1.authz = rabbit_auth_backend_ip_range
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [{rabbit_auth_backend_internal, rabbit_auth_backend_ip_range}]}
]
}].
</pre>
<p>
The following example configures RabbitMQ to use <a href="/ldap.html">LDAP backend</a>
for authentication and but internal backend for authorisation:
</p>
<pre class="sourcecode ini">
# rabbitmq.conf
#
auth_backends.1.authn = ldap
auth_backends.1.authz = internal
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal}]
]}].
</pre>
<p>
The example below is fairly advanced. It will check LDAP
first. If the user is found in LDAP then the password will be
checked against LDAP and subsequent authorisation checks will
be performed against the internal database (therefore users in
LDAP must exist in the internal database as well, but do not
need a password there). If the user is not found in LDAP then
a second attempt is made using only the internal database:
</p>
<pre class="sourcecode ini">
# rabbitmq.conf
#
auth_backends.1.authn = ldap
auth_backends.1.authz = internal
auth_backends.2 = internal
</pre>
Or, in the <a href="/configure.html#erlang-term-config-file">classic config format</a>:
<pre class="sourcecode erlang">
[{rabbit, [
{auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal},
rabbit_auth_backend_internal]}
]
}].
</pre>
</doc:subsection>
</doc:section>
</body>
</html>