rabbitmq_http_auth_backend 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 96a75df203d47f917752b3cef73ec78a6e3f6a570db3c1e92f778c380276ef1b
4
+ data.tar.gz: aee167ba2a0804d262a564b15a53bce8df4ccb17a243999750eec2e8cc8d59e2
5
+ SHA512:
6
+ metadata.gz: 1946c3abd0c748a6cf11c16a71e52d0d16ad85ac338cd813a6f7625320511a89bda3549abe8a3827a137c9839c8492203071b319c07717217cf9859e0ad4ee8e
7
+ data.tar.gz: 273f0c29de8a6f6c31d8c2593e7d86bb21426e5da84c7079626766984eff535651079e3dac58202bec98b3989d7519a29cb01ef036548fa28d18acf52f38b489
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rabbitmq_http_auth_backend.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rabbitmq_http_auth_backend (1.0.0)
5
+ roda (~> 3.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.2)
11
+ diff-lcs (1.3)
12
+ method_source (0.9.2)
13
+ pry (0.12.2)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.9.0)
16
+ rack (2.0.7)
17
+ rack-test (1.1.0)
18
+ rack (>= 1.0, < 3)
19
+ rake (10.5.0)
20
+ roda (3.19.0)
21
+ rack
22
+ rspec (3.8.0)
23
+ rspec-core (~> 3.8.0)
24
+ rspec-expectations (~> 3.8.0)
25
+ rspec-mocks (~> 3.8.0)
26
+ rspec-core (3.8.0)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-expectations (3.8.3)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.8.0)
31
+ rspec-mocks (3.8.0)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.8.0)
34
+ rspec-support (3.8.0)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ bundler (~> 2.0)
41
+ pry (~> 0.12.2)
42
+ rabbitmq_http_auth_backend!
43
+ rack-test (~> 1.1.0)
44
+ rake (~> 10.0)
45
+ rspec (~> 3.0)
46
+
47
+ BUNDLED WITH
48
+ 2.0.1
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2019 Stanko K.R. <hey@stanko.io>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,342 @@
1
+ # RabbitMQHttpAuthBackend
2
+
3
+ Mountable Rack application that implements a configurable API for RabbitMQ's
4
+ [rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http).
5
+
6
+ ## Purpose
7
+
8
+ RabbitMQ comes bundled with the [rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http)
9
+ plug-in. The purpose of this plug-in is to authorize each action of an user
10
+ connected to RabbitMQ by asking a server over HTTP if the user is allowed to
11
+ do that action.
12
+
13
+ The plugin expects the server to implement four endpoints - one for
14
+ login (`/user`), one for vhost access, one for general resources (exchanges,
15
+ queues, topics) and one for topics.
16
+
17
+ Each endpoint has to respond with a custom format to either allow or deny the
18
+ action.
19
+
20
+ This library implements all of this as a mountable Rack application. Meaning,
21
+ after minimal configuration your application can implement the four required
22
+ endpoints and respond with correctly formated responses.
23
+
24
+ ## Usage
25
+
26
+ 1. [Mounting the endpoint](#mounting-the-endpoint)
27
+ 2. [Configuration](#configuration)
28
+ 3. [Resolvers](#resolvers)
29
+ 4. [Versioning](#versioning)
30
+ 5. [Default configuration](#default-configuration)
31
+
32
+ ### Mounting the endpoint
33
+
34
+ To use `RabbitMQHttpAuthBackend`, you will have to mount it within your
35
+ Rack application. This will expose it's endpoints from your application,
36
+ name spaced with by any prefix of your choosing.
37
+
38
+ The following are examples for some popular Rack based frameworks. Note that
39
+ `/rabbitmq/auth` is only a prefix and can be changed to whatever you desire.
40
+
41
+ For **Rails** applications, add the following line to your `routes.rb` file:
42
+ ```ruby
43
+ # /config/routes.rb
44
+ Rails.application.routes.draw do
45
+ mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth'
46
+ end
47
+ ```
48
+
49
+ For **Sinatra** applications, add the following to `config.ru`:
50
+ ```ruby
51
+ # config.ru
52
+ map '/rabbitmq/auth' do
53
+ run RabbitMQHttpAuthBackend.app
54
+ end
55
+ ```
56
+
57
+ For **Hanami** applications, add the following to `config/environment.rb`:
58
+ ```ruby
59
+ Hanami.configure do
60
+ mount RabbitMQHttpAuthBackend.app, at: '/rabbitmq/auth'
61
+ end
62
+ ```
63
+
64
+ For **Roda** applications, you have to call `run` from within your routing tree:
65
+ ```ruby
66
+ class MyApp < Roda
67
+ route do |r|
68
+ r.on '/rabbitmq/auth' do
69
+ r.run RabbitMQHttpAuthBackend.app
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ ### Configuration
76
+
77
+ `RabbitMQHttpAuthBackend` can be configured to suite your needs. Both the
78
+ HTTP method as well as the names of all the endpoints are configurable in the
79
+ following manner.
80
+
81
+ ```ruby
82
+ # /config/initializers/rabbitmq_http_auth_backend.rb
83
+ RabbitMQHttpAuthBackend.configure! do
84
+ http_method :post
85
+
86
+ user do
87
+ path '/anvandare'
88
+ end
89
+
90
+ vhost do
91
+ path '/vhost'
92
+ end
93
+
94
+ resource do
95
+ path '/resurs'
96
+ end
97
+
98
+ topic do
99
+ path '/amne'
100
+ end
101
+ end
102
+ ```
103
+
104
+ ### Resolvers
105
+
106
+ Resolvers are used to determine whether or not a user is allowed access to a
107
+ particular resource. Resolvers are passed as part of the configuration. They
108
+ can be any callable object - any object that responds to a `call` method that
109
+ takes one argument (the params, a hash containing RabbitMQ query information).
110
+
111
+ The return value of the resolver can be either `:allow` or `:deny`. If
112
+ additional tags need to be returned alongside `:allow` return an `Array`
113
+ containing `:allow` and an `Array` of tags - e.g. `[:allow, ['admin']]`.
114
+
115
+ ```ruby
116
+ # /config/initializers/rabbitmq_http_auth_backend.rb
117
+ RabbitMQHttpAuthBackend.configure! do
118
+ http_method :post
119
+
120
+ user do
121
+ path '/anvandare'
122
+ resolver(lambda do |params|
123
+ if params['username'] == 'admin'
124
+ return :allow
125
+ end
126
+
127
+ :deny
128
+ end)
129
+ end
130
+
131
+ topic do
132
+ resolver TopicsResolver
133
+ end
134
+ end
135
+
136
+ class TopicsResolver
137
+ def self.call(params)
138
+ if params['username'] == 'admin'
139
+ return :allow, ['admin', 'manager']
140
+ end
141
+
142
+ :deny
143
+ end
144
+ end
145
+ ```
146
+
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!
152
+
153
+ Not all methods return usable values for all resources. Here's a list:
154
+ * user
155
+ - `username`
156
+ - `password`
157
+ * vhost
158
+ - `username`
159
+ - `vhost`
160
+ - `ip`
161
+ * resource
162
+ - `username`
163
+ - `vhost`
164
+ - `resource` (can return `:exchange`, `:queue` or `:topic`)
165
+ - `name`
166
+ - `permission` (can return `:configure`, `:read` or `:write`)
167
+ * topic
168
+ - `username`
169
+ - `vhost`
170
+ - `resource` (can return `:topic`)
171
+ - `name`
172
+ - `permission` (can return `:configure`, `:read` or `:write`)
173
+ - `routing_key` (of the published message if the permission is `:write`, else of the queue binding)
174
+
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
+ ### Versioning
193
+
194
+ Everybody makes mistakes and changes their minds. Therefore this library
195
+ enables you to create multiple versions of itself and mount them.
196
+
197
+ There is little difference to the regular usage.
198
+
199
+ Mounting:
200
+ ```ruby
201
+ # /config/routes.rb
202
+ Rails.application.routes.draw do
203
+ mount RabbitMQHttpAuthBackend.app(:v1) => '/rabbitmq/auth'
204
+ # ^^^^^
205
+ end
206
+ ```
207
+
208
+ Configuration:
209
+ ```ruby
210
+ # /config/initializers/rabbitmq_http_auth_backend.rb
211
+ RabbitMQHttpAuthBackend.configure!(:v1) do
212
+ # ^^^^^
213
+ # ...
214
+ end
215
+ ```
216
+
217
+ If no version is given the `:default` or global configuration is edited.
218
+
219
+ ### Default configuration
220
+
221
+ The global default configuration can be changed by altering the configuration
222
+ for the `:default` version.
223
+
224
+ Here is the full default configuration
225
+
226
+ ```ruby
227
+ # /config/initializers/rabbitmq_http_auth_backend.rb
228
+ RabbitMQHttpAuthBackend.configure!(:default) do
229
+ http_method :get
230
+
231
+ user do
232
+ path '/user'
233
+ resolver do
234
+ deny!
235
+ end
236
+ end
237
+
238
+ vhost do
239
+ path '/vhost'
240
+ resolver do
241
+ deny!
242
+ end
243
+ end
244
+
245
+ resource do
246
+ path '/resource'
247
+ resolver do
248
+ deny!
249
+ end
250
+ end
251
+
252
+ topic do
253
+ path '/topic'
254
+ resolver do
255
+ deny!
256
+ end
257
+ end
258
+ end
259
+ ```
260
+
261
+ ## Installation
262
+
263
+ Add this line to your application's Gemfile:
264
+
265
+ ```ruby
266
+ # Gemfile
267
+ gem 'rabbitmq_http_auth_backend'
268
+ ```
269
+
270
+ Configure the library:
271
+
272
+ ```ruby
273
+ # /config/initializers/rabbitmq_http_auth_backend.rb
274
+ RabbitMQHttpAuthBackend.configure!(:v1) do
275
+ http_method :get
276
+
277
+ user do
278
+ path '/user'
279
+ resolver do
280
+ deny!
281
+ end
282
+ end
283
+
284
+ vhost do
285
+ path '/vhost'
286
+ resolver do
287
+ deny!
288
+ end
289
+ end
290
+
291
+ resource do
292
+ path '/resource'
293
+ resolver do
294
+ deny!
295
+ end
296
+ end
297
+
298
+ topic do
299
+ path '/topic'
300
+ resolver do
301
+ deny!
302
+ end
303
+ end
304
+ end
305
+ ```
306
+
307
+ Mount the application:
308
+
309
+ ```ruby
310
+ # /config/routes.rb
311
+ Rails.application.routes.draw do
312
+ mount RabbitMQHttpAuthBackend.app => '/rabbitmq/auth'
313
+ end
314
+ ```
315
+
316
+ ## Development
317
+
318
+ After checking out the repo, run `bin/setup` to install dependencies.
319
+ Then, run `rake spec` to run the tests.
320
+ You can also run `bin/console` for an interactive prompt that will allow you
321
+ to experiment.
322
+
323
+ To install this gem onto your local machine, run `bundle exec rake install`.
324
+ To release a new version, update the version number in `version.rb`, and then
325
+ run `bundle exec rake release`, which will create a git tag for the version,
326
+ push git commits and tags, and push the `.gem` file
327
+ to [rubygems.org](https://rubygems.org).
328
+
329
+ ## Contributing
330
+
331
+ Bug reports and pull requests are welcome on GitHub at
332
+ https://github.com/monorkin/rabbitmq_http_auth_backend/.
333
+
334
+ ## License
335
+
336
+ This software is licensed under the MIT license. A copy of the license
337
+ can be found in the [LICENSE.txt file](/LICENSE.txt) included with this
338
+ software.
339
+
340
+ **TL;DR** this software comes with absolutely no warranty of any kind.
341
+ You are free to redistribute and modify the software as long as the original
342
+ copyright notice is present in your derivative work.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class Error < StandardError; end
5
+
6
+ def self.configure!(version = nil, &block)
7
+ version ||= RabbitMQHttpAuthBackend::Config.default_configuration_key
8
+ RabbitMQHttpAuthBackend::Config.configuration[version] ||= {}
9
+ cfg = RabbitMQHttpAuthBackend::Config.configuration[version]
10
+ RabbitMQHttpAuthBackend::Config::Runtime.new(cfg).instance_eval(&block)
11
+ RabbitMQHttpAuthBackend::Config.version(version)
12
+ end
13
+
14
+ def self.app(version = nil)
15
+ version ||= RabbitMQHttpAuthBackend::Config.default_configuration_key
16
+ config = RabbitMQHttpAuthBackend::Config.new(version)
17
+ RabbitMQHttpAuthBackend::App.new(config).generate
18
+ end
19
+ end
20
+
21
+ require 'rabbitmq_http_auth_backend/version'
22
+ require 'rabbitmq_http_auth_backend/service'
23
+ require 'rabbitmq_http_auth_backend/config'
24
+ require 'rabbitmq_http_auth_backend/resolver'
25
+ require 'rabbitmq_http_auth_backend/app'
@@ -0,0 +1,39 @@
1
+ require 'roda'
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class App
5
+ RESOURCES = %i[user vhost resource topic].freeze
6
+ private_constant :RESOURCES
7
+
8
+ attr_reader :config
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ def generate
15
+ # NOTE: config has to be bound to the local scope as a variable to be
16
+ # accessible from within the class that is being built
17
+ config = self.config
18
+
19
+ Class.new(Roda) do
20
+ route do |r|
21
+ RESOURCES.map do |resource|
22
+ r.on(config.fetch(resource, :path)) do
23
+ r.is do
24
+ r.public_send(config.http_method) do
25
+ result =
26
+ RabbitMQHttpAuthBackend::Resolver
27
+ .call(r.params, config.fetch(resource, :resolver))
28
+ ResponseFormatter.call(result)
29
+ end
30
+ end
31
+ end
32
+ end.last
33
+ end
34
+ end.freeze.app
35
+ end
36
+ end
37
+ end
38
+
39
+ require 'rabbitmq_http_auth_backend/app/response_formatter'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class App
5
+ class ResponseFormatter < RabbitMQHttpAuthBackend::Service
6
+ attr_reader :response
7
+
8
+ def initialize(response)
9
+ @response = response
10
+ end
11
+
12
+ def call
13
+ action = response[0]
14
+ tags = response[1]
15
+
16
+ if action == :allow && tags
17
+ "#{action} #{tags.join(' ')}"
18
+ else
19
+ action.to_s
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class Config
5
+ DEFAULT_CFG_KEY = :default
6
+ private_constant :DEFAULT_CFG_KEY
7
+
8
+ DENY_PROC = (proc { deny! }).freeze
9
+ private_constant :DENY_PROC
10
+
11
+ DEFAULT_VALUES = {
12
+ # HTTP
13
+ http_method: :get,
14
+ # Paths
15
+ user_path: '/user',
16
+ vhost_path: '/vhost',
17
+ resource_path: '/resource',
18
+ topic_path: '/topic',
19
+ # Resolvers
20
+ user_resolver: DENY_PROC,
21
+ vhost_resolver: DENY_PROC,
22
+ resource_resolver: DENY_PROC,
23
+ topic_resolver: DENY_PROC
24
+ }.freeze
25
+ private_constant :DEFAULT_VALUES
26
+
27
+ def self.configuration
28
+ @configuration ||= { default_configuration_key => default_configuration }
29
+ end
30
+
31
+ def self.reset!
32
+ @configuration = { default_configuration_key => default_configuration }
33
+ end
34
+
35
+ def self.versions
36
+ configuration.keys
37
+ end
38
+
39
+ def self.default_configuration_key
40
+ DEFAULT_CFG_KEY
41
+ end
42
+
43
+ def self.default_configuration
44
+ {}.merge(DEFAULT_VALUES)
45
+ end
46
+
47
+ def self.version(version)
48
+ return unless versions.include?(version)
49
+
50
+ new(version)
51
+ end
52
+
53
+ attr_reader :version
54
+
55
+ def initialize(version = DEFAULT_CFG_KEY)
56
+ @version = version.to_sym
57
+ end
58
+
59
+ def http_method
60
+ data[:http_method]
61
+ end
62
+
63
+ def user_path
64
+ sanitize_path(data[:user_path])
65
+ end
66
+
67
+ def user_resolver
68
+ data[:user_resolver]
69
+ end
70
+
71
+ def vhost_path
72
+ sanitize_path(data[:vhost_path])
73
+ end
74
+
75
+ def vhost_resolver
76
+ data[:vhost_resolver]
77
+ end
78
+
79
+ def resource_path
80
+ sanitize_path(data[:resource_path])
81
+ end
82
+
83
+ def resource_resolver
84
+ data[:resource_resolver]
85
+ end
86
+
87
+ def topic_path
88
+ sanitize_path(data[:topic_path])
89
+ end
90
+
91
+ def topic_resolver
92
+ data[:topic_resolver]
93
+ end
94
+
95
+ def fetch(resource, element)
96
+ method = "#{resource}_#{element}".to_sym
97
+ return nil unless respond_to?(method)
98
+ public_send(method)
99
+ end
100
+
101
+ private
102
+
103
+ def data
104
+ @data ||= begin
105
+ defaults = self.class.configuration[DEFAULT_CFG_KEY]
106
+ cfg = self.class.configuration[version] || {}
107
+ defaults.merge(cfg).freeze
108
+ end
109
+ end
110
+
111
+ def sanitize_path(path)
112
+ path.gsub(%r{^/}, '')
113
+ end
114
+ end
115
+ end
116
+
117
+ require 'rabbitmq_http_auth_backend/config/runtime'
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class Config
5
+ class Runtime
6
+ attr_reader :configuration
7
+
8
+ def initialize(config = nil, key = nil)
9
+ @configuration =
10
+ config || RabbitMQHttpAuthBackend::Config.default_configuration
11
+ @key = key
12
+ end
13
+
14
+ def http_method(method)
15
+ configuration[:http_method] = method.to_s.downcase.to_sym
16
+ end
17
+
18
+ def user(&block)
19
+ self.class.new(configuration, :user).instance_eval(&block)
20
+ end
21
+
22
+ def vhost(&block)
23
+ self.class.new(configuration, :vhost).instance_eval(&block)
24
+ end
25
+
26
+ def resource(&block)
27
+ self.class.new(configuration, :resource).instance_eval(&block)
28
+ end
29
+
30
+ def topic(&block)
31
+ self.class.new(configuration, :topic).instance_eval(&block)
32
+ end
33
+
34
+ def path(path)
35
+ configuration["#{key}_path".to_sym] = path
36
+ end
37
+
38
+ def resolver(resolver = nil, &block)
39
+ configuration["#{key}_resolver".to_sym] = resolver || block
40
+ end
41
+
42
+ protected
43
+
44
+ attr_reader :key
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class Resolver < Service
5
+ class Error < RabbitMQHttpAuthBackend::Error; end
6
+ class NoResolverError < Error; end
7
+ class NonCallableResolverError < Error; end
8
+ class InvalidResponseError < Error; end
9
+
10
+ attr_reader :params
11
+ attr_reader :resolver
12
+
13
+ def initialize(params, resolver)
14
+ @params = params
15
+ @resolver = resolver || raise(NoResolverError)
16
+ end
17
+
18
+ def call
19
+ response = generate_response!
20
+ validate_response!(response)
21
+ response
22
+ end
23
+
24
+ private
25
+
26
+ def generate_response!
27
+ if resolver.is_a?(Proc) && resolver.arity.zero?
28
+ runtime = Runtime.new(params)
29
+ runtime.instance_eval(&resolver)
30
+ build_response(runtime)
31
+ elsif resolver.respond_to?(:call)
32
+ Array(resolver.call(params))
33
+ else
34
+ raise(NonCallableResolverError)
35
+ end
36
+ end
37
+
38
+ def validate_response!(response)
39
+ raise(InvalidResponseError) unless response.is_a?(Array)
40
+ raise(InvalidResponseError) unless %I[allow deny].include?(response.first)
41
+
42
+ true
43
+ end
44
+
45
+ def build_response(runtime)
46
+ symbol = runtime.allowed? ? :allow : :deny
47
+ tags = runtime.tags
48
+ [symbol, tags].compact
49
+ end
50
+ end
51
+ end
52
+
53
+ require 'rabbitmq_http_auth_backend/resolver/runtime'
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
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
11
+ attr_accessor :tags
12
+ attr_accessor :_allowed
13
+
14
+ def initialize(params)
15
+ @params = params
16
+ self.tags = nil
17
+ self._allowed = false
18
+ end
19
+
20
+ def allow!(tags = nil)
21
+ self._allowed = true
22
+ self.tags = tags
23
+ end
24
+
25
+ def deny!
26
+ self._allowed = false
27
+ self.tags = nil
28
+ end
29
+
30
+ def allowed?
31
+ _allowed == true
32
+ end
33
+
34
+ def denied?
35
+ !allowed?
36
+ 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
+ end
82
+ end
83
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ class Service
5
+ def self.call(*args)
6
+ new(*args).call
7
+ end
8
+
9
+ def call
10
+ raise(NotImplementedError)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RabbitMQHttpAuthBackend
4
+ module Version
5
+ MAJOR = 1
6
+ MINOR = 0
7
+ PATCH = 0
8
+
9
+ FULL = [MAJOR, MINOR, PATCH].join('.').freeze
10
+
11
+ def self.to_s
12
+ FULL
13
+ end
14
+ end
15
+
16
+ VERSION = Version.to_s
17
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rabbitmq_http_auth_backend/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rabbitmq_http_auth_backend'
9
+ spec.version = RabbitMQHttpAuthBackend::Version.to_s
10
+ spec.authors = ['Stanko K.R.']
11
+ spec.email = ['me@stanko.io']
12
+
13
+ spec.summary = 'Mountable Rack application that implements a configurable '\
14
+ "API for RabbitMQ's rabbitmq-auth-backend-http"
15
+ spec.description = spec.summary
16
+ spec.homepage = 'https://github.com/monorkin/rabbitmq_http_auth_backend'
17
+ spec.licenses = %w[MIT]
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the
20
+ # 'allowed_push_host' to allow pushing to a single host or delete this
21
+ # section to allow pushing to any host.
22
+ if spec.respond_to?(:metadata)
23
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
+
25
+ spec.metadata['homepage_uri'] = spec.homepage
26
+ spec.metadata['source_code_uri'] = spec.homepage
27
+ spec.metadata['changelog_uri'] = 'https://github.com/'\
28
+ 'monorkin/rabbitmq_http_auth_backend'\
29
+ '/blob/master/CHANGELOG.md'
30
+ else
31
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
32
+ 'public gem pushes.'
33
+ end
34
+
35
+ # Specify which files should be added to the gem when it is released.
36
+ # The `git ls-files -z` loads the files in the RubyGem that have been added
37
+ # into git.
38
+ IGNORED_FILES = [
39
+ '.gitignore', '.rspec', '.travis.yml', 'Makefile', 'Rakefile',
40
+ 'CHANGELOG.md', /^bin\/.*/
41
+ ].map { |p| Regexp.new(p) }
42
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
43
+ `git ls-files -z`.split("\x0").reject do |f|
44
+ f.match(%r{^(test|spec|features)/})
45
+ end
46
+ end.reject { |f| IGNORED_FILES.any? { |r| r.match?(f) } }
47
+
48
+
49
+ spec.bindir = 'exe'
50
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
51
+ spec.require_paths = ['lib']
52
+
53
+ spec.add_dependency 'roda', '~> 3.0'
54
+
55
+ spec.add_development_dependency 'bundler', '~> 2.0'
56
+ spec.add_development_dependency 'pry', '~> 0.12.2'
57
+ spec.add_development_dependency 'rack-test', '~> 1.1.0'
58
+ spec.add_development_dependency 'rake', '~> 10.0'
59
+ spec.add_development_dependency 'rspec', '~> 3.0'
60
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbitmq_http_auth_backend
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Stanko K.R.
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-05-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: roda
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.12.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.12.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: Mountable Rack application that implements a configurable API for RabbitMQ's
98
+ rabbitmq-auth-backend-http
99
+ email:
100
+ - me@stanko.io
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - Gemfile
106
+ - Gemfile.lock
107
+ - LICENSE.txt
108
+ - README.md
109
+ - lib/rabbitmq_http_auth_backend.rb
110
+ - lib/rabbitmq_http_auth_backend/app.rb
111
+ - lib/rabbitmq_http_auth_backend/app/response_formatter.rb
112
+ - lib/rabbitmq_http_auth_backend/config.rb
113
+ - lib/rabbitmq_http_auth_backend/config/runtime.rb
114
+ - lib/rabbitmq_http_auth_backend/resolver.rb
115
+ - lib/rabbitmq_http_auth_backend/resolver/runtime.rb
116
+ - lib/rabbitmq_http_auth_backend/service.rb
117
+ - lib/rabbitmq_http_auth_backend/version.rb
118
+ - rabbitmq_http_auth_backend.gemspec
119
+ homepage: https://github.com/monorkin/rabbitmq_http_auth_backend
120
+ licenses:
121
+ - MIT
122
+ metadata:
123
+ allowed_push_host: https://rubygems.org
124
+ homepage_uri: https://github.com/monorkin/rabbitmq_http_auth_backend
125
+ source_code_uri: https://github.com/monorkin/rabbitmq_http_auth_backend
126
+ changelog_uri: https://github.com/monorkin/rabbitmq_http_auth_backend/blob/master/CHANGELOG.md
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubygems_version: 3.0.1
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Mountable Rack application that implements a configurable API for RabbitMQ's
146
+ rabbitmq-auth-backend-http
147
+ test_files: []