{"id":15792911,"url":"https://github.com/monorkin/rabbitmq_http_auth_backend","last_synced_at":"2025-03-14T14:30:47.920Z","repository":{"id":34847636,"uuid":"184234899","full_name":"monorkin/rabbitmq_http_auth_backend","owner":"monorkin","description":"Mountable Rack application that implements a configurable API for RabbitMQ's rabbitmq-auth-backend-http.","archived":false,"fork":false,"pushed_at":"2024-02-29T11:54:22.000Z","size":58,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-09T05:31:46.782Z","etag":null,"topics":["authentication","authorization","hanami","rabbitmq","rabbitmq-auth-backend","roda","ruby","ruby-on-rails","sinatra"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monorkin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-30T09:40:11.000Z","updated_at":"2023-01-24T17:43:28.000Z","dependencies_parsed_at":"2024-02-29T13:15:41.516Z","dependency_job_id":null,"html_url":"https://github.com/monorkin/rabbitmq_http_auth_backend","commit_stats":{"total_commits":27,"total_committers":2,"mean_commits":13.5,"dds":0.2962962962962963,"last_synced_commit":"1cbad6ee529e222167a793acf30783fb5c5eff7b"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monorkin%2Frabbitmq_http_auth_backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monorkin%2Frabbitmq_http_auth_backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monorkin%2Frabbitmq_http_auth_backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monorkin%2Frabbitmq_http_auth_backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monorkin","download_url":"https://codeload.github.com/monorkin/rabbitmq_http_auth_backend/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243593230,"owners_count":20316153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","authorization","hanami","rabbitmq","rabbitmq-auth-backend","roda","ruby","ruby-on-rails","sinatra"],"created_at":"2024-10-04T23:06:53.086Z","updated_at":"2025-03-14T14:30:47.531Z","avatar_url":"https://github.com/monorkin.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RabbitMQHttpAuthBackend\n\nMountable Rack application that implements a configurable API for RabbitMQ's\n[rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http).\n\n[![Gem Version](https://badge.fury.io/rb/rabbitmq_http_auth_backend.svg)](https://badge.fury.io/rb/rabbitmq_http_auth_backend)\n\n## Purpose\n\nRabbitMQ comes bundled with the [rabbitmq-auth-backend-http](https://github.com/rabbitmq/rabbitmq-auth-backend-http)\nplug-in. The purpose of this plug-in is to authorize each action of an user\nconnected to RabbitMQ by asking a server over HTTP if the user is allowed to\ndo that action.\n\nThe plugin expects the server to implement four endpoints - one for\nlogin (`/user`), one for vhost access, one for general resources (exchanges,\nqueues, topics) and one for topics.\n\nEach endpoint has to respond with a custom format to either allow or deny the\naction.\n\nThis library implements all of this as a mountable Rack application. Meaning,\nafter minimal configuration your application can implement the four required\nendpoints and respond with correctly formated responses.\n\n## Index\n\n1. [Usage](#usage)\n    1. [Mounting the endpoint](#mounting-the-endpoint)\n    2. [Configuration](#configuration)\n    3. [Resolvers](#resolvers)\n    4. [Versioning](#versioning)\n    5. [Default configuration](#default-configuration)\n2. [Installation](#installation)\n3. [FAQ](#faq)\n4. [Change log](#change-log)\n5. [Development](#development)\n6. [Contributing](#contributing)\n7. [License](#license)\n\n## Usage\n\n1. [Mounting the endpoint](#mounting-the-endpoint)\n2. [Configuration](#configuration)\n3. [Resolvers](#resolvers)\n4. [Versioning](#versioning)\n5. [Default configuration](#default-configuration)\n\n### Mounting the endpoint\n\nTo use `RabbitMQHttpAuthBackend`, you will have to mount it within your\nRack application. This will expose it's endpoints from your application,\nname spaced with by any prefix of your choosing.\n\nThe following are examples for some popular Rack based frameworks. Note that\n`/rabbitmq/auth` is only a prefix and can be changed to whatever you desire.\n\nFor **Rails** applications, add the following line to your `routes.rb` file:\n```ruby\n# /config/routes.rb\nRails.application.routes.draw do\n  mount RabbitMQHttpAuthBackend.app =\u003e '/rabbitmq/auth', as: 'rmq_auth_api'\nend\n```\n\nFor **Sinatra** applications, add the following to `config.ru`:\n```ruby\n# config.ru\nmap '/rabbitmq/auth' do\n  run RabbitMQHttpAuthBackend.app\nend\n```\n\nFor **Hanami** applications, add the following to `config/environment.rb`:\n```ruby\nHanami.configure do\n  mount RabbitMQHttpAuthBackend.app, at: '/rabbitmq/auth'\nend\n```\n\nFor **Roda** applications, you have to call `run` from within your routing tree:\n```ruby\nclass MyApp \u003c Roda\n  route do |r|\n    r.on '/rabbitmq/auth' do\n      r.run RabbitMQHttpAuthBackend.app\n    end\n  end\nend\n```\n\n### Configuration\n\n`RabbitMQHttpAuthBackend` can be configured to suite your needs. Both the\nHTTP method as well as the names of all the endpoints are configurable in the\nfollowing manner.\n\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure! do\n  http_method :post\n\n  user do\n    path '/anvandare'\n  end\n\n  vhost do\n    path '/vhost'\n  end\n\n  resource do\n    path '/resurs'\n  end\n\n  topic do\n    path '/amne'\n  end\nend\n```\n\n### Resolvers\n\nResolvers are used to determine whether or not a user is allowed access to a\nparticular resource. Resolvers are passed as part of the configuration. They\ncan be any callable object - any object that responds to a `call` method that\ntakes one argument (the params, a hash containing RabbitMQ query information).\n\nThe return value of the resolver can be either `:allow` or `:deny`. If\nadditional tags need to be returned alongside `:allow` return an `Array`\ncontaining `:allow` and an `Array` of tags - e.g. `[:allow, ['admin']]`.\n\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure! do\n  http_method :post\n\n  user do\n    path '/anvandare'\n    resolver(lambda do |params|\n      if params['username'] == 'admin'\n        return :allow, [:admin, :moderator]\n      end\n\n      :deny\n    end)\n  end\n\n  topic do\n    resolver TopicsResolver\n  end\nend\n\nclass TopicsResolver\n  def self.call(params)\n    if params['username'] == 'admin'\n      return :allow\n    end\n\n    if params['permission'] == 'read' \u0026\u0026 params['name'] == 'messages'\n      return :allow\n    end\n\n    :deny\n  end\nend\n```\n\nMost commonly used methods related to resolvers are extracted to the\n`BasicResolver` class. Any class inheriting from it becomes a callable object\non the class and instance level. The user is expected to implement the `#call`\nmethod.\n\nThe following methods are available within a class inheriting from\n`BasicResolver`:\n\n| Method        | Description                                                  |\n|:--------------|:-------------------------------------------------------------|\n| `username`    | Returns the user's username                                  |\n| `password`    | Returns the user's password                                  |\n| `name`        | Returns the name of the resource                             |\n| `queue?`      | Returns true if the queried resource is a queue              |\n| `exchange?`   | Returns true if the queried resource is an exchange          |\n| `topic?`      | Returns true if the queried resource is a topic              |\n| `resource`    | Returns the resource type (as a String, e.g. `'exchange'`)   |\n| `read?`       | Returns true if the queried permission is read               |\n| `write?`      | Returns true if the queried permission is write              |\n| `configure?`  | Returns true if the queried permission is write              |\n| `permission`  | Returns the requested permission (as a String, e.g. `'read'`)|\n| `routing_key` | Returns the queried routing key                              |\n| `vhost`       | Returns the queried vhost                                    |\n| `ip`          | Returns the IP address of the client querying                |\n\nThe following is the same as the `TopicsResolver` from the previous example, but\nrewritten using `BasicResolver`:\n\n```ruby\nclass TopicsResolver \u003c RabbitMQHttpAuthBackend::BasicResolver\n  def call\n    return :allow if username == 'admin'\n    return :allow if name == 'messages' \u0026\u0026 read?\n    :deny\n  end\nend\n\n# This makes `TopicsResolver` a callable object on the class level\n# \u003e TopicsResolver.call(params)\n# And it's callable on the instance level\n# \u003e TopicsResolver.new(params).call\n```\n\nA \"native\" configuration DSL is also provided. The DSL provides the same utility\nmethods as `BasicResolver` as well as `allow!`, `deny!`, `tags`, `allowed?` and\n`denised?` which can be used to set the result or to query it - note that they\ndon't stop execution!\n\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure! do\n  http_method :post\n\n  topic do\n    resolver do\n      if username == 'admin'\n        allow! ['admin', 'manager']\n      else\n        deny!\n      end\n    end\n  end\nend\n```\n\nNot all methods return usable values for all resources. Here's a list:\n* user\n  - `username`\n  - `password`\n* vhost\n  - `username`\n  - `vhost`\n  - `ip`\n* resource\n  - `username`\n  - `vhost`\n  - `resource` (can return `:exchange`, `:queue` or `:topic`)\n  - `name`\n  - `permission` (can return `:configure`, `:read` or `:write`)\n* topic\n  - `username`\n  - `vhost`\n  - `resource` (can return `:topic`)\n  - `name`\n  - `permission` (can return `:configure`, `:read` or `:write`)\n  - `routing_key` (of the published message if the permission is `:write`, else of the queue binding)\n\n### Versioning\n\nEverybody makes mistakes and changes their minds. Therefore this library\nenables you to create multiple versions of itself and mount them.\n\nThere is little difference to the regular usage.\n\nMounting:\n```ruby\n# /config/routes.rb\nRails.application.routes.draw do\n  mount RabbitMQHttpAuthBackend.app(:v1) =\u003e '/rabbitmq/auth'\n  #                                ^^^^^\nend\n```\n\nConfiguration:\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure!(:v1) do\n  #                               ^^^^^\n  # ...\nend\n```\n\nIf no version is given the `:default` or global configuration is edited.\n\n### Default configuration\n\nThe global default configuration can be changed by altering the configuration\nfor the `:default` version.\n\nHere is the full default configuration\n\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure!(:default) do\n  http_method :get\n\n  user do\n    path '/user'\n    resolver do\n      deny!\n    end\n  end\n\n  vhost do\n    path '/vhost'\n    resolver do\n      deny!\n    end\n  end\n\n  resource do\n    path '/resource'\n    resolver do\n      deny!\n    end\n  end\n\n  topic do\n    path '/topic'\n    resolver do\n      deny!\n    end\n  end\nend\n```\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\n# Gemfile\ngem 'rabbitmq_http_auth_backend'\n```\n\nConfigure the library:\n\n```ruby\n# /config/initializers/rabbitmq_http_auth_backend.rb\nRabbitMQHttpAuthBackend.configure!(:v1) do\n  http_method :get\n\n  user do\n    path '/user'\n    resolver do\n      deny!\n    end\n  end\n\n  vhost do\n    path '/vhost'\n    resolver do\n      deny!\n    end\n  end\n\n  resource do\n    path '/resource'\n    resolver do\n      deny!\n    end\n  end\n\n  topic do\n    path '/topic'\n    resolver do\n      deny!\n    end\n  end\nend\n```\n\nMount the application:\n\n```ruby\n# /config/routes.rb\nRails.application.routes.draw do\n  mount RabbitMQHttpAuthBackend.app =\u003e '/rabbitmq/auth', as: 'rmq_auth_api'\nend\n```\n\nYou are done!\n\n```\nbash-4.4$ curl localhost:3000/rabbitmq/auth/user \u0026\u0026 echo\ndeny\n```\n\n## FAQ\n\n\u003cdetails\u003e\n  \u003csummary\u003eYou use a version in your installation example. Do I have to use a version?\u003c/summary\u003e\n  \u003cp\u003e\n    You don't have to, but I would advise you do.\n    Editing the default configuration might cause you problems in the future\n    when you would like to have a clean slate.\n  \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWhy does the \"native\" DSL exist?\u003c/summary\u003e\n  \u003cp\u003e\n    To provide a simple configuration language to accomplish basic tasks. I\n    would advise you to use `BasicResolver` or a custom resolver callable object\n    for anything other than the most basic use case e.g. check a username or IP.\n  \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCan my path be nested? E.g. `/foo/bar/baz/cux`?\u003c/summary\u003e\n  \u003cp\u003eYes they can.\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCan my path contain arguments? E.g. `/foo/:name/bar`?\u003c/summary\u003e\n  \u003cp\u003eAt the moment, no.\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDoes this library handle caching for me?\u003c/summary\u003e\n  \u003cp\u003e\n    No. This feature was removed from the original implementation of this\n    library.\n  \u003c/p\u003e\n  \u003cp\u003e\n    Caching is a tricky topic. It's hard to get right. I couldn't find an\n    expressive enough interface for handling cache invalidation that would\n    satisfy my needs or be flexible enough to accommodate the use cases I think\n    are common. Therefore I decided against implementing caching within this\n    library.\n  \u003c/p\u003e\n  \u003cp\u003e\n    I recommend that you implement your custom caching and invalidation logic\n    in a custom resolver.\n  \u003c/p\u003e\n  \u003cp\u003e\n    Also, use the \u003ca href=\"https://github.com/rabbitmq/rabbitmq-auth-backend-cache\"\u003erabbitmq-auth-backend-cache\u003c/a\u003e plugin.\n    It provides time based client-side caching and comes standard with RabbitMQ 3.7+\n  \u003c/p\u003e\n  \u003cp\u003e\n    Here is an example of a fully configured HTTP auth backend plugin in\n    conjunction with the caching plugin:\n  \u003c/p\u003e\n  \u003cpre\u003e\n    auth_backends.1 = internal\n    auth_backends.2 = cache\n    auth_cache.cached_backend = http\n    auth_http.http_method = get\n    auth_http.user_path = http://localhost:3000/rabbitmq/auth/user\n    auth_http.vhost_path = http://localhost:3000/rabbitmq/auth/vhost\n    auth_http.resource_path = http://localhost:3000/rabbitmq/auth/resource\n    auth_http.topic_path = http://localhost:3000/rabbitmq/auth/topic\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eHow do you use Rabbit's HTTP backend?\u003c/summary\u003e\n  \u003cp\u003e\n    Follow the installation instructions in this guide to setup your Rack\n    (Rails/Roda/Sinatra/...) application as an HTTP auth backend. Then add\n    the following to your `rabbitmq.conf`, located within `/etc/rabbitmq`\n    (if it's not there, create it).\n  \u003c/p\u003e\n  \u003cpre\u003e\n    auth_backends.1 = internal\n    auth_backends.2 = http\n    auth_http.http_method = get\n    auth_http.user_path = http://localhost:3000/rabbitmq/auth/user\n    auth_http.vhost_path = http://localhost:3000/rabbitmq/auth/vhost\n    auth_http.resource_path = http://localhost:3000/rabbitmq/auth/resource\n    auth_http.topic_path = http://localhost:3000/rabbitmq/auth/topic\n  \u003c/pre\u003e\n  \u003cp\u003e\n    Assuming that your application and RabbitMQ instance are on the same\n    machine, and that your application is exposed on port 3000 everything\n    should just work™️.\n  \u003c/p\u003e\n  \u003cp\u003e\n    If it doesn't work try restarting RabbitMQ and your application.\n  \u003c/p\u003e\n  \u003cp\u003e\n    If your application and RabbitMQ instance aren't on the same machine, make\n    sure that the RabbitMQ instance can access your application, the\n    easiest way to do this is to connect to the RabbitMQ server and using\n    `ping \u003cyour application URL or IP\u003e` or `curl \u003cyour application URL or IP\u003e:\u003cyour application port\u003e`.\n    Remember to change the `localhost:3000` in `rabbitmq.conf` to your\n    application's URL or IP.\n  \u003c/p\u003e\n\u003c/details\u003e\n\n## Change log\n\nAll changes between versions are logged to the change log available in the\n[CHANGELOG.md file](/CHANGELOG.md).\n\nThis project follows the [semantic versioning schema](https://semver.org/).\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies.\nThen, run `rake spec` to run the tests.\nYou can also run `bin/console` for an interactive prompt that will allow you\nto experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`.\nTo release a new version, update the version number in `version.rb`, and then\nrun `bundle exec rake release`, which will create a git tag for the version,\npush git commits and tags, and push the `.gem` file\nto [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\n[https://github.com/monorkin/rabbitmq_http_auth_backend/](https://github.com/monorkin/rabbitmq_http_auth_backend/).\n\n## License\n\nThis software is licensed under the MIT license. A copy of the license\ncan be found in the [LICENSE.txt file](/LICENSE.txt) included with this\nsoftware.\n\n**TL;DR** this software comes with absolutely no warranty of any kind.\nYou are free to redistribute and modify the software as long as the original\ncopyright notice is present in your derivative work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonorkin%2Frabbitmq_http_auth_backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonorkin%2Frabbitmq_http_auth_backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonorkin%2Frabbitmq_http_auth_backend/lists"}