rabbitmq_http_auth_backend 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96a75df203d47f917752b3cef73ec78a6e3f6a570db3c1e92f778c380276ef1b
4
- data.tar.gz: aee167ba2a0804d262a564b15a53bce8df4ccb17a243999750eec2e8cc8d59e2
3
+ metadata.gz: fd12d683b1642bfeee042ebe891b33d2ca4e81c2d7bcb55be0764e1f04eee17d
4
+ data.tar.gz: de3568b054e40b4c40c3c44e01787084bc134a28e4baec90e88e1ab1808a610d
5
5
  SHA512:
6
- metadata.gz: 1946c3abd0c748a6cf11c16a71e52d0d16ad85ac338cd813a6f7625320511a89bda3549abe8a3827a137c9839c8492203071b319c07717217cf9859e0ad4ee8e
7
- data.tar.gz: 273f0c29de8a6f6c31d8c2593e7d86bb21426e5da84c7079626766984eff535651079e3dac58202bec98b3989d7519a29cb01ef036548fa28d18acf52f38b489
6
+ metadata.gz: ff46159edf0371a1c8ace6e7f95a3f6ad54f679fd27f321ff7411a6e7be4d9cf8613636acc0117faaae4d58b24ae86049519db83b61582e96380fb22467bdb12
7
+ data.tar.gz: 910e309b702173ec6cd8420f136bf446b1e908fe33abc3191c9df44abac5f17d5c60f276eed581709b6a650c047e7aa4e55a1af63404684a2476ccc5085f3743
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rabbitmq_http_auth_backend (1.0.0)
4
+ rabbitmq_http_auth_backend (1.1.0)
5
5
  roda (~> 3.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  Mountable Rack application that implements a configurable API for RabbitMQ's
4
4
  [rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http).
5
5
 
6
+ [![Gem Version](https://badge.fury.io/rb/rabbitmq_http_auth_backend.svg)](https://badge.fury.io/rb/rabbitmq_http_auth_backend)
7
+
6
8
  ## Purpose
7
9
 
8
10
  RabbitMQ comes bundled with the [rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http)
@@ -21,6 +23,21 @@ This library implements all of this as a mountable Rack application. Meaning,
21
23
  after minimal configuration your application can implement the four required
22
24
  endpoints and respond with correctly formated responses.
23
25
 
26
+ ## Index
27
+
28
+ 1. [Usage](#usage)
29
+ 1. [Mounting the endpoint](#mounting-the-endpoint)
30
+ 2. [Configuration](#configuration)
31
+ 3. [Resolvers](#resolvers)
32
+ 4. [Versioning](#versioning)
33
+ 5. [Default configuration](#default-configuration)
34
+ 2. [Installation](#installation)
35
+ 3. [FAQ](#faq)
36
+ 4. [Change log](#change-log)
37
+ 5. [Development](#development)
38
+ 6. [Contributing](#contributing)
39
+ 7. [License](#license)
40
+
24
41
  ## Usage
25
42
 
26
43
  1. [Mounting the endpoint](#mounting-the-endpoint)
@@ -42,7 +59,7 @@ For **Rails** applications, add the following line to your `routes.rb` file:
42
59
  ```ruby
43
60
  # /config/routes.rb
44
61
  Rails.application.routes.draw do
45
- mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth'
62
+ mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth', as: 'rmq_auth_api'
46
63
  end
47
64
  ```
48
65
 
@@ -121,7 +138,7 @@ RabbitMQHttpAuthBackend.configure! do
121
138
  path '/anvandare'
122
139
  resolver(lambda do |params|
123
140
  if params['username'] == 'admin'
124
- return :allow
141
+ return :allow, [:admin, :moderator]
125
142
  end
126
143
 
127
144
  :deny
@@ -136,7 +153,11 @@ end
136
153
  class TopicsResolver
137
154
  def self.call(params)
138
155
  if params['username'] == 'admin'
139
- return :allow, ['admin', 'manager']
156
+ return :allow
157
+ end
158
+
159
+ if params['permission'] == 'read' && params['name'] == 'messages'
160
+ return :allow
140
161
  end
141
162
 
142
163
  :deny
@@ -144,11 +165,70 @@ class TopicsResolver
144
165
  end
145
166
  ```
146
167
 
147
- A "native" configuration DSL is also provided. The DSL provides utility methods
148
- such as `username`, `password`, `vhost`, `resource`, `name`, `permission`, `ip`
149
- and `routing_key`. Any utility methods `allow!` and `deny!` can be used to set
150
- the return value (they don't have to be the return value).
151
- Just note that they don't stop execution!
168
+ Most commonly used methods related to resolvers are extracted to the
169
+ `BasicResolver` class. Any class inheriting from it becomes a callable object
170
+ on the class and instance level. The user is expected to implement the `#call`
171
+ method.
172
+
173
+ The following methods are available within a class inheriting from
174
+ `BasicResolver`:
175
+
176
+ | Method | Description |
177
+ |:--------------|:-------------------------------------------------------------|
178
+ | `username` | Returns the user's username |
179
+ | `password` | Returns the user's password |
180
+ | `name` | Returns the name of the resource |
181
+ | `queue?` | Returns true if the queried resource is a queue |
182
+ | `exchange?` | Returns true if the queried resource is an exchange |
183
+ | `topic?` | Returns true if the queried resource is a topic |
184
+ | `resource` | Returns the resource type (as a String, e.g. `'exchange'`) |
185
+ | `read?` | Returns true if the queried permission is read |
186
+ | `write?` | Returns true if the queried permission is write |
187
+ | `configure?` | Returns true if the queried permission is write |
188
+ | `permission` | Returns the requested permission (as a String, e.g. `'read'`)|
189
+ | `routing_key` | Returns the queried routing key |
190
+ | `vhost` | Returns the queried vhost |
191
+ | `ip` | Returns the IP address of the client querying |
192
+
193
+ The following is the same as the `TopicsResolver` from the previous example, but
194
+ rewritten using `BasicResolver`:
195
+
196
+ ```ruby
197
+ class TopicsResolver < RabbitMQHttpAuthBackend::BasicResolver
198
+ def call
199
+ return :allow if username == 'admin'
200
+ return :allow if name == 'messages' && read?
201
+ :deny
202
+ end
203
+ end
204
+
205
+ # This makes `TopicsResolver` a callable object on the class level
206
+ # > TopicsResolver.call(params)
207
+ # And it's callable on the instance level
208
+ # > TopicsResolver.new(params).call
209
+ ```
210
+
211
+ A "native" configuration DSL is also provided. The DSL provides the same utility
212
+ methods as `BasicResolver` as well as `allow!`, `deny!`, `tags`, `allowed?` and
213
+ `denised?` which can be used to set the result or to query it - note that they
214
+ don't stop execution!
215
+
216
+ ```ruby
217
+ # /config/initializers/rabbitmq_http_auth_backend.rb
218
+ RabbitMQHttpAuthBackend.configure! do
219
+ http_method :post
220
+
221
+ topic do
222
+ resolver do
223
+ if username == 'admin'
224
+ allow! ['admin', 'manager']
225
+ else
226
+ deny!
227
+ end
228
+ end
229
+ end
230
+ end
231
+ ```
152
232
 
153
233
  Not all methods return usable values for all resources. Here's a list:
154
234
  * user
@@ -172,23 +252,6 @@ Not all methods return usable values for all resources. Here's a list:
172
252
  - `permission` (can return `:configure`, `:read` or `:write`)
173
253
  - `routing_key` (of the published message if the permission is `:write`, else of the queue binding)
174
254
 
175
- ```ruby
176
- # /config/initializers/rabbitmq_http_auth_backend.rb
177
- RabbitMQHttpAuthBackend.configure! do
178
- http_method :post
179
-
180
- topic do
181
- resolver do
182
- if username == 'admin'
183
- allow! ['admin', 'manager']
184
- else
185
- deny!
186
- end
187
- end
188
- end
189
- end
190
- ```
191
-
192
255
  ### Versioning
193
256
 
194
257
  Everybody makes mistakes and changes their minds. Therefore this library
@@ -309,10 +372,136 @@ Mount the application:
309
372
  ```ruby
310
373
  # /config/routes.rb
311
374
  Rails.application.routes.draw do
312
- mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth'
375
+ mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth', as: 'rmq_auth_api'
313
376
  end
314
377
  ```
315
378
 
379
+ You are done!
380
+
381
+ ```
382
+ bash-4.4$ curl localhost:3000/rabbitmq/auth/user && echo
383
+ deny
384
+ ```
385
+
386
+ ## FAQ
387
+
388
+ <details>
389
+ <summary>You use a version in your installation example. Do I have to use a version?</summary>
390
+ <p>
391
+ You don't have to, but I would advise you do.
392
+ Editing the default configuration might cause you problems in the future
393
+ when you would like to have a clean slate.
394
+ </p>
395
+ </details>
396
+
397
+ <details>
398
+ <summary>Why does the "native" DSL exist?</summary>
399
+ <p>
400
+ To provide a simple configuration language to accomplish basic tasks. I
401
+ would advise you to use `BasicResolver` or a custom resolver callable object
402
+ for anything other than the most basic use case e.g. check a username or IP.
403
+ </p>
404
+ </details>
405
+
406
+ <details>
407
+ <summary>Can my path be nested? E.g. `/foo/bar/baz/cux`?</summary>
408
+ <p>Yes they can.</p>
409
+ </details>
410
+
411
+ <details>
412
+ <summary>Can my path contain arguments? E.g. `/foo/:name/bar`?</summary>
413
+ <p>At the moment, no.</p>
414
+ </details>
415
+
416
+ <details>
417
+ <summary>Does this library handle caching for me?</summary>
418
+ <p>
419
+ No. This feature was removed from the original implementation of this
420
+ library.
421
+ </p>
422
+ <p>
423
+ Caching is a tricky topic. It's hard to get right. I couldn't find an
424
+ expressive enough interface for handling cache invalidation that would
425
+ satisfy my needs or be flexible enough to accommodate the use cases I think
426
+ are common. Therefore I decided against implementing caching within this
427
+ library.
428
+ </p>
429
+ <p>
430
+ I recommend that you implement your custom caching and invalidation logic
431
+ in a custom resolver.
432
+ </p>
433
+ <p>
434
+ Also, use the <a href="https://github.com/rabbitmq/rabbitmq-auth-backend-cache">rabbitmq-auth-backend-cache</a> plugin.
435
+ It provides time based client-side caching and comes standard with RabbitMQ 3.7+
436
+ </p>
437
+ <p>
438
+ Here is an example of a fully configured HTTP auth backend plugin in
439
+ conjunction with the caching plugin:
440
+ </p>
441
+ <pre>
442
+ auth_backends.1 = internal
443
+ auth_backends.2 = cache
444
+ auth_cache.cached_backend = http
445
+ auth_http.http_method = get
446
+ auth_http.user_path = http://localhost:3000/rabbitmq/auth/user
447
+ auth_http.vhost_path = http://localhost:3000/rabbitmq/auth/vhost
448
+ auth_http.resource_path = http://localhost:3000/rabbitmq/auth/resource
449
+ auth_http.topic_path = http://localhost:3000/rabbitmq/auth/topic
450
+ </pre>
451
+ </details>
452
+
453
+ <details>
454
+ <summary>How do you use Rabbit's HTTP backend?</summary>
455
+ <p>
456
+ Follow the installation instructions in this guide to setup your Rack
457
+ (Rails/Roda/Sinatra/...) application as an HTTP auth backend. Then add
458
+ the following to your `rabbitmq.conf`, located within `/etc/rabbitmq`
459
+ (if it's not there, create it).
460
+ </p>
461
+ <pre>
462
+ auth_backends.1 = internal
463
+ auth_backends.2 = http
464
+ auth_http.http_method = get
465
+ auth_http.user_path = http://localhost:3000/rabbitmq/auth/user
466
+ auth_http.vhost_path = http://localhost:3000/rabbitmq/auth/vhost
467
+ auth_http.resource_path = http://localhost:3000/rabbitmq/auth/resource
468
+ auth_http.topic_path = http://localhost:3000/rabbitmq/auth/topic
469
+ </pre>
470
+ <p>
471
+ Assuming that your application and RabbitMQ instance are on the same
472
+ machine, and that your application is exposed on port 3000 everything
473
+ should just work™️.
474
+ </p>
475
+ <p>
476
+ If it doesn't work try restarting RabbitMQ and your application.
477
+ </p>
478
+ <p>
479
+ If your application and RabbitMQ instance aren't on the same machine, make
480
+ sure that the RabbitMQ instance can access your application, the
481
+ easiest way to do this is to connect to the RabbitMQ server and using
482
+ `ping <your application URL or IP>` or `curl <your application URL or IP>:<your application port>`.
483
+ Remember to change the `localhost:3000` in `rabbitmq.conf` to your
484
+ application's URL or IP.
485
+ </p>
486
+ </details>
487
+
488
+ <details>
489
+ <summary>Why does this library depend on Roda?</summary>
490
+ <p>
491
+ <a href="https://github.com/jeremyevans/roda">Roda</a> is, in my opinion, a lightweight framework around Rack.
492
+ I prefer it over raw Rack - since, in my opinion, the overhead of it is
493
+ negligible over raw Rack I use it as a more ergonomic interface to create
494
+ Rack applications.
495
+ </p>
496
+ </details>
497
+
498
+ ## Change log
499
+
500
+ All changes between versions are logged to the change log available in the
501
+ [CHANGELOG.md file](/CHANGELOG.md).
502
+
503
+ This project follows the [semantic versioning schema](https://semver.org/).
504
+
316
505
  ## Development
317
506
 
318
507
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -329,7 +518,7 @@ to [rubygems.org](https://rubygems.org).
329
518
  ## Contributing
330
519
 
331
520
  Bug reports and pull requests are welcome on GitHub at
332
- https://github.com/monorkin/rabbitmq_http_auth_backend/.
521
+ [https://github.com/monorkin/rabbitmq_http_auth_backend/](https://github.com/monorkin/rabbitmq_http_auth_backend/).
333
522
 
334
523
  ## License
335
524
 
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class BasicResolver < Service
5
+ def initialize(params)
6
+ @params = params
7
+ end
8
+
9
+ protected
10
+
11
+ attr_reader :params
12
+
13
+ private
14
+
15
+ def username
16
+ params['username']
17
+ end
18
+
19
+ def password
20
+ params['password']
21
+ end
22
+
23
+ def name
24
+ params['name']
25
+ end
26
+
27
+ def queue?
28
+ resource == 'queue'
29
+ end
30
+
31
+ def exchange?
32
+ resource == 'exchange'
33
+ end
34
+
35
+ def topic?
36
+ resource == 'topic'
37
+ end
38
+
39
+ def resource
40
+ params['resource']
41
+ end
42
+
43
+ def read?
44
+ permission == 'read'
45
+ end
46
+
47
+ def write?
48
+ permission == 'write'
49
+ end
50
+
51
+ def configure?
52
+ permission == 'configure'
53
+ end
54
+
55
+ def permission
56
+ params['permission']
57
+ end
58
+
59
+ def routing_key
60
+ params['routing_key']
61
+ end
62
+
63
+ def vhost
64
+ params['vhost']
65
+ end
66
+
67
+ def ip
68
+ params['ip']
69
+ end
70
+ end
71
+ end
@@ -50,4 +50,5 @@ module RabbitMQHttpAuthBackend
50
50
  end
51
51
  end
52
52
 
53
+ require 'rabbitmq_http_auth_backend/basic_resolver'
53
54
  require 'rabbitmq_http_auth_backend/resolver/runtime'
@@ -2,17 +2,12 @@
2
2
 
3
3
  module RabbitMQHttpAuthBackend
4
4
  class Resolver
5
- class Runtime
6
- class Error < RabbitMQHttpAuthBackend::Error; end
7
- class InvalidResourceError < Error; end
8
- class InvalidPermissionError < Error; end
9
-
10
- attr_reader :params
5
+ class Runtime < BasicResolver
11
6
  attr_accessor :tags
12
7
  attr_accessor :_allowed
13
8
 
14
9
  def initialize(params)
15
- @params = params
10
+ super(params)
16
11
  self.tags = nil
17
12
  self._allowed = false
18
13
  end
@@ -34,50 +29,6 @@ module RabbitMQHttpAuthBackend
34
29
  def denied?
35
30
  !allowed?
36
31
  end
37
-
38
- def username
39
- params['username']
40
- end
41
-
42
- def password
43
- params['password']
44
- end
45
-
46
- def vhost
47
- params['vhost']
48
- end
49
-
50
- def resource
51
- @resource ||=
52
- case params['resource']
53
- when 'exchange' then :exchange
54
- when 'queue' then :queue
55
- when 'topic' then :topic
56
- else raise(InvalidResourceError)
57
- end
58
- end
59
-
60
- def name
61
- params['name']
62
- end
63
-
64
- def permission
65
- @permission ||=
66
- case params['permission']
67
- when 'configure' then :configure
68
- when 'write' then :write
69
- when 'read' then :read
70
- else raise(InvalidPermissionError)
71
- end
72
- end
73
-
74
- def ip
75
- params['ip']
76
- end
77
-
78
- def routing_key
79
- params['routing_key']
80
- end
81
32
  end
82
33
  end
83
34
  end
@@ -3,7 +3,7 @@
3
3
  module RabbitMQHttpAuthBackend
4
4
  module Version
5
5
  MAJOR = 1
6
- MINOR = 0
6
+ MINOR = 1
7
7
  PATCH = 0
8
8
 
9
9
  FULL = [MAJOR, MINOR, PATCH].join('.').freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbitmq_http_auth_backend
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanko K.R.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-02 00:00:00.000000000 Z
11
+ date: 2019-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: roda
@@ -109,6 +109,7 @@ files:
109
109
  - lib/rabbitmq_http_auth_backend.rb
110
110
  - lib/rabbitmq_http_auth_backend/app.rb
111
111
  - lib/rabbitmq_http_auth_backend/app/response_formatter.rb
112
+ - lib/rabbitmq_http_auth_backend/basic_resolver.rb
112
113
  - lib/rabbitmq_http_auth_backend/config.rb
113
114
  - lib/rabbitmq_http_auth_backend/config/runtime.rb
114
115
  - lib/rabbitmq_http_auth_backend/resolver.rb