├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── LICENSE-MPL-RabbitMQ ├── Makefile ├── README.md ├── TODO ├── erlang.mk ├── examples ├── README.md ├── docker-compose.yml ├── docker │ ├── enabled_plugins │ ├── nodered │ │ ├── Dockerfile │ │ ├── docker-compose.yml │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── rabbitmq.conf ├── rabbitmq_auth_backend_django │ ├── .gitignore │ ├── Dockerfile │ ├── docker-compose.yml │ ├── manage.py │ ├── rabbitmq_auth_backend_django │ │ ├── __init__.py │ │ ├── auth │ │ │ ├── __init__.py │ │ │ ├── models.py │ │ │ ├── tests.py │ │ │ └── views.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── start.sh ├── rabbitmq_auth_backend_php │ ├── .gitignore │ ├── composer.json │ ├── src │ │ ├── bootstrap.php │ │ ├── resource.php │ │ ├── topic.php │ │ ├── user.php │ │ └── vhost.php │ └── var │ │ └── log.log ├── rabbitmq_auth_backend_spring_boot │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── MavenWrapperDownloader.java │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── rabbitmq │ │ │ └── examples │ │ │ ├── AuthBackendHttpController.java │ │ │ ├── BaseCheck.java │ │ │ ├── RabbitMqAuthBackendHttp.java │ │ │ ├── ResourceCheck.java │ │ │ ├── TopicCheck.java │ │ │ ├── User.java │ │ │ └── VirtualHostCheck.java │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── rabbitmq │ │ │ └── examples │ │ │ └── AuthBackendHttpControllerTest.java │ │ └── resources │ │ └── logback-test.xml ├── rabbitmq_auth_backend_spring_boot_kotlin │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── README.md │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── rabbitmq │ │ │ │ └── examples │ │ │ │ ├── AuthController.kt │ │ │ │ ├── Configuration.kt │ │ │ │ └── RabbitmqAuthBackendApplication.kt │ │ └── resources │ │ │ ├── application.properties │ │ │ └── rabbitmq.conf │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── rabbitmq │ │ └── examples │ │ └── AuthApiTest.kt ├── rabbitmq_auth_backend_webapi_dotnet │ ├── App_Start │ │ └── WebApiConfig.cs │ ├── Controllers │ │ └── AuthController.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── WebApiHttpAuthService.csproj │ ├── WebApiHttpAuthService.csproj.user │ ├── WebApiHttpAuthService.sln │ └── packages.config └── rabbitmq_auth_backend_webapi_dotnetcore │ ├── AuthResult.cs │ ├── Controllers │ └── AuthController.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── RabbitMqAuthBackendHttp.csproj │ ├── RabbitMqAuthBackendHttp.sln │ ├── Requests │ ├── Resource.cs │ ├── ResourceAuthRequest.cs │ ├── TopicAuthRequest.cs │ ├── UserAuthRequest.cs │ └── VhostAuthRequest.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── priv └── schema │ └── rabbitmq_auth_backend_http.schema ├── rabbitmq-components.mk ├── src ├── rabbit_auth_backend_http.erl └── rabbit_auth_backend_http_app.erl └── test ├── auth_SUITE.erl ├── auth_http_mock.erl ├── config_schema_SUITE.erl ├── config_schema_SUITE_data └── rabbitmq_auth_backend_http.snippets └── unit_SUITE.erl /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for using RabbitMQ. 2 | 3 | **STOP NOW AND READ THIS** BEFORE OPENING A NEW ISSUE ON GITHUB 4 | 5 | Unless you are CERTAIN you have found a reproducible problem in RabbitMQ or 6 | have a **specific, actionable** suggestion for our team, you must first ask 7 | your question or discuss your suspected issue on the mailing list: 8 | 9 | https://groups.google.com/forum/#!forum/rabbitmq-users 10 | 11 | Team RabbitMQ does not use GitHub issues for discussions, investigations, root 12 | cause analysis and so on. 13 | 14 | Please take the time to read the CONTRIBUTING.md document for instructions on 15 | how to effectively ask a question or report a suspected issue: 16 | 17 | https://github.com/rabbitmq/rabbitmq-server/blob/master/CONTRIBUTING.md#github-issues 18 | 19 | Following these rules **will save time** for both you and RabbitMQ's maintainers. 20 | 21 | Thank you. 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | 3 | Please describe the big picture of your changes here to communicate to the 4 | RabbitMQ team why we should accept this pull request. If it fixes a bug or 5 | resolves a feature request, be sure to link to that issue. 6 | 7 | A pull request that doesn't explain **why** the change was made has a much 8 | lower chance of being accepted. 9 | 10 | If English isn't your first language, don't worry about it and try to 11 | communicate the problem you are trying to solve to the best of your abilities. 12 | As long as we can understand the intent, it's all good. 13 | 14 | ## Types of Changes 15 | 16 | What types of changes does your code introduce to this project? 17 | _Put an `x` in the boxes that apply_ 18 | 19 | - [ ] Bug fix (non-breaking change which fixes issue #NNNN) 20 | - [ ] New feature (non-breaking change which adds functionality) 21 | - [ ] Breaking change (fix or feature that would cause an observable behavior change in existing systems) 22 | - [ ] Documentation improvements (corrections, new content, etc) 23 | - [ ] Cosmetic change (whitespace, formatting, etc) 24 | 25 | ## Checklist 26 | 27 | _Put an `x` in the boxes that apply. You can also fill these out after creating 28 | the PR. If you're unsure about any of them, don't hesitate to ask on the 29 | mailing list. We're here to help! This is simply a reminder of what we are 30 | going to look for before merging your code._ 31 | 32 | - [ ] I have read the `CONTRIBUTING.md` document 33 | - [ ] I have signed the CA (see https://cla.pivotal.io/sign/rabbitmq) 34 | - [ ] All tests pass locally with my changes 35 | - [ ] I have added tests that prove my fix is effective or that my feature works 36 | - [ ] I have added necessary documentation (if appropriate) 37 | - [ ] Any dependent changes have been merged and published in related repositories 38 | 39 | ## Further Comments 40 | 41 | If this is a relatively large or complex change, kick off the discussion by 42 | explaining why you chose the solution you did and what alternatives you 43 | considered, etc. 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sw? 2 | .*.sw? 3 | *.beam 4 | /.erlang.mk/ 5 | /cover/ 6 | /deps/ 7 | /doc/ 8 | /ebin/ 9 | /escript/ 10 | /escript.lock 11 | /logs/ 12 | /plugins/ 13 | /plugins.lock 14 | /sbin/ 15 | /sbin.lock 16 | 17 | test/config_schema_SUITE_data/schema/ 18 | 19 | /rabbitmq_auth_backend_http.d 20 | 21 | .idea 22 | 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # vim:sw=2:et: 2 | 3 | os: linux 4 | dist: xenial 5 | language: elixir 6 | notifications: 7 | email: 8 | recipients: 9 | - alerts@rabbitmq.com 10 | on_success: never 11 | on_failure: always 12 | addons: 13 | apt: 14 | packages: 15 | - awscli 16 | cache: 17 | apt: true 18 | env: 19 | global: 20 | - secure: IRKRVDsvD0owEKM2GDKvuk5zSQJa+Z0Iu4JQuK78BBLTcmjVmWhHsaE1H9hwzCpWwC2yaMz/2C5GEEaK/ET1XnY48UvuihGWxpMnzbzhYuEx6CRSa9Ka7ik2LCP1lZ+t6OxBXT07PdJ2Ib3hPXcxgRHgOEAHfJ9gmMHgG9vrbiI= 21 | - secure: SffTvt5GWsNq/Nc5epFn5ODIbnn17AkEUsrf3LQc8huKdN92x2v5rSrGgJAPN7WCRW1VPmlgwMF0tj6uY+oSKI+sotWb+dPdCyuXh/z4JhxX+S/ui4ItgbfD6DAui+eLXZxkvzGyv4NJ85aKhj5y8ztSqD7Fgeg0jErZwbNg6y0= 22 | 23 | # $base_rmq_ref is used by rabbitmq-components.mk to select the 24 | # appropriate branch for dependencies. 25 | - base_rmq_ref=master 26 | 27 | elixir: 28 | - '1.9' 29 | otp_release: 30 | - '21.3' 31 | - '22.2' 32 | 33 | install: 34 | # This project being an Erlang one (we just set language to Elixir 35 | # to ensure it is installed), we don't want Travis to run mix(1) 36 | # automatically as it will break. 37 | skip 38 | 39 | script: 40 | # $current_rmq_ref is also used by rabbitmq-components.mk to select 41 | # the appropriate branch for dependencies. 42 | - make check-rabbitmq-components.mk 43 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 44 | - make xref 45 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 46 | - make tests 47 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 48 | 49 | after_failure: 50 | - | 51 | cd "$TRAVIS_BUILD_DIR" 52 | if test -d logs && test "$AWS_ACCESS_KEY_ID" && test "$AWS_SECRET_ACCESS_KEY"; then 53 | archive_name="$(basename "$TRAVIS_REPO_SLUG")-$TRAVIS_JOB_NUMBER" 54 | 55 | tar -c --transform "s/^logs/${archive_name}/" -f - logs | \ 56 | xz > "${archive_name}.tar.xz" 57 | 58 | aws s3 cp "${archive_name}.tar.xz" s3://server-release-pipeline/travis-ci-logs/ \ 59 | --region eu-west-1 \ 60 | --acl public-read 61 | fi 62 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of fostering an open 4 | and welcoming community, we pledge to respect all people who contribute through reporting 5 | issues, posting feature requests, updating documentation, submitting pull requests or 6 | patches, and other activities. 7 | 8 | We are committed to making participation in this project a harassment-free experience for 9 | everyone, regardless of level of experience, gender, gender identity and expression, 10 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, 11 | religion, or nationality. 12 | 13 | Examples of unacceptable behavior by participants include: 14 | 15 | * The use of sexualized language or imagery 16 | * Personal attacks 17 | * Trolling or insulting/derogatory comments 18 | * Public or private harassment 19 | * Publishing other's private information, such as physical or electronic addresses, 20 | without explicit permission 21 | * Other unethical or unprofessional conduct 22 | 23 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 24 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 25 | Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors 26 | that they deem inappropriate, threatening, offensive, or harmful. 27 | 28 | By adopting this Code of Conduct, project maintainers commit themselves to fairly and 29 | consistently applying these principles to every aspect of managing this project. Project 30 | maintainers who do not follow or enforce the Code of Conduct may be permanently removed 31 | from the project team. 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an 34 | individual is representing the project or its community. 35 | 36 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 37 | contacting a project maintainer at [info@rabbitmq.com](mailto:info@rabbitmq.com). All complaints will 38 | be reviewed and investigated and will result in a response that is deemed necessary and 39 | appropriate to the circumstances. Maintainers are obligated to maintain confidentiality 40 | with regard to the reporter of an incident. 41 | 42 | This Code of Conduct is adapted from the 43 | [Contributor Covenant](https://contributor-covenant.org), version 1.3.0, available at 44 | [contributor-covenant.org/version/1/3/0/](https://contributor-covenant.org/version/1/3/0/) 45 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thank you for using RabbitMQ and for taking the time to contribute to the project. 2 | This document has two main parts: 3 | 4 | * when and how to file GitHub issues for RabbitMQ projects 5 | * how to submit pull requests 6 | 7 | They intend to save you and RabbitMQ maintainers some time, so please 8 | take a moment to read through them. 9 | 10 | ## Overview 11 | 12 | ### GitHub issues 13 | 14 | The RabbitMQ team uses GitHub issues for _specific actionable items_ that 15 | engineers can work on. This assumes the following: 16 | 17 | * GitHub issues are not used for questions, investigations, root cause 18 | analysis, discussions of potential issues, etc (as defined by this team) 19 | * Enough information is provided by the reporter for maintainers to work with 20 | 21 | The team receives many questions through various venues every single 22 | day. Frequently, these questions do not include the necessary details 23 | the team needs to begin useful work. GitHub issues can very quickly 24 | turn into a something impossible to navigate and make sense 25 | of. Because of this, questions, investigations, root cause analysis, 26 | and discussions of potential features are all considered to be 27 | [mailing list][rmq-users] material. If you are unsure where to begin, 28 | the [RabbitMQ users mailing list][rmq-users] is the right place. 29 | 30 | Getting all the details necessary to reproduce an issue, make a 31 | conclusion or even form a hypothesis about what's happening can take a 32 | fair amount of time. Please help others help you by providing a way to 33 | reproduce the behavior you're observing, or at least sharing as much 34 | relevant information as possible on the [RabbitMQ users mailing 35 | list][rmq-users]. 36 | 37 | Please provide versions of the software used: 38 | 39 | * RabbitMQ server 40 | * Erlang 41 | * Operating system version (and distribution, if applicable) 42 | * All client libraries used 43 | * RabbitMQ plugins (if applicable) 44 | 45 | The following information greatly helps in investigating and reproducing issues: 46 | 47 | * RabbitMQ server logs 48 | * A code example or terminal transcript that can be used to reproduce 49 | * Full exception stack traces (a single line message is not enough!) 50 | * `rabbitmqctl report` and `rabbitmqctl environment` output 51 | * Other relevant details about the environment and workload, e.g. a traffic capture 52 | * Feel free to edit out hostnames and other potentially sensitive information. 53 | 54 | To make collecting much of this and other environment information, use 55 | the [`rabbitmq-collect-env`][rmq-collect-env] script. It will produce an archive with 56 | server logs, operating system logs, output of certain diagnostics commands and so on. 57 | Please note that **no effort is made to scrub any information that may be sensitive**. 58 | 59 | ### Pull Requests 60 | 61 | RabbitMQ projects use pull requests to discuss, collaborate on and accept code contributions. 62 | Pull requests is the primary place of discussing code changes. 63 | 64 | Here's the recommended workflow: 65 | 66 | * [Fork the repository][github-fork] or repositories you plan on contributing to. If multiple 67 | repositories are involved in addressing the same issue, please use the same branch name 68 | in each repository 69 | * Create a branch with a descriptive name in the relevant repositories 70 | * Make your changes, run tests (usually with `make tests`), commit with a 71 | [descriptive message][git-commit-msgs], push to your fork 72 | * Submit pull requests with an explanation what has been changed and **why** 73 | * Submit a filled out and signed [Contributor Agreement][ca-agreement] if needed (see below) 74 | * Be patient. We will get to your pull request eventually 75 | 76 | If what you are going to work on is a substantial change, please first 77 | ask the core team for their opinion on the [RabbitMQ users mailing list][rmq-users]. 78 | 79 | ## Running Tests 80 | 81 | make tests 82 | 83 | ## Code of Conduct 84 | 85 | See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). 86 | 87 | ## Contributor Agreement 88 | 89 | If you want to contribute a non-trivial change, please submit a signed 90 | copy of our [Contributor Agreement][ca-agreement] around the time you 91 | submit your pull request. This will make it much easier (in some 92 | cases, possible) for the RabbitMQ team at Pivotal to merge your 93 | contribution. 94 | 95 | ## Where to Ask Questions 96 | 97 | If something isn't clear, feel free to ask on our [mailing list][rmq-users]. 98 | 99 | [rmq-collect-env]: https://github.com/rabbitmq/support-tools/blob/master/scripts/rabbitmq-collect-env 100 | [git-commit-msgs]: https://chris.beams.io/posts/git-commit/ 101 | [rmq-users]: https://groups.google.com/forum/#!forum/rabbitmq-users 102 | [ca-agreement]: https://cla.pivotal.io/sign/rabbitmq 103 | [github-fork]: https://help.github.com/articles/fork-a-repo/ 104 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This package is licensed under the MPL 2.0. For the MPL 2.0, please see LICENSE-MPL-RabbitMQ. 2 | 3 | If you have any questions regarding licensing, please contact us at 4 | info@rabbitmq.com. 5 | -------------------------------------------------------------------------------- /LICENSE-MPL-RabbitMQ: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = rabbitmq_auth_backend_http 2 | PROJECT_DESCRIPTION = RabbitMQ HTTP Authentication Backend 3 | PROJECT_MOD = rabbit_auth_backend_http_app 4 | 5 | define PROJECT_ENV 6 | [ 7 | {http_method, get}, 8 | {user_path, "http://localhost:8000/auth/user"}, 9 | {vhost_path, "http://localhost:8000/auth/vhost"}, 10 | {resource_path, "http://localhost:8000/auth/resource"}, 11 | {topic_path, "http://localhost:8000/auth/topic"} 12 | ] 13 | endef 14 | 15 | define PROJECT_APP_EXTRA_KEYS 16 | {broker_version_requirements, []} 17 | endef 18 | 19 | LOCAL_DEPS = inets 20 | DEPS = rabbit_common rabbit amqp_client 21 | TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers cowboy 22 | 23 | DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk 24 | DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk 25 | 26 | # FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be 27 | # reviewed and merged. 28 | 29 | ERLANG_MK_REPO = https://github.com/rabbitmq/erlang.mk.git 30 | ERLANG_MK_COMMIT = rabbitmq-tmp 31 | 32 | include rabbitmq-components.mk 33 | include erlang.mk 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTP-based authorisation and authentication for RabbitMQ 2 | 3 | ## This was migrated to https://github.com/rabbitmq/rabbitmq-server 4 | 5 | This repository has been moved to the main unified RabbitMQ "monorepo", including all open issues. You can find the source under [/deps/rabbitmq_auth_backend_http](https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/rabbitmq_auth_backend_http). 6 | All issues have been transferred. 7 | 8 | ## Overview 9 | 10 | This plugin provides the ability for your RabbitMQ server to perform 11 | authentication (determining who can log in) and authorisation 12 | (determining what permissions they have) by making requests to an HTTP 13 | server. 14 | 15 | This plugin can put a significant amount of load on its backing service. 16 | We recommend using it together with [rabbitmq_auth_backend_cache](http://github.com/rabbitmq/rabbitmq-auth-backend-cache) 17 | with a reasonable caching interval (e.g. 1-3 minutes). 18 | 19 | 20 | ## Project Maturity 21 | 22 | As of 3.7.0, this plugin is distributed with RabbitMQ. 23 | 24 | 25 | ## RabbitMQ Version Requirements 26 | 27 | As of 3.7.0, this plugin is distributed with RabbitMQ. 28 | 29 | As with all [authentication plugins](http://rabbitmq.com/access-control.html), this one requires RabbitMQ server 30 | 2.3.1 or later. 31 | 32 | ## Using with RabbitMQ 3.6.x 33 | 34 | Install the corresponding .ez files from our 35 | [Community Plugins page](http://www.rabbitmq.com/community-plugins.html). Note that different 36 | releases of this plugin support different versions of RabbitMQ. 37 | 38 | ## Enabling the Plugin 39 | 40 | First enable the plugin using `rabbitmq-plugins`: 41 | 42 | rabbitmq-plugins enable rabbitmq_auth_backend_http 43 | 44 | 45 | ## Configuring the Plugin 46 | 47 | To use this backend exclusively, use the following snippet in `rabbitmq.conf` (currently 48 | in master) 49 | 50 | auth_backends.1 = http 51 | 52 | Or, in the classic config format (`rabbitmq.config`, prior to 3.7.0) or `advanced.config`: 53 | 54 | [{rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}]. 55 | 56 | See [RabbitMQ Configuration guide](http://www.rabbitmq.com/configure.html) and 57 | [Access Control guide](http://rabbitmq.com/access-control.html) for more information. 58 | 59 | You need to configure the plugin to know which URIs to point at 60 | and which HTTP method to use. 61 | 62 | Below is a minimal configuration file example. 63 | 64 | In `rabbitmq.conf`: 65 | 66 | auth_backends.1 = http 67 | auth_http.http_method = post 68 | auth_http.user_path = http://some-server/auth/user 69 | auth_http.vhost_path = http://some-server/auth/vhost 70 | auth_http.resource_path = http://some-server/auth/resource 71 | auth_http.topic_path = http://some-server/auth/topic 72 | 73 | In the [classic config format](http://www.rabbitmq.com/configure.html) (`rabbitmq.config` prior to 3.7.0 or `advanced.config`): 74 | 75 | [ 76 | {rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}, 77 | {rabbitmq_auth_backend_http, 78 | [{http_method, post}, 79 | {user_path, "http(s)://some-server/auth/user"}, 80 | {vhost_path, "http(s)://some-server/auth/vhost"}, 81 | {resource_path, "http(s)://some-server/auth/resource"}, 82 | {topic_path, "http(s)://some-server/auth/topic"}]} 83 | ]. 84 | 85 | By default `http_method` configuration is `GET` for backwards compatibility. It's recommended 86 | to use `POST` requests to avoid credentials logging. 87 | 88 | ## What Must My Web Server Do? 89 | 90 | This plugin requires that your web server respond to requests in a 91 | certain predefined format. It will make GET (by default) or POST requests 92 | against the URIs listed in the configuration file. It will add query string 93 | (for `GET` requests) or a URL-encoded request body (for `POST` requests) parameters as follows: 94 | 95 | ### user_path 96 | 97 | * `username` - the name of the user 98 | * `password` - the password provided (may be missing if e.g. rabbitmq-auth-mechanism-ssl is used) 99 | 100 | ### vhost_path 101 | 102 | * `username` - the name of the user 103 | * `vhost` - the name of the virtual host being accessed 104 | * `ip` - the client ip address 105 | 106 | Note that you cannot create arbitrary virtual hosts using this plugin; you can only determine whether your users can see / access the ones that exist. 107 | 108 | ### resource_path 109 | 110 | * `username` - the name of the user 111 | * `vhost` - the name of the virtual host containing the resource 112 | * `resource` - the type of resource (`exchange`, `queue`, `topic`) 113 | * `name` - the name of the resource 114 | * `permission` - the access level to the resource (`configure`, `write`, `read`) - see [the Access Control guide](http://www.rabbitmq.com/access-control.html) for their meaning 115 | 116 | ### topic_path 117 | 118 | * `username` - the name of the user 119 | * `vhost` - the name of the virtual host containing the resource 120 | * `resource` - the type of resource (`topic` in this case) 121 | * `name` - the name of the exchange 122 | * `permission` - the access level to the resource (`write` or `read`) 123 | * `routing_key` - the routing key of a published message (when the permission is `write`) 124 | or routing key of the queue binding (when the permission is `read`) 125 | 126 | See [topic authorisation](http://www.rabbitmq.com/access-control.html#topic-authorisation) for more information 127 | about topic authorisation. 128 | 129 | Your web server should always return HTTP 200 OK, with a body 130 | containing: 131 | 132 | * `deny` - deny access to the user / vhost / resource 133 | * `allow` - allow access to the user / vhost / resource 134 | * `allow [list of tags]` - (for `user_path` only) - allow access, and mark the user as an having the tags listed 135 | 136 | ## Using TLS/HTTPS 137 | 138 | If your Web server uses HTTPS and certificate verification, you need to 139 | configure the plugin to use a CA and client certificate/key pair using the `rabbitmq_auth_backend_http.ssl_options` config variable: 140 | 141 | [ 142 | {rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}, 143 | {rabbitmq_auth_backend_http, 144 | [{http_method, post}, 145 | {user_path, "https://some-server/auth/user"}, 146 | {vhost_path, "https://some-server/auth/vhost"}, 147 | {resource_path, "https://some-server/auth/resource"}, 148 | {topic_path, "https://some-server/auth/topic"}, 149 | {ssl_options, 150 | [{cacertfile, "/path/to/cacert.pem"}, 151 | {certfile, "/path/to/client/cert.pem"}, 152 | {keyfile, "/path/to/client/key.pem"}, 153 | {verify, verify_peer}, 154 | {fail_if_no_peer_cert, true}]}]} 155 | ]. 156 | 157 | It is recommended to use TLS for authentication and enable peer verification. 158 | 159 | 160 | ## Debugging 161 | 162 | Check the RabbitMQ logs if things don't seem to be working 163 | properly. Look for log messages containing "rabbit_auth_backend_http 164 | failed". 165 | 166 | ## Example Apps 167 | 168 | There are [example backend services](./examples) available in Python, PHP, Spring Boot, ASP.NET Web API. 169 | 170 | See [examples README](./examples/README.md) for more information. 171 | 172 | ## Building from Source 173 | 174 | You can build and install it like any other plugin (see 175 | [the plugin development guide](http://www.rabbitmq.com/plugin-development.html)). 176 | 177 | This plugin depends on the Erlang client (just to grab a URI parser). 178 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Start ssl application when SSL URIs are used. 2 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ HTTP Authn/Authz Backend Examples 2 | 3 | ## Overview 4 | 5 | This directory provides a number of community contributed example applications that target 6 | different platforms and frameworks: 7 | 8 | * Python and Django 9 | * Java and Spring Boot 10 | * Kotlin and Spring Boot 11 | * C# and ASP.NET Web API 12 | * C# and ASP.NET Core 2.1 13 | * PHP 14 | 15 | ## Python Example 16 | 17 | `rabbitmq_auth_backend_django` is a very minimalistic [Django](https://www.djangoproject.com/) application 18 | that rabbitmq-auth-backend-http can authenticate against. It's really 19 | not designed to be anything other than an example. 20 | 21 | ### Running the Example 22 | 23 | Run 24 | 25 | ``` shell 26 | start.sh 27 | ``` 28 | 29 | to launch it after [installing Django](https://docs.djangoproject.com/en/2.1/intro/install/). 30 | You may need to hack `start.sh` if you are not running Debian or Ubuntu. 31 | 32 | The app will use a local SQLite database. It uses the standard 33 | Django authentication database. All users get access to all vhosts and 34 | resources. 35 | 36 | The app recognises two users (to make the setup easier): `admin` and `someuser`. 37 | Passwords for those users do not matter. user `admin` as tagged as `administrator`. 38 | 39 | ### HTTP Endpoint Examples 40 | 41 | `urls.py` and `auth/views.py` are the main modules that describe HTTP routes and 42 | views (endpoints). 43 | 44 | 45 | ## Spring Boot Example 46 | 47 | `rabbitmq_auth_backend_spring_boot` is a simple [Spring Boot](https://projects.spring.io/spring-boot/) 48 | application that rabbitmq-auth-backend-http can authenticate against. It's really 49 | not designed to be anything other than an example. 50 | 51 | ### Running the Example 52 | 53 | Import the example as a Maven project in your favorite IDE or run it directly from the command line: 54 | 55 | ``` shell 56 | mvn spring-boot:run 57 | ``` 58 | 59 | The application listens on the 8080 port. 60 | 61 | ### HTTP Endpoint Examples 62 | 63 | Have a look at the `AuthBackendHttpController`. There's only one user: `guest`, 64 | with the `guest` password. This implementation also checks the 65 | routing key starts with an `a` when publishing to a topic exchange 66 | or consuming from a topic. (an example of [topic authorisation](http://next.rabbitmq.com/access-control.html#topic-authorisation)). 67 | 68 | ### rabbitmq.config Example 69 | 70 | Below is a [RabbitMQ config file](http://www.rabbitmq.com/configure.html) example to go with this 71 | example: 72 | 73 | ``` ini 74 | auth_backends.1 = http 75 | 76 | auth_http.http_method = post 77 | auth_http.user_path = http://localhost:8080/auth/user 78 | auth_http.vhost_path = http://localhost:8080/auth/vhost 79 | auth_http.resource_path = http://localhost:8080/auth/resource 80 | auth_http.topic_path = http://localhost:8080/auth/topic 81 | ``` 82 | 83 | ## Spring Boot Kotlin Example 84 | 85 | `rabbitmq_auth_backend_spring_boot_kotlin` is a simple [Spring Boot](https://projects.spring.io/spring-boot/) 86 | application written in Kotlin that rabbitmq-auth-backend-http can authenticate against. It's really 87 | not designed to be anything other than an example. 88 | It contains examples with recommended POST methods and example RabbitMQ configuration. 89 | It can be run the same way as the above example. 90 | 91 | 92 | ## ASP.NET Web API Example 93 | 94 | `rabbitmq_auth_backend_webapi_dotnet` is a very minimalistic ASP.NET Web API application 95 | the plugin can authenticate against. It's really 96 | **not designed to be anything other than an example**. 97 | 98 | ### Running the Example 99 | 100 | Open the WebApiHttpAuthService.csproj in Visual Studio 2017, More details about prerequisites can be found below. 101 | 102 | As with other examples, RabbitMQ [authentication and authorization backends](http://www.rabbitmq.com/access-control.html) must be configured 103 | to use this plugin and the endpoints provided by this example app. 104 | 105 | Then Build the solution and run it from Visual Studio. 106 | `Controllers/AuthController.cs` contains the authentication and authorization logic. 107 | By default All users get access to all vhosts and resources. 108 | User "authuser" will be denied access. 109 | 110 | ### HTTP Endpoint Examples 111 | 112 | Have a look at `AuthController`. 113 | 114 | ### Development Environment 115 | 116 | This example was developed using 117 | 118 | * .NET Framework 4.5 119 | * Visual Studio 2017 120 | * Windows 10 and IIS v10.0 121 | 122 | It is possible to build and run service from Visual Studio browse the endpoint without using IIS. 123 | Port number may vary but will likely be `62190`. 124 | 125 | When the example is hosted on IIS, port 80 will be used by default. 126 | 127 | ## ASP.NET Core 2.1 Example 128 | 129 | `rabbitmq_auth_backend_webapi_dotnetcore` is a modification of the `rabbitmq_auth_backend_webapi_dotnet` example 130 | designed for ASP.NET Core 2.1. It's very similar to the original version but it also adds some static typing 131 | for requests and responses. 132 | 133 | ### Running the Example 134 | 135 | Open the solution file, WebApiHttpAuthService.sln` in Visual Studio 2017 or later. 136 | 137 | As with other examples, RabbitMQ [authentication and authorization backends](http://www.rabbitmq.com/access-control.html) must be configured 138 | to use this plugin and the endpoints provided by this example app. 139 | 140 | Then build the solution and run it from Visual Studio. 141 | `Controllers/AuthController.cs` contains the authentication and authorization logic. 142 | By default All users get access to all vhosts and resources. 143 | User "authuser" will be denied access. 144 | 145 | ### HTTP Endpoint Examples 146 | 147 | Have a look at `AuthController`. 148 | 149 | ### Development Environment 150 | 151 | This example was developed using 152 | 153 | * ASP.NET Core 2.1 154 | * Visual Studio 2017 (Visual Studio Code) 155 | * Windows 10 156 | 157 | It is possible to build and run service from Visual Studio using IIS or from Visual Studio or Visual Studio Code using cross-platform server Kestrel. 158 | 159 | 160 | ## PHP Example 161 | 162 | `rabbitmq_auth_backend_php` is a minimalistic PHP application that this plugin can authenticate against. 163 | It's really not designed to be anything other than an example. 164 | 165 | ### Running the Example 166 | 167 | The example requires PHP >= 5.4 and [Composer](https://getcomposer.org/). 168 | 169 | The `rabbitmq-auth-backend-http-php` library depend on `symfony/security` and `symfony/http-foundation` components. 170 | Go to the `rabbitmq_auth_backend_php` folder and run `composer install`. 171 | 172 | ``` shell 173 | cd rabbitmq_auth_backend_php/ 174 | composer install 175 | ``` 176 | 177 | Now you can run the PHP 5.4 server (server at http://127.0.0.1:8080) 178 | 179 | ``` shell 180 | composer start 181 | ``` 182 | 183 | Ensure the log file is writable `rabbitmq-auth-backend-http/examples/rabbitmq_auth_backend_php/var/log.log`. 184 | 185 | Go to `http://localhost:8080/user.php?username=Anthony&password=anthony-password`, all work properly if you see `Allow administrator` 186 | 187 | 188 | ### HTTP Endpoint Examples 189 | 190 | Have a look at the `bootstrap.php`. By default this example implement the same authorization rules than RabbitMQ. 191 | 192 | Users list: 193 | 194 | | User | password | is admin | Vhost | Configure regex | Write regex | Read regex | tags | 195 | |--|--|--|--|--|--|--|--| 196 | | Anthony | anthony-password | ✔️ | All | All | All | All | administrator | 197 | | James | bond | | / | .* | .* | .* | management | 198 | | Roger | rabbit | | | | | | monitoring | 199 | | bunny | bugs | | | | | | policymaker | 200 | 201 | ### rabbitmq.config Example 202 | 203 | Below is a [RabbitMQ config file](http://www.rabbitmq.com/configure.html) example to go with this 204 | example: 205 | 206 | ``` ini 207 | auth_backends.1 = internal 208 | auth_backends.2 = http 209 | 210 | auth_http.user_path = http://localhost:62190/auth/user.php 211 | auth_http.vhost_path = http://localhost:62190/auth/vhost.php 212 | auth_http.resource_path = http://localhost:62190/auth/resource.php 213 | auth_http.topic_path = http://localhost:62190/auth/topic.php 214 | ``` 215 | 216 | See [RabbitMQ Access Control guide](http://www.rabbitmq.com/access-control.html) for more information. 217 | 218 | ## Running with Docker Compose 219 | 220 | An example node can be started using a provided `docker-compose.yml` file that sets up RabbitMQ. 221 | There's also a file that sets up the Django example above: 222 | 223 | ```bash 224 | docker-compose -f docker-compose.yml -f rabbitmq_auth_backend_django/docker-compose.yml up --build 225 | ``` 226 | 227 | Another file, `docker/nodered/docker-compose.yml`, will run [nodered](https://nodered.org/) on port 1880 228 | with a configured MQTT client that will connect to RabbitMQ and perform basic operations that will trigger 229 | requests to the example service: 230 | 231 | ```bash 232 | docker-compose -f docker-compose.yml -f rabbitmq_auth_backend_django/docker-compose.yml -f docker/nodered/docker-compose.yml up --build 233 | ``` 234 | 235 | Edit the provided [config file](docker/rabbitmq.conf) and enable caching and logging settings. 236 | -------------------------------------------------------------------------------- /examples/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | rabbit: 5 | image: rabbitmq:management 6 | volumes: 7 | - ./docker/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf 8 | - ./docker/enabled_plugins:/etc/rabbitmq/enabled_plugins 9 | ports: 10 | - 15672:15672 11 | - 1883:1883 12 | 13 | -------------------------------------------------------------------------------- /examples/docker/enabled_plugins: -------------------------------------------------------------------------------- 1 | [rabbitmq_management,rabbitmq_auth_backend_cache,rabbitmq_auth_backend_http,rabbitmq_mqtt]. 2 | -------------------------------------------------------------------------------- /examples/docker/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red-docker 2 | 3 | COPY flows.json /data/ 4 | COPY flows_cred.json /data/ 5 | COPY settings.js /data/ 6 | -------------------------------------------------------------------------------- /examples/docker/nodered/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | nodered: 5 | build: ./docker/nodered/ 6 | ports: 7 | - 1880:1880 8 | 9 | -------------------------------------------------------------------------------- /examples/docker/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"782c13cf.81627c","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"ebd3e611.cdef38","type":"mqtt-broker","z":"","name":"as admin","broker":"rabbit","port":"1883","clientid":"adminclienid","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"90e1a809.a7ff5","type":"mqtt-broker","z":"","name":"someuser","broker":"rabbit","port":"1883","clientid":"someuserclientid","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"dac58353.662ad","type":"mqtt in","z":"782c13cf.81627c","name":"","topic":"some/topic/as/admin","qos":"2","broker":"ebd3e611.cdef38","x":160,"y":100,"wires":[["efe47f32.30786"]]},{"id":"f63b9dd3.36cde","type":"comment","z":"782c13cf.81627c","name":"admin","info":"","x":110,"y":60,"wires":[]},{"id":"e948a0d9.babb18","type":"mqtt out","z":"782c13cf.81627c","name":"","topic":"some/topic/as/admin","qos":"","retain":"","broker":"ebd3e611.cdef38","x":360,"y":160,"wires":[]},{"id":"cf18517f.444ef8","type":"inject","z":"782c13cf.81627c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":160,"wires":[["e948a0d9.babb18"]]},{"id":"efe47f32.30786","type":"debug","z":"782c13cf.81627c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":430,"y":100,"wires":[]},{"id":"c7046417.f9b368","type":"mqtt in","z":"782c13cf.81627c","name":"","topic":"some/topic/as/someuser","qos":"2","broker":"90e1a809.a7ff5","x":170,"y":280,"wires":[["be230f6b.e78ec"]]},{"id":"be230f6b.e78ec","type":"debug","z":"782c13cf.81627c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":420,"y":280,"wires":[]},{"id":"f3153151.f2bee8","type":"comment","z":"782c13cf.81627c","name":"someuser","info":"","x":120,"y":240,"wires":[]}] -------------------------------------------------------------------------------- /examples/docker/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"$":"00ae52fd43067c0f54608e6e26ba669f6VIl433Q1ap8mC1z8Gq4TymUQc4xgTTEKUHO5khripHCamXAJXfsezBEsKCPmAhv/1Q8GYVFbDdFH5EcYUs6u5MV4+LJ/jL01toZr6utgIoKYQmjpKoh4fHhScYrezMpKoNglVsV+HSOd91GLBGvyzldmh2JJrAMyZEPdCkDg+fobQ=="} -------------------------------------------------------------------------------- /examples/docker/nodered/settings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright JS Foundation and other contributors, http://js.foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | // The `https` setting requires the `fs` module. Uncomment the following 18 | // to make it available: 19 | //var fs = require("fs"); 20 | 21 | module.exports = { 22 | // the tcp port that the Node-RED web server is listening on 23 | uiPort: process.env.PORT || 1880, 24 | 25 | // By default, the Node-RED UI accepts connections on all IPv4 interfaces. 26 | // To listen on all IPv6 addresses, set uiHost to "::", 27 | // The following property can be used to listen on a specific interface. For 28 | // example, the following would only allow connections from the local machine. 29 | //uiHost: "127.0.0.1", 30 | 31 | // Retry time in milliseconds for MQTT connections 32 | mqttReconnectTime: 15000, 33 | 34 | // Retry time in milliseconds for Serial port connections 35 | serialReconnectTime: 15000, 36 | 37 | // Retry time in milliseconds for TCP socket connections 38 | //socketReconnectTime: 10000, 39 | 40 | // Timeout in milliseconds for TCP server socket connections 41 | // defaults to no timeout 42 | //socketTimeout: 120000, 43 | 44 | // Maximum number of messages to wait in queue while attempting to connect to TCP socket 45 | // defaults to 1000 46 | //tcpMsgQueueSize: 2000, 47 | 48 | // Timeout in milliseconds for HTTP request connections 49 | // defaults to 120 seconds 50 | //httpRequestTimeout: 120000, 51 | 52 | // The maximum length, in characters, of any message sent to the debug sidebar tab 53 | debugMaxLength: 1000, 54 | 55 | // The maximum number of messages nodes will buffer internally as part of their 56 | // operation. This applies across a range of nodes that operate on message sequences. 57 | // defaults to no limit. A value of 0 also means no limit is applied. 58 | //nodeMaxMessageBufferLength: 0, 59 | 60 | // To disable the option for using local files for storing keys and certificates in the TLS configuration 61 | // node, set this to true 62 | //tlsConfigDisableLocalFiles: true, 63 | 64 | // Colourise the console output of the debug node 65 | //debugUseColors: true, 66 | 67 | // The file containing the flows. If not set, it defaults to flows_.json 68 | //flowFile: 'flows.json', 69 | 70 | // To enabled pretty-printing of the flow within the flow file, set the following 71 | // property to true: 72 | //flowFilePretty: true, 73 | 74 | // By default, credentials are encrypted in storage using a generated key. To 75 | // specify your own secret, set the following property. 76 | // If you want to disable encryption of credentials, set this property to false. 77 | // Note: once you set this property, do not change it - doing so will prevent 78 | // node-red from being able to decrypt your existing credentials and they will be 79 | // lost. 80 | credentialSecret: "a-secret-key", 81 | 82 | // By default, all user data is stored in the Node-RED install directory. To 83 | // use a different location, the following property can be used 84 | //userDir: '/home/nol/.node-red/', 85 | 86 | // Node-RED scans the `nodes` directory in the install directory to find nodes. 87 | // The following property can be used to specify an additional directory to scan. 88 | //nodesDir: '/home/nol/.node-red/nodes', 89 | 90 | // By default, the Node-RED UI is available at http://localhost:1880/ 91 | // The following property can be used to specify a different root path. 92 | // If set to false, this is disabled. 93 | //httpAdminRoot: '/admin', 94 | 95 | // Some nodes, such as HTTP In, can be used to listen for incoming http requests. 96 | // By default, these are served relative to '/'. The following property 97 | // can be used to specifiy a different root path. If set to false, this is 98 | // disabled. 99 | //httpNodeRoot: '/red-nodes', 100 | 101 | // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', 102 | // to apply the same root to both parts. 103 | //httpRoot: '/red', 104 | 105 | // When httpAdminRoot is used to move the UI to a different root path, the 106 | // following property can be used to identify a directory of static content 107 | // that should be served at http://localhost:1880/. 108 | //httpStatic: '/home/nol/node-red-static/', 109 | 110 | // The maximum size of HTTP request that will be accepted by the runtime api. 111 | // Default: 5mb 112 | //apiMaxLength: '5mb', 113 | 114 | // If you installed the optional node-red-dashboard you can set it's path 115 | // relative to httpRoot 116 | //ui: { path: "ui" }, 117 | 118 | // Securing Node-RED 119 | // ----------------- 120 | // To password protect the Node-RED editor and admin API, the following 121 | // property can be used. See http://nodered.org/docs/security.html for details. 122 | //adminAuth: { 123 | // type: "credentials", 124 | // users: [{ 125 | // username: "admin", 126 | // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", 127 | // permissions: "*" 128 | // }] 129 | //}, 130 | 131 | // To password protect the node-defined HTTP endpoints (httpNodeRoot), or 132 | // the static content (httpStatic), the following properties can be used. 133 | // The pass field is a bcrypt hash of the password. 134 | // See http://nodered.org/docs/security.html#generating-the-password-hash 135 | //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, 136 | //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, 137 | 138 | // The following property can be used to enable HTTPS 139 | // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener 140 | // for details on its contents. 141 | // See the comment at the top of this file on how to load the `fs` module used by 142 | // this setting. 143 | // 144 | //https: { 145 | // key: fs.readFileSync('privatekey.pem'), 146 | // cert: fs.readFileSync('certificate.pem') 147 | //}, 148 | 149 | // The following property can be used to cause insecure HTTP connections to 150 | // be redirected to HTTPS. 151 | //requireHttps: true, 152 | 153 | // The following property can be used to disable the editor. The admin API 154 | // is not affected by this option. To disable both the editor and the admin 155 | // API, use either the httpRoot or httpAdminRoot properties 156 | //disableEditor: false, 157 | 158 | // The following property can be used to configure cross-origin resource sharing 159 | // in the HTTP nodes. 160 | // See https://github.com/troygoode/node-cors#configuration-options for 161 | // details on its contents. The following is a basic permissive set of options: 162 | //httpNodeCors: { 163 | // origin: "*", 164 | // methods: "GET,PUT,POST,DELETE" 165 | //}, 166 | 167 | // If you need to set an http proxy please set an environment variable 168 | // called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. 169 | // For example - http_proxy=http://myproxy.com:8080 170 | // (Setting it here will have no effect) 171 | // You may also specify no_proxy (or NO_PROXY) to supply a comma separated 172 | // list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk 173 | 174 | // The following property can be used to add a custom middleware function 175 | // in front of all http in nodes. This allows custom authentication to be 176 | // applied to all http in nodes, or any other sort of common request processing. 177 | //httpNodeMiddleware: function(req,res,next) { 178 | // // Handle/reject the request, or pass it on to the http in node by calling next(); 179 | // // Optionally skip our rawBodyParser by setting this to true; 180 | // //req.skipRawBodyParser = true; 181 | // next(); 182 | //}, 183 | 184 | // The following property can be used to verify websocket connection attempts. 185 | // This allows, for example, the HTTP request headers to be checked to ensure 186 | // they include valid authentication information. 187 | //webSocketNodeVerifyClient: function(info) { 188 | // // 'info' has three properties: 189 | // // - origin : the value in the Origin header 190 | // // - req : the HTTP request 191 | // // - secure : true if req.connection.authorized or req.connection.encrypted is set 192 | // // 193 | // // The function should return true if the connection should be accepted, false otherwise. 194 | // // 195 | // // Alternatively, if this function is defined to accept a second argument, callback, 196 | // // it can be used to verify the client asynchronously. 197 | // // The callback takes three arguments: 198 | // // - result : boolean, whether to accept the connection or not 199 | // // - code : if result is false, the HTTP error status to return 200 | // // - reason: if result is false, the HTTP reason string to return 201 | //}, 202 | 203 | // Anything in this hash is globally available to all functions. 204 | // It is accessed as context.global. 205 | // eg: 206 | // functionGlobalContext: { os:require('os') } 207 | // can be accessed in a function block as: 208 | // context.global.os 209 | 210 | functionGlobalContext: { 211 | // os:require('os'), 212 | // jfive:require("johnny-five"), 213 | // j5board:require("johnny-five").Board({repl:false}) 214 | }, 215 | 216 | // Context Storage 217 | // The following property can be used to enable context storage. The configuration 218 | // provided here will enable file-based context that flushes to disk every 30 seconds. 219 | // Refer to the documentation for further options: https://nodered.org/docs/api/context/ 220 | // 221 | //contextStorage: { 222 | // default: { 223 | // module:"localfilesystem" 224 | // }, 225 | //}, 226 | 227 | // The following property can be used to order the categories in the editor 228 | // palette. If a node's category is not in the list, the category will get 229 | // added to the end of the palette. 230 | // If not set, the following default order is used: 231 | //paletteCategories: ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'], 232 | 233 | // Configure the logging output 234 | logging: { 235 | // Only console logging is currently supported 236 | console: { 237 | // Level of logging to be recorded. Options are: 238 | // fatal - only those errors which make the application unusable should be recorded 239 | // error - record errors which are deemed fatal for a particular request + fatal errors 240 | // warn - record problems which are non fatal + errors + fatal errors 241 | // info - record information about the general running of the application + warn + error + fatal errors 242 | // debug - record information which is more verbose than info + info + warn + error + fatal errors 243 | // trace - record very detailed logging + debug + info + warn + error + fatal errors 244 | // off - turn off all logging (doesn't affect metrics or audit) 245 | level: "info", 246 | // Whether or not to include metric events in the log output 247 | metrics: false, 248 | // Whether or not to include audit events in the log output 249 | audit: false 250 | } 251 | }, 252 | 253 | // Customising the editor 254 | editorTheme: { 255 | projects: { 256 | // To enable the Projects feature, set this value to true 257 | enabled: false 258 | } 259 | }, 260 | } 261 | -------------------------------------------------------------------------------- /examples/docker/rabbitmq.conf: -------------------------------------------------------------------------------- 1 | loopback_users.guest = false 2 | listeners.tcp.default = 5672 3 | management.listener.port = 15672 4 | management.listener.ssl = false 5 | 6 | auth_backends.1 = http 7 | 8 | ## This configures rabbitmq_auth_backend_cache that delegates to 9 | ## the HTTP backend. If using this, make sure to comment the 10 | ## auth_backends.1 line above. 11 | ## 12 | # auth_backends.1 = cache 13 | # 14 | # auth_cache.cached_backend = http 15 | # auth_cache.cache_ttl = 5000 16 | 17 | 18 | auth_http.http_method = get 19 | auth_http.user_path = http://auth-backend:8000/auth/user 20 | auth_http.vhost_path = http://auth-backend:8000/auth/vhost 21 | auth_http.resource_path = http://auth-backend:8000/auth/resource 22 | auth_http.topic_path = http://auth-backend:8000/auth/topic 23 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite3 -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-alpine 2 | 3 | ENV PYTHONDONTWRITEBYTECODE 1 4 | ENV PYTHONUNBUFFERED 1 5 | 6 | WORKDIR /usr/src/app 7 | 8 | RUN pip install django 9 | 10 | 11 | COPY . /usr/src/app 12 | 13 | EXPOSE 8000 14 | 15 | ENTRYPOINT ["/usr/src/app/start.sh"] 16 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | auth-backend: 5 | build: ./rabbitmq_auth_backend_django 6 | 7 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rabbitmq_auth_backend_django.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-auth-backend-http/6788d2bba551d08467f41ce7f0e2d27fc83cb753/examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/__init__.py -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/auth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-auth-backend-http/6788d2bba551d08467f41ce7f0e2d27fc83cb753/examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/auth/__init__.py -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/auth/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/auth/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates two different styles of tests (one doctest and one 3 | unittest). These will both pass when you run "manage.py test". 4 | 5 | Replace these with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | class SimpleTest(TestCase): 11 | def test_basic_addition(self): 12 | """ 13 | Tests that 1 + 1 always equals 2. 14 | """ 15 | self.failUnlessEqual(1 + 1, 2) 16 | 17 | __test__ = {"doctest": """ 18 | Another way to test that 1 + 1 is equal to 2. 19 | 20 | >>> 1 + 1 == 2 21 | True 22 | """} 23 | 24 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/auth/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.contrib.auth import authenticate 3 | from django.views.decorators.csrf import csrf_exempt 4 | import logging 5 | 6 | logger = logging.getLogger('auth_backend') 7 | 8 | @csrf_exempt 9 | def user(request): 10 | logger.info(request.GET) 11 | if 'username' in request.GET and 'password' in request.GET: 12 | username = request.GET['username'] 13 | password = request.GET['password'] 14 | if username == 'admin': 15 | return HttpResponse("allow administrator") 16 | 17 | if username == 'someuser': 18 | return HttpResponse("allow") 19 | 20 | user = authenticate(username=username, password=password) 21 | if user: 22 | if user.is_superuser: 23 | return HttpResponse("allow administrator") 24 | else: 25 | return HttpResponse("allow management") 26 | return HttpResponse("deny") 27 | 28 | @csrf_exempt 29 | def vhost(request): 30 | logger.info(request.GET) 31 | return HttpResponse("allow") 32 | 33 | @csrf_exempt 34 | def resource(request): 35 | logger.info(request.GET) 36 | return HttpResponse("allow") 37 | 38 | @csrf_exempt 39 | def topic(request): 40 | logger.info(request.GET) 41 | return HttpResponse("allow") 42 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for rabbitmq_auth_backend_django project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.10.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.10/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '_wqlwxs-s(na_@1-@3=6uc2=-ka3f)))%-v#lgx4een8^#u92c' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = ['0.0.0.0', '127.0.0.1', 'localhost', 'auth-backend'] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | ] 41 | 42 | MIDDLEWARE = [ 43 | 'django.middleware.security.SecurityMiddleware', 44 | 'django.contrib.sessions.middleware.SessionMiddleware', 45 | 'django.middleware.common.CommonMiddleware', 46 | 'django.middleware.csrf.CsrfViewMiddleware', 47 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 48 | 'django.contrib.messages.middleware.MessageMiddleware', 49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 50 | ] 51 | 52 | ROOT_URLCONF = 'rabbitmq_auth_backend_django.urls' 53 | 54 | TEMPLATES = [ 55 | { 56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 57 | 'DIRS': [], 58 | 'APP_DIRS': True, 59 | 'OPTIONS': { 60 | 'context_processors': [ 61 | 'django.template.context_processors.debug', 62 | 'django.template.context_processors.request', 63 | 'django.contrib.auth.context_processors.auth', 64 | 'django.contrib.messages.context_processors.messages', 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = 'rabbitmq_auth_backend_django.wsgi.application' 71 | 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/1.10/ref/settings/#databases 75 | 76 | DATABASES = { 77 | 'default': { 78 | 'ENGINE': 'django.db.backends.sqlite3', 79 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 80 | } 81 | } 82 | 83 | 84 | # Password validation 85 | # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 86 | 87 | AUTH_PASSWORD_VALIDATORS = [ 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 99 | }, 100 | ] 101 | 102 | 103 | # Internationalization 104 | # https://docs.djangoproject.com/en/1.10/topics/i18n/ 105 | 106 | LANGUAGE_CODE = 'en-us' 107 | 108 | TIME_ZONE = 'UTC' 109 | 110 | USE_I18N = True 111 | 112 | USE_L10N = True 113 | 114 | USE_TZ = True 115 | 116 | 117 | # Static files (CSS, JavaScript, Images) 118 | # https://docs.djangoproject.com/en/1.10/howto/static-files/ 119 | 120 | STATIC_URL = '/static/' 121 | 122 | LOGGING = { 123 | 'version': 1, 124 | 'formatters': { 125 | 'verbose': { 126 | 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 127 | }, 128 | 'simple': { 129 | 'format': '%(levelname)s %(message)s' 130 | }, 131 | }, 132 | 'handlers': { 133 | 'console': { 134 | 'level': 'DEBUG', 135 | 'class': 'logging.StreamHandler', 136 | 'formatter': 'simple' 137 | }, 138 | }, 139 | 'loggers': { 140 | 'django': { 141 | 'handlers': ['console'], 142 | 'propagate': True, 143 | }, 144 | 'auth_backend': { 145 | 'handlers': ['console'], 146 | 'level': 'DEBUG', 147 | 'propagate': True, 148 | }, 149 | } 150 | } 151 | # 152 | # if DEBUG: 153 | # # make all loggers use the console. 154 | # for logger in LOGGING['loggers']: 155 | # LOGGING['loggers'][logger]['handlers'] = ['console'] 156 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/urls.py: -------------------------------------------------------------------------------- 1 | """rabbitmq_auth_backend_django URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.10/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import url 17 | from django.contrib import admin 18 | import rabbitmq_auth_backend_django.auth.views as views 19 | 20 | urlpatterns = [ 21 | url(r'^auth/user', views.user), 22 | url(r'^auth/vhost', views.vhost), 23 | url(r'^auth/resource', views.resource), 24 | url(r'^auth/topic', views.topic), 25 | url(r'^admin/', admin.site.urls), 26 | ] 27 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/rabbitmq_auth_backend_django/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for rabbitmq_auth_backend_django project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rabbitmq_auth_backend_django.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_django/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | python manage.py migrate 3 | python manage.py runserver 0.0.0.0:8000 4 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | var 3 | composer.lock 4 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Example RabbitMQ http auth backend php", 3 | "type": "library", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Anthony", 8 | "email": "instabledesign@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=5.4", 13 | "symftony/rabbitmq-auth-backend-http-php": "dev-master", 14 | "monolog/monolog": "^1.23" 15 | }, 16 | "scripts": { 17 | "start": "php -S 127.0.0.1:8080 -t src" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/src/bootstrap.php: -------------------------------------------------------------------------------- 1 | array( 26 | 'password' => 'anthony-password', 27 | 'roles' => array( 28 | 'administrator', 29 | // 'impersonator', // report to https://www.rabbitmq.com/validated-user-id.html 30 | ), 31 | ), 32 | 'James' => array( 33 | 'password' => 'bond', 34 | 'roles' => array( 35 | 'management', 36 | ), 37 | ), 38 | 'Roger' => array( 39 | 'password' => 'rabbit', 40 | 'roles' => array( 41 | 'monitoring', 42 | ), 43 | ), 44 | 'Bunny' => array( 45 | 'password' => 'bugs', 46 | 'roles' => array( 47 | 'policymaker', 48 | ), 49 | ), 50 | )); 51 | 52 | /** 53 | * You can edit the user permissions here 54 | * 55 | * $permissions = arrray( 56 | * '{USERNAME}' => array( 57 | * '{VHOST}' => array( 58 | * 'ip' => '{REGEX_IP}', 59 | * 'read' => '{REGEX_READ}', 60 | * 'write' => '{REGEX_WRITE}', 61 | * 'configure' => '{REGEX_CONFIGURE}', 62 | * ), 63 | * ), 64 | * ); 65 | */ 66 | $permissions = array( 67 | 'Anthony' => array( 68 | 'isAdmin' => true, 69 | ), 70 | 'James' => array( 71 | '/' => array( 72 | 'ip' => '.*', 73 | 'read' => '.*', 74 | 'write' => '.*', 75 | 'configure' => '.*', 76 | ), 77 | ), 78 | ); 79 | 80 | /** 81 | * Authenticator initialisation 82 | * 83 | * His gonna to find the user (with user provider) and to check the authentication with the authentication checker. 84 | * 85 | * We are 2 types of access token: 86 | * - UserPasswordToken use with the user endpoint (to check the username and the password validity) 87 | * - UserToken use with resource/topic/vhost endpoint (to check the username existence) 88 | */ 89 | $authenticator = new Authenticator( 90 | $userProvider, 91 | new ChainAuthenticationChecker(array( 92 | new UserPasswordTokenChecker(), 93 | new UserTokenChecker(), 94 | )) 95 | ); 96 | 97 | /** 98 | * DefaultVoter is used to check the authorization. 99 | * 100 | * This class has the same implementation of default RabbitMQ authorization process. 101 | * 102 | * $permission is the configured user permission 103 | */ 104 | $defaultVoter = new DefaultVoter($permissions); 105 | 106 | /** 107 | * This class is the initialisation of the symfony/security component 108 | */ 109 | $authenticationManager = new AuthenticationProviderManager(array($authenticator)); 110 | $accessDecisionManager = new AccessDecisionManager(array($defaultVoter)); 111 | 112 | $tokenStorage = new TokenStorage(); 113 | 114 | $authorizationChecker = new AuthorizationChecker( 115 | $tokenStorage, 116 | $authenticationManager, 117 | $accessDecisionManager 118 | ); 119 | 120 | /** 121 | * The security class is the main class 122 | */ 123 | $security = new Security($authenticationManager, $authorizationChecker); 124 | 125 | /** 126 | * This is the auth controller. 127 | * 128 | * It take the http request and return the http response 129 | */ 130 | $authController = new AuthController($tokenStorage, $security); 131 | 132 | /** Add a logger */ 133 | $stream = new StreamHandler(__DIR__.'/../var/log.log', Logger::DEBUG); 134 | $authenticator->setLogger((new Logger('rabbitmq_authenticator'))->pushHandler($stream)); 135 | $defaultVoter->setLogger((new Logger('rabbitmq_default_voter'))->pushHandler($stream)); 136 | $security->setLogger((new Logger('rabbitmq_security'))->pushHandler($stream)); 137 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/src/resource.php: -------------------------------------------------------------------------------- 1 | resourceAction( 11 | \Symfony\Component\HttpFoundation\Request::createFromGlobals() // Create an request object 12 | ); 13 | 14 | $response->send(); // send the http response 15 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/src/topic.php: -------------------------------------------------------------------------------- 1 | topicAction( 11 | \Symfony\Component\HttpFoundation\Request::createFromGlobals() // Create an request object 12 | ); 13 | 14 | $response->send(); // send the http response 15 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/src/user.php: -------------------------------------------------------------------------------- 1 | userAction( 11 | \Symfony\Component\HttpFoundation\Request::createFromGlobals() // Create an request object 12 | ); 13 | 14 | $response->send(); // send the http response 15 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/src/vhost.php: -------------------------------------------------------------------------------- 1 | vhostAction( 11 | \Symfony\Component\HttpFoundation\Request::createFromGlobals() // Create an request object 12 | ); 13 | 14 | $response->send(); // send the http response 15 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_php/var/log.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-auth-backend-http/6788d2bba551d08467f41ce7f0e2d27fc83cb753/examples/rabbitmq_auth_backend_php/var/log.log -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | target 3 | *.iml 4 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.5"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-auth-backend-http/6788d2bba551d08467f41ce7f0e2d27fc83cb753/examples/rabbitmq_auth_backend_spring_boot/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar 3 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.1.5.RELEASE 11 | 12 | 13 | 14 | 1.8 15 | 1.8 16 | 17 | 18 | com.rabbitmq.examples 19 | rabbitmq-auth-backend-spring-boot 20 | 1.0-SNAPSHOT 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-test 31 | test 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-maven-plugin 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/AuthBackendHttpController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.util.MultiValueMap; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestMethod; 16 | import org.springframework.web.bind.annotation.RequestParam; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import static java.util.Arrays.asList; 23 | import static org.springframework.util.StringUtils.collectionToDelimitedString; 24 | 25 | /** 26 | * 27 | */ 28 | @RestController 29 | @RequestMapping(path = "/auth", method = { RequestMethod.GET, RequestMethod.POST }) 30 | public class AuthBackendHttpController { 31 | 32 | private static final Logger LOGGER = LoggerFactory.getLogger(AuthBackendHttpController.class); 33 | 34 | private final Map users = new HashMap() {{ 35 | put("guest", new User("guest", "guest", asList("administrator", "management"))); 36 | put("springy", new User("springy", "springy", asList("administrator", "management"))); 37 | }}; 38 | 39 | @RequestMapping("user") 40 | public String user(@RequestParam("username") String username, 41 | @RequestParam("password") String password) { 42 | LOGGER.info("Trying to authenticate user {}", username); 43 | User user = users.get(username); 44 | if (user != null && user.getPassword().equals(password)) { 45 | return "allow " + collectionToDelimitedString(user.getTags(), " "); 46 | } else { 47 | return "deny"; 48 | } 49 | } 50 | 51 | @RequestMapping("vhost") 52 | public String vhost(VirtualHostCheck check) { 53 | LOGGER.info("Checking vhost access with {}", check); 54 | return "allow"; 55 | } 56 | 57 | @RequestMapping("resource") 58 | public String resource(ResourceCheck check) { 59 | LOGGER.info("Checking resource access with {}", check); 60 | return "allow"; 61 | } 62 | 63 | @RequestMapping("topic") 64 | public String topic(TopicCheck check) { 65 | LOGGER.info("Checking topic access with {}", check); 66 | return check.getRouting_key().startsWith("a") ? "allow" : "deny"; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/BaseCheck.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | public class BaseCheck { 12 | 13 | private String username; 14 | 15 | private String vhost; 16 | 17 | public String getUsername() { 18 | return username; 19 | } 20 | 21 | public void setUsername(String username) { 22 | this.username = username; 23 | } 24 | 25 | public String getVhost() { 26 | return vhost; 27 | } 28 | 29 | public void setVhost(String vhost) { 30 | this.vhost = vhost; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return getClass().getSimpleName() + "{" + 36 | "username='" + username + '\'' + 37 | ", vhost='" + vhost + '\'' + 38 | '}'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/RabbitMqAuthBackendHttp.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.boot.SpringApplication; 13 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 14 | import org.springframework.boot.autoconfigure.SpringBootApplication; 15 | import org.springframework.context.annotation.Configuration; 16 | import org.springframework.context.annotation.Profile; 17 | import org.springframework.ui.ModelMap; 18 | import org.springframework.util.StringUtils; 19 | import org.springframework.web.context.request.WebRequest; 20 | import org.springframework.web.context.request.WebRequestInterceptor; 21 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 22 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 23 | 24 | import java.util.stream.Collectors; 25 | 26 | @EnableAutoConfiguration 27 | @SpringBootApplication 28 | public class RabbitMqAuthBackendHttp { 29 | 30 | public static void main(String[] args) { 31 | SpringApplication.run(RabbitMqAuthBackendHttp.class, args); 32 | } 33 | 34 | // to enable: ./mvnw spring-boot:run -Dspring-boot.run.profiles=debug 35 | @Profile("debug") 36 | @Configuration 37 | static class DebugConfiguration implements WebMvcConfigurer { 38 | 39 | @Override 40 | public void addInterceptors(InterceptorRegistry registry) { 41 | 42 | registry.addWebRequestInterceptor(new WebRequestInterceptor() { 43 | @Override 44 | public void preHandle(WebRequest request) { 45 | LoggerFactory.getLogger(DebugConfiguration.class).info( 46 | "HTTP request parameters: {}", 47 | request.getParameterMap() 48 | .entrySet().stream() 49 | .map(entry -> entry.getKey() + " = " + StringUtils.arrayToCommaDelimitedString(entry.getValue())) 50 | .collect(Collectors.toList()) 51 | ); 52 | } 53 | 54 | @Override 55 | public void postHandle(WebRequest request, ModelMap model) { 56 | 57 | } 58 | 59 | @Override 60 | public void afterCompletion(WebRequest request, Exception ex) { 61 | 62 | } 63 | }); 64 | } 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/ResourceCheck.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | public class ResourceCheck extends BaseCheck { 12 | 13 | private String resource, name, permission; 14 | 15 | public String getResource() { 16 | return resource; 17 | } 18 | 19 | public void setResource(String resource) { 20 | this.resource = resource; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getPermission() { 32 | return permission; 33 | } 34 | 35 | public void setPermission(String permission) { 36 | this.permission = permission; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ResourceCheck{" + 42 | "resource='" + resource + '\'' + 43 | ", name='" + name + '\'' + 44 | ", permission='" + permission + '\'' + 45 | "} " + super.toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/TopicCheck.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | public class TopicCheck extends ResourceCheck { 12 | 13 | private String routing_key; 14 | 15 | public String getRouting_key() { 16 | return routing_key; 17 | } 18 | 19 | public void setRouting_key(String routing_key) { 20 | this.routing_key = routing_key; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "TopicCheck{" + 26 | "routing_key='" + routing_key + '\'' + 27 | "} " + super.toString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collection; 13 | import java.util.Collections; 14 | 15 | /** 16 | * 17 | */ 18 | public class User { 19 | 20 | private final String username, password; 21 | 22 | private final Collection tags; 23 | 24 | public User(String username, String password) { 25 | this(username, password, Collections.emptyList()); 26 | } 27 | 28 | public User(String username, String password, Collection tags) { 29 | this.username = username; 30 | this.password = password; 31 | this.tags = tags; 32 | } 33 | 34 | public String getUsername() { 35 | return username; 36 | } 37 | 38 | public String getPassword() { 39 | return password; 40 | } 41 | 42 | public Collection getTags() { 43 | return new ArrayList(tags); 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) 49 | return true; 50 | if (o == null || getClass() != o.getClass()) 51 | return false; 52 | 53 | User user = (User) o; 54 | 55 | return username.equals(user.username); 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return username.hashCode(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/main/java/com/rabbitmq/examples/VirtualHostCheck.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | public class VirtualHostCheck extends BaseCheck { 12 | 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/test/java/com/rabbitmq/examples/AuthBackendHttpControllerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | 9 | package com.rabbitmq.examples; 10 | 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | import org.springframework.test.web.servlet.MockMvc; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 21 | 22 | @RunWith(SpringRunner.class) 23 | @WebMvcTest(AuthBackendHttpController.class) 24 | public class AuthBackendHttpControllerTest { 25 | 26 | @Autowired 27 | private MockMvc mvc; 28 | 29 | @Test public void authenticationAuthorisation() throws Exception { 30 | this.mvc.perform(get("/auth/user").param("username", "guest").param("password", "guest")) 31 | .andExpect(status().isOk()).andExpect(content().string("allow administrator management")); 32 | 33 | this.mvc.perform(get("/auth/user").param("username", "guest").param("password", "wrong")) 34 | .andExpect(status().isOk()).andExpect(content().string("deny")); 35 | 36 | this.mvc.perform(get("/auth/vhost").param("username", "guest").param("vhost", "/")) 37 | .andExpect(status().isOk()).andExpect(content().string("allow")); 38 | 39 | this.mvc.perform(get("/auth/resource") 40 | .param("username", "guest") 41 | .param("vhost", "/") 42 | .param("resource", "exchange") 43 | .param("name", "amq.topic") 44 | .param("permission", "write")) 45 | .andExpect(status().isOk()).andExpect(content().string("allow")); 46 | 47 | this.mvc.perform(get("/auth/topic") 48 | .param("username", "guest") 49 | .param("vhost", "/") 50 | .param("resource", "exchange") 51 | .param("name", "amq.topic") 52 | .param("permission", "write") 53 | .param("routing_key","a.b")) 54 | .andExpect(status().isOk()).andExpect(content().string("allow")); 55 | 56 | this.mvc.perform(get("/auth/topic") 57 | .param("username", "guest") 58 | .param("vhost", "/") 59 | .param("resource", "exchange") 60 | .param("name", "amq.topic") 61 | .param("permission", "write") 62 | .param("routing_key","b.b")) 63 | .andExpect(status().isOk()).andExpect(content().string("deny")); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-auth-backend-http/6788d2bba551d08467f41ce7f0e2d27fc83cb753/examples/rabbitmq_auth_backend_spring_boot_kotlin/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Kotlin Backend 2 | 3 | Run the backend with: 4 | 5 | ./mvnw spring-boot:run 6 | 7 | Don't forget to configure the broker to use the backend! 8 | 9 | Use [`http`](https://httpie.org/doc) to test your program: 10 | 11 | $ http -f POST http://localhost:8080/auth/user username=foo password=bar -v 12 | POST /auth/user HTTP/1.1 13 | Accept: */* 14 | Accept-Encoding: gzip, deflate 15 | Connection: keep-alive 16 | Content-Length: 25 17 | Content-Type: application/x-www-form-urlencoded; charset=utf-8 18 | Host: localhost:8080 19 | User-Agent: HTTPie/0.9.2 20 | 21 | username=foo&password=bar 22 | 23 | HTTP/1.1 200 24 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 25 | Content-Length: 5 26 | Content-Type: text/plain;charset=UTF-8 27 | Date: Thu, 01 Nov 2018 21:16:06 GMT 28 | Expires: 0 29 | Pragma: no-cache 30 | X-Content-Type-Options: nosniff 31 | X-Frame-Options: DENY 32 | X-XSS-Protection: 1; mode=block 33 | 34 | allow 35 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | ########################################################################################## 204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 205 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 206 | ########################################################################################## 207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 208 | if [ "$MVNW_VERBOSE" = true ]; then 209 | echo "Found .mvn/wrapper/maven-wrapper.jar" 210 | fi 211 | else 212 | if [ "$MVNW_VERBOSE" = true ]; then 213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 214 | fi 215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 216 | while IFS="=" read key value; do 217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 218 | esac 219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 220 | if [ "$MVNW_VERBOSE" = true ]; then 221 | echo "Downloading from: $jarUrl" 222 | fi 223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 224 | 225 | if command -v wget > /dev/null; then 226 | if [ "$MVNW_VERBOSE" = true ]; then 227 | echo "Found wget ... using wget" 228 | fi 229 | wget "$jarUrl" -O "$wrapperJarPath" 230 | elif command -v curl > /dev/null; then 231 | if [ "$MVNW_VERBOSE" = true ]; then 232 | echo "Found curl ... using curl" 233 | fi 234 | curl -o "$wrapperJarPath" "$jarUrl" 235 | else 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Falling back to using Java to download" 238 | fi 239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 240 | if [ -e "$javaClass" ]; then 241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 242 | if [ "$MVNW_VERBOSE" = true ]; then 243 | echo " - Compiling MavenWrapperDownloader.java ..." 244 | fi 245 | # Compiling the Java class 246 | ("$JAVA_HOME/bin/javac" "$javaClass") 247 | fi 248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 249 | # Running the downloader 250 | if [ "$MVNW_VERBOSE" = true ]; then 251 | echo " - Running MavenWrapperDownloader.java ..." 252 | fi 253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 254 | fi 255 | fi 256 | fi 257 | fi 258 | ########################################################################################## 259 | # End of extension 260 | ########################################################################################## 261 | 262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 263 | if [ "$MVNW_VERBOSE" = true ]; then 264 | echo $MAVEN_PROJECTBASEDIR 265 | fi 266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 267 | 268 | # For Cygwin, switch paths to Windows format before running java 269 | if $cygwin; then 270 | [ -n "$M2_HOME" ] && 271 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 272 | [ -n "$JAVA_HOME" ] && 273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 274 | [ -n "$CLASSPATH" ] && 275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 276 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 278 | fi 279 | 280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 281 | 282 | exec "$JAVACMD" \ 283 | $MAVEN_OPTS \ 284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 287 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( 125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | echo Found %WRAPPER_JAR% 132 | ) else ( 133 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 134 | echo Downloading from: %DOWNLOAD_URL% 135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" 136 | echo Finished downloading %WRAPPER_JAR% 137 | ) 138 | @REM End of extension 139 | 140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 141 | if ERRORLEVEL 1 goto error 142 | goto end 143 | 144 | :error 145 | set ERROR_CODE=1 146 | 147 | :end 148 | @endlocal & set ERROR_CODE=%ERROR_CODE% 149 | 150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 154 | :skipRcPost 155 | 156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 158 | 159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 160 | 161 | exit /B %ERROR_CODE% 162 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.rabbitmq.examples 7 | rabbitmq-auth-backend-spring-boot-kotlin 8 | 1.0-SNAPSHOT 9 | jar 10 | 11 | rabbitmq-auth-backend-spring-boot-kotlin 12 | Demo project for https://github.com/rabbitmq/rabbitmq-auth-backend-http 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.0.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 1.3.0 26 | 5.3.1 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-security 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-web 37 | 38 | 39 | com.fasterxml.jackson.module 40 | jackson-module-kotlin 41 | 42 | 43 | org.jetbrains.kotlin 44 | kotlin-stdlib-jdk8 45 | 46 | 47 | org.jetbrains.kotlin 48 | kotlin-reflect 49 | 50 | 51 | 52 | org.springframework.security 53 | spring-security-test 54 | test 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-test 59 | test 60 | 61 | 62 | junit 63 | junit 64 | 65 | 66 | org.skyscreamer 67 | jsonassert 68 | 69 | 70 | 71 | 72 | org.junit.jupiter 73 | junit-jupiter-api 74 | 75 | 76 | org.junit.jupiter 77 | junit-jupiter-engine 78 | 79 | 80 | org.jetbrains.kotlin 81 | kotlin-test 82 | ${kotlin.version} 83 | test 84 | 85 | 86 | 87 | 88 | ${project.basedir}/src/main/kotlin 89 | ${project.basedir}/src/test/kotlin 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-maven-plugin 94 | 95 | 96 | kotlin-maven-plugin 97 | org.jetbrains.kotlin 98 | 99 | 100 | -Xjsr305=strict 101 | 102 | 103 | spring 104 | 105 | 106 | 107 | 108 | org.jetbrains.kotlin 109 | kotlin-maven-allopen 110 | ${kotlin.version} 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/main/kotlin/com/rabbitmq/examples/AuthController.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | package com.rabbitmq.examples; 9 | 10 | import org.slf4j.LoggerFactory 11 | import org.springframework.web.bind.annotation.RequestMapping 12 | import org.springframework.web.bind.annotation.RequestMethod 13 | import org.springframework.web.bind.annotation.RestController 14 | 15 | /** 16 | * Controller for the RabbitMQ authentication/authorisation as described 17 | * in https://github.com/rabbitmq/rabbitmq-auth-backend-http 18 | */ 19 | @RequestMapping(path = ["/auth"], method = [RequestMethod.GET, RequestMethod.POST]) 20 | @RestController 21 | class AuthController { 22 | 23 | private val ALLOW = "allow" 24 | private val DENY = "deny" 25 | 26 | private val logger = LoggerFactory.getLogger(AuthController::class.java!!) 27 | 28 | /** 29 | * user_path 30 | */ 31 | @RequestMapping(value = ["/user"], produces = ["text/plain"]) 32 | fun checkUserCredentials(passwordCheck: PasswordCheck): String { 33 | logger.info("checkUserCredentials username: ${passwordCheck.username}") 34 | if (passwordCheck.username == "guest" && passwordCheck.password == "guest") { 35 | return "$ALLOW administrator management" 36 | } else { 37 | return DENY 38 | } 39 | } 40 | 41 | /** 42 | * vhost_path 43 | */ 44 | @RequestMapping(value = ["/vhost"], produces = ["text/plain"]) 45 | fun checkVhost(question: VirtualHostCheck): String { 46 | logger.info("checkVhost: $question") 47 | return ALLOW 48 | } 49 | 50 | /** 51 | * resource_path 52 | */ 53 | @RequestMapping(value = ["/resource"], produces = ["text/plain"]) 54 | fun checkResource(question: ResourceCheck): String { 55 | logger.info("checkResource: $question") 56 | return ALLOW 57 | } 58 | 59 | /** 60 | * topic_path 61 | */ 62 | @RequestMapping(value = ["/topic"], produces = ["text/plain"]) 63 | fun checkTopic(question: TopicCheck): String { 64 | logger.info("checkTopic: $question") 65 | return if (question.routing_key.startsWith("a", false)) ALLOW else DENY 66 | } 67 | 68 | } 69 | 70 | data class PasswordCheck(val username: String, val password: String) 71 | data class VirtualHostCheck(val username: String, val vhost: String) 72 | data class ResourceCheck(val username: String, val vhost: String, val resource: String, val name: String, val permission: String) 73 | data class TopicCheck(val username: String, val vhost: String, val resource: String, val name: String, val permission: String, val routing_key: String) 74 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/main/kotlin/com/rabbitmq/examples/Configuration.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | package com.rabbitmq.examples 9 | 10 | import org.springframework.context.annotation.Configuration 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 13 | 14 | 15 | @Configuration 16 | class SecurityConfiguration : WebSecurityConfigurerAdapter() { 17 | override fun configure(http: HttpSecurity) { 18 | http.csrf().ignoringAntMatchers("/auth/**") 19 | } 20 | } -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/main/kotlin/com/rabbitmq/examples/RabbitmqAuthBackendApplication.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | package com.rabbitmq.examples 9 | 10 | import org.springframework.boot.autoconfigure.SpringBootApplication 11 | import org.springframework.boot.runApplication 12 | 13 | @SpringBootApplication 14 | class RabbitmqAuthBackendSpringBootKotlinApplication 15 | 16 | fun main(args: Array) { 17 | runApplication(*args) 18 | } 19 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=INFO 2 | logging.level.com.rabbitmq.examples=INFO -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/main/resources/rabbitmq.conf: -------------------------------------------------------------------------------- 1 | # Additional configuration for /etc/rabbitmq/rabbitmq.conf 2 | # do not forget to initialize the plugin in the docker 3 | # RUN rabbitmq-plugins enable --offline rabbitmq_auth_backend_http 4 | 5 | # http backend 6 | auth_backends.1 = rabbit_auth_backend_http 7 | auth_http.user_path = http:////auth/user 8 | auth_http.vhost_path = http:////auth/vhost 9 | auth_http.resource_path = http:////auth/resource 10 | auth_http.topic_path = http:////auth/topic 11 | auth_http.http_method = post -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_spring_boot_kotlin/src/test/kotlin/com/rabbitmq/examples/AuthApiTest.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. 7 | */ 8 | package com.rabbitmq.examples 9 | 10 | import org.junit.jupiter.api.Test 11 | import org.junit.jupiter.api.extension.ExtendWith 12 | import org.springframework.beans.factory.annotation.Autowired 13 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest 14 | import org.springframework.http.MediaType 15 | import org.springframework.test.context.junit.jupiter.SpringExtension 16 | import org.springframework.test.web.servlet.MockMvc 17 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get 18 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post 19 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers 20 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status 21 | 22 | @ExtendWith(SpringExtension::class) 23 | @WebMvcTest 24 | class AuthApiTest(@Autowired val mockMvc: MockMvc) { 25 | 26 | // user 27 | @Test 28 | fun `Check authentication for external users with GET`() { 29 | mockMvc.perform(get("/auth/user") 30 | .param("username", "guest") 31 | .param("password", "guest")) 32 | .andExpect(status().isOk) 33 | .andExpect(MockMvcResultMatchers.content().string("allow administrator management")) 34 | 35 | } 36 | 37 | @Test 38 | fun `Check deny for external users with GET`() { 39 | mockMvc.perform(get("/auth/user") 40 | .param("username", "guest") 41 | .param("password", "wrong")) 42 | .andExpect(status().isOk) 43 | .andExpect(MockMvcResultMatchers.content().string("deny")) 44 | } 45 | 46 | @Test 47 | fun `Check authentication for external users with POST`() { 48 | mockMvc.perform(post("/auth/user").contentType(MediaType.APPLICATION_FORM_URLENCODED) 49 | .content("username=guest&password=guest")) 50 | .andExpect(status().isOk) 51 | .andExpect(MockMvcResultMatchers.content().string("allow administrator management")) 52 | } 53 | 54 | // vhost 55 | @Test 56 | fun `Check vhost for external users with GET`() { 57 | mockMvc.perform(get("/auth/vhost") 58 | .param("username", "guest") 59 | .param("vhost", "guest")) 60 | .andExpect(status().isOk) 61 | .andExpect(MockMvcResultMatchers.content().string("allow")) 62 | } 63 | 64 | @Test 65 | fun `Check vhost for external users with POST`() { 66 | mockMvc.perform(post("/auth/vhost").contentType(MediaType.APPLICATION_FORM_URLENCODED) 67 | .content("username=guest&vhost=guest")) 68 | .andExpect(status().isOk) 69 | .andExpect(MockMvcResultMatchers.content().string("allow")) 70 | } 71 | 72 | // resource 73 | @Test 74 | fun `Check resource_path for external users with GET`() { 75 | mockMvc.perform(get("/auth/resource") 76 | .param("username", "guest") 77 | .param("vhost", "guest") 78 | .param("resource", "exchange") 79 | .param("name", "amq.topic") 80 | .param("permission", "write")) 81 | .andExpect(status().isOk) 82 | .andExpect(MockMvcResultMatchers.content().string("allow")) 83 | } 84 | 85 | @Test 86 | fun `Check resource_path for external users with POST`() { 87 | mockMvc.perform(post("/auth/resource").contentType(MediaType.APPLICATION_FORM_URLENCODED) 88 | .content("username=guest&vhost=guest&resource=exchange&name=amq.topic&permission=write")) 89 | .andExpect(status().isOk) 90 | .andExpect(MockMvcResultMatchers.content().string("allow")) 91 | } 92 | 93 | // topic 94 | @Test 95 | fun `Check topic for external users with GET`() { 96 | mockMvc.perform(get("/auth/topic") 97 | .param("username", "guest") 98 | .param("vhost", "guest") 99 | .param("resource", "exchange") 100 | .param("name", "amq.topic") 101 | .param("routing_key", "a.b") 102 | .param("permission", "write")) 103 | .andExpect(status().isOk) 104 | .andExpect(MockMvcResultMatchers.content().string("allow")) 105 | } 106 | 107 | @Test 108 | fun `Check topic for external users with POST`() { 109 | mockMvc.perform(post("/auth/topic").contentType(MediaType.APPLICATION_FORM_URLENCODED) 110 | .content("username=guest&vhost=guest&resource=exchange&name=amq.topic&permission=write&routing_key=a.b")) 111 | .andExpect(status().isOk) 112 | .andExpect(MockMvcResultMatchers.content().string("allow")) 113 | } 114 | 115 | @Test 116 | fun `Check deny topic for external users with GET`() { 117 | mockMvc.perform(get("/auth/topic") 118 | .param("username", "guest") 119 | .param("vhost", "guest") 120 | .param("resource", "exchange") 121 | .param("name", "amq.topic") 122 | .param("routing_key", "b.b") 123 | .param("permission", "write")) 124 | .andExpect(status().isOk) 125 | .andExpect(MockMvcResultMatchers.content().string("deny")) 126 | } 127 | } -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | 3 | namespace WebApiHttpAuthService 4 | { 5 | public static class WebApiConfig 6 | { 7 | public static void Register(HttpConfiguration config) 8 | { 9 | config.MapHttpAttributeRoutes(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Controllers/AuthController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Net.Http.Formatting; 5 | using System.Text; 6 | using System.Web.Http; 7 | 8 | namespace WebApiHttpAuthService.Controllers 9 | { 10 | [RoutePrefix("auth")] 11 | public class AuthController : ApiController 12 | { 13 | // Note: the following is necessary to ensure that no 14 | // BOM is part of the response 15 | private static readonly UTF8Encoding encoding = new UTF8Encoding(false); 16 | 17 | [Route("user")] 18 | [HttpPost] 19 | public HttpResponseMessage user(FormDataCollection form) 20 | { 21 | string content = "allow administrator management"; 22 | try 23 | { 24 | if (form != null) 25 | { 26 | string username = form.Get("username"); 27 | string password = form.Get("password"); 28 | 29 | if(username=="authuser") //Sample check you can put your custom logic over here 30 | content = "deny"; 31 | 32 | string userlog = string.Format("user :{0}, password :{1}", username, password); 33 | } 34 | } 35 | catch(Exception ex) 36 | { 37 | //check or log error 38 | } 39 | 40 | var resp = new HttpResponseMessage(HttpStatusCode.OK); 41 | resp.Content = new StringContent(content, encoding, "text/plain"); 42 | return resp; 43 | } 44 | 45 | [Route("vhost")] 46 | [HttpPost] 47 | public HttpResponseMessage vhost(FormDataCollection form) 48 | { 49 | string content = "allow"; 50 | try 51 | { 52 | if (form != null) 53 | { 54 | string username = form.Get("username"); 55 | string ip = form.Get("ip"); 56 | 57 | if (username == "authuser") //Sample checks you can put your custom logic over here 58 | content = "deny"; 59 | 60 | string userlog = string.Format("user :{0}, ip :{1}", username, ip); 61 | } 62 | } 63 | catch (Exception ex) 64 | { 65 | //check or log error 66 | } 67 | 68 | var resp = new HttpResponseMessage(HttpStatusCode.OK); 69 | resp.Content = new StringContent(content, encoding, "text/plain"); 70 | return resp; 71 | } 72 | 73 | [Route("resource")] 74 | [HttpPost] 75 | public HttpResponseMessage resource(FormDataCollection form) 76 | { 77 | string content = "allow"; 78 | 79 | try 80 | { 81 | if (form != null) 82 | { 83 | string username = form.Get("username"); 84 | string vhost = form.Get("vhost"); 85 | string resource = form.Get("resource"); 86 | string name = form.Get("name"); 87 | string permission = form.Get("permission"); 88 | 89 | if (username == "authuser") //Sample checks you can put your custom logic over here 90 | content = "deny"; 91 | 92 | string userlog = string.Format("user :{0}, vhost :{1}, resource :{2}, name: {3}, permission: {4}", username, vhost, resource, name, permission); 93 | 94 | } 95 | } 96 | catch (Exception ex) 97 | { 98 | //check or log error 99 | } 100 | 101 | 102 | var resp = new HttpResponseMessage(HttpStatusCode.OK); 103 | resp.Content = new StringContent(content, encoding, "text/plain"); 104 | return resp; 105 | } 106 | 107 | [Route("topic")] 108 | [HttpPost] 109 | public HttpResponseMessage topic(FormDataCollection form) 110 | { 111 | string content = "allow"; 112 | try 113 | { 114 | if (form != null) 115 | { 116 | string username = form.Get("username"); 117 | string vhost = form.Get("vhost"); 118 | string resource = form.Get("resource"); 119 | string name = form.Get("name"); 120 | string permission = form.Get("permission"); 121 | string routing_key = form.Get("routing_key"); 122 | 123 | if (username == "authuser") //Sample checks you can put your custom logic over here 124 | content = "deny"; 125 | 126 | string userlog = string.Format("user :{0}, vhost :{1}, resource :{2}, name: {3}, permission: {4}, routing_key :{5}", username, vhost, resource, name, permission, routing_key); 127 | 128 | } 129 | } 130 | catch (Exception ex) 131 | { 132 | //check or log error 133 | } 134 | 135 | var resp = new HttpResponseMessage(HttpStatusCode.OK); 136 | resp.Content = new StringContent(content, encoding, "text/plain"); 137 | return resp; 138 | } 139 | 140 | 141 | 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="WebApiHttpAuthService.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | 3 | namespace WebApiHttpAuthService 4 | { 5 | public class WebApiApplication : System.Web.HttpApplication 6 | { 7 | protected void Application_Start() 8 | { 9 | GlobalConfiguration.Configure(WebApiConfig.Register); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebApiHttpAuthService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebApiHttpAuthService")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f141c3e3-fd04-475b-b2b9-00328d0f907b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 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 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/WebApiHttpAuthService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {F141C3E3-FD04-475B-B2B9-00328D0F907B} 10 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 11 | Library 12 | Properties 13 | WebApiHttpAuthService 14 | WebApiHttpAuthService 15 | v4.5 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | true 29 | full 30 | false 31 | bin\ 32 | DEBUG;TRACE 33 | prompt 34 | 4 35 | true 36 | 37 | 38 | true 39 | pdbonly 40 | true 41 | bin\ 42 | TRACE 43 | prompt 44 | 4 45 | 46 | 47 | 48 | 49 | ..\..\VEMS.Sample\Dependencies\WSF\Microsoft.Practices.ServiceLocation.dll 50 | 51 | 52 | 53 | 54 | packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll 67 | 68 | 69 | packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Designer 81 | 82 | 83 | 84 | 85 | 86 | 87 | Global.asax 88 | 89 | 90 | 91 | 92 | 93 | 94 | Web.config 95 | 96 | 97 | Web.config 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 10.0 106 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | True 116 | True 117 | 62243 118 | / 119 | http://localhost:62190/ 120 | False 121 | False 122 | 123 | 124 | False 125 | 126 | 127 | 128 | 129 | 136 | 137 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/WebApiHttpAuthService.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | 7 | 8 | 9 | 10 | 11 | 600 12 | True 13 | False 14 | True 15 | 16 | False 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | CurrentPage 25 | True 26 | False 27 | False 28 | False 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | True 38 | True 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/WebApiHttpAuthService.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.8 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApiHttpAuthService", "WebApiHttpAuthService.csproj", "{F141C3E3-FD04-475B-B2B9-00328D0F907B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F141C3E3-FD04-475B-B2B9-00328D0F907B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F141C3E3-FD04-475B-B2B9-00328D0F907B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F141C3E3-FD04-475B-B2B9-00328D0F907B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F141C3E3-FD04-475B-B2B9-00328D0F907B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {2E60A79D-A68A-4486-A8F2-917C08BA2C8A} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnet/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/AuthResult.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace RabbitMqAuthBackendHttp 4 | { 5 | public static class AuthResult 6 | { 7 | public static IActionResult Allow() 8 | { 9 | return new OkObjectResult("allow"); 10 | } 11 | 12 | public static IActionResult Allow(params string[] tags) 13 | { 14 | return new OkObjectResult($"allow {string.Join(" ", tags)}"); 15 | } 16 | 17 | public static IActionResult Deny() 18 | { 19 | return new OkObjectResult("deny"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Controllers/AuthController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.Logging; 4 | using RabbitMqAuthBackendHttp.Requests; 5 | 6 | namespace RabbitMqAuthBackendHttp.Controllers 7 | { 8 | [Route("[controller]")] 9 | [ApiController] 10 | public class AuthController : ControllerBase 11 | { 12 | private readonly ILogger _logger; 13 | 14 | public AuthController(ILogger logger) 15 | { 16 | _logger = logger; 17 | } 18 | 19 | [HttpGet] 20 | public ActionResult Get() 21 | { 22 | return "AuthController"; 23 | } 24 | 25 | [Route("user")] 26 | [HttpPost] 27 | public IActionResult CheckUser([FromForm]UserAuthRequest request) 28 | { 29 | var tags = new [] {"administrator", "management"}; 30 | 31 | try 32 | { 33 | var userlog = string.Format("user : {0}, password : {1}", request.UserName, request.Password); 34 | _logger.LogInformation(userlog); 35 | 36 | if (request.UserName == "authuser") //Sample check you can put your custom logic over here 37 | return AuthResult.Deny(); 38 | 39 | } 40 | catch (Exception ex) 41 | { 42 | //check or log error 43 | } 44 | 45 | return AuthResult.Allow(tags); 46 | } 47 | 48 | [Route("vhost")] 49 | [HttpPost] 50 | public IActionResult CheckVhost([FromForm]VhostAuthRequest request) 51 | { 52 | try 53 | { 54 | var userlog = string.Format("user : {0}, ip : {1}", request.UserName, request.Ip); 55 | _logger.LogInformation(userlog); 56 | 57 | if (request.UserName == "authuser") //Sample checks you can put your custom logic over here 58 | return AuthResult.Deny(); 59 | } 60 | catch (Exception ex) 61 | { 62 | //check or log error 63 | } 64 | 65 | return AuthResult.Allow(); 66 | } 67 | 68 | [Route("resource")] 69 | [HttpPost] 70 | public IActionResult CheckResource([FromForm]ResourceAuthRequest request) 71 | { 72 | try 73 | { 74 | var userlog = $"user : {request.UserName}, vhost : {request.Vhost}, resource : {request.Resource}, " + 75 | $"name : {request.Name}, permission : {request.Permission}"; 76 | _logger.LogInformation(userlog); 77 | 78 | if (request.UserName == "authuser") //Sample checks you can put your custom logic over here 79 | return AuthResult.Deny(); 80 | } 81 | catch (Exception ex) 82 | { 83 | //check or log error 84 | } 85 | 86 | return AuthResult.Allow(); 87 | } 88 | 89 | [Route("topic")] 90 | [HttpPost] 91 | public IActionResult CheckTopic([FromForm]TopicAuthRequest request) 92 | { 93 | try 94 | { 95 | var userlog = $"user : {request.UserName}, vhost : {request.Vhost}, resource : {request.Resource}, " + 96 | $"name : {request.Name}, routing key: {request.RoutingKey}, permission : {request.Permission}"; 97 | _logger.LogInformation(userlog); 98 | 99 | if (request.UserName == "authuser") //Sample checks you can put your custom logic over here 100 | return AuthResult.Deny(); 101 | } 102 | catch (Exception ex) 103 | { 104 | //check or log error 105 | } 106 | 107 | return AuthResult.Allow(); 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace RabbitMqAuthBackendHttp 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 14 | WebHost.CreateDefaultBuilder(args) 15 | .UseStartup(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53729", 7 | "sslPort": 44312 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/values", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "RabbitMqAuthBackendHttp": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "api/values", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | }, 27 | "applicationUrl": "http://localhost:5000" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/RabbitMqAuthBackendHttp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/RabbitMqAuthBackendHttp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RabbitMqAuthBackendHttp", "RabbitMqAuthBackendHttp.csproj", "{5CBC938E-5097-4888-A43F-2A9C190F41A6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|x64.ActiveCfg = Debug|Any CPU 21 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|x64.Build.0 = Debug|Any CPU 22 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|x86.ActiveCfg = Debug|Any CPU 23 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Debug|x86.Build.0 = Debug|Any CPU 24 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|x64.ActiveCfg = Release|Any CPU 27 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|x64.Build.0 = Release|Any CPU 28 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|x86.ActiveCfg = Release|Any CPU 29 | {5CBC938E-5097-4888-A43F-2A9C190F41A6}.Release|x86.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {8B62538E-3E8E-4B80-857E-D34C9DE1CD09} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Requests/Resource.cs: -------------------------------------------------------------------------------- 1 | namespace RabbitMqAuthBackendHttp.Requests 2 | { 3 | public enum Resource 4 | { 5 | Exchange, 6 | 7 | Queue, 8 | 9 | Topic 10 | } 11 | } -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Requests/ResourceAuthRequest.cs: -------------------------------------------------------------------------------- 1 | namespace RabbitMqAuthBackendHttp.Requests 2 | { 3 | public class ResourceAuthRequest 4 | { 5 | public string UserName { get; set; } 6 | 7 | public string Vhost { get; set; } 8 | 9 | public Resource Resource { get; set; } 10 | 11 | public string Name { get; set; } 12 | 13 | public ResourcePermission Permission { get; set; } 14 | } 15 | 16 | public enum ResourcePermission 17 | { 18 | Configure, 19 | 20 | Write, 21 | 22 | Read 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Requests/TopicAuthRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace RabbitMqAuthBackendHttp.Requests 4 | { 5 | public class TopicAuthRequest 6 | { 7 | public string UserName { get; set; } 8 | 9 | public string Vhost { get; set; } 10 | 11 | public string Name { get; set; } 12 | 13 | public Resource Resource { get; set; } 14 | 15 | public TopicPermission Permission { get; set; } 16 | 17 | [ModelBinder(Name = "routing_key")] 18 | public string RoutingKey { get; set; } 19 | } 20 | 21 | public enum TopicPermission 22 | { 23 | Write, 24 | 25 | Read 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Requests/UserAuthRequest.cs: -------------------------------------------------------------------------------- 1 | namespace RabbitMqAuthBackendHttp.Requests 2 | { 3 | public class UserAuthRequest 4 | { 5 | public string UserName { get; set; } 6 | 7 | public string Password { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Requests/VhostAuthRequest.cs: -------------------------------------------------------------------------------- 1 | namespace RabbitMqAuthBackendHttp.Requests 2 | { 3 | public class VhostAuthRequest 4 | { 5 | public string UserName { get; set; } 6 | 7 | public string Vhost { get; set; } 8 | 9 | public string Ip { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | namespace RabbitMqAuthBackendHttp 8 | { 9 | public class Startup 10 | { 11 | public Startup(IConfiguration configuration) 12 | { 13 | Configuration = configuration; 14 | } 15 | 16 | public IConfiguration Configuration { get; } 17 | 18 | public void ConfigureServices(IServiceCollection services) 19 | { 20 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 21 | } 22 | 23 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 24 | { 25 | if (env.IsDevelopment()) 26 | { 27 | app.UseDeveloperExceptionPage(); 28 | } 29 | else 30 | { 31 | app.UseHsts(); 32 | } 33 | 34 | app.UseHttpsRedirection(); 35 | app.UseMvc(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/rabbitmq_auth_backend_webapi_dotnetcore/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /priv/schema/rabbitmq_auth_backend_http.schema: -------------------------------------------------------------------------------- 1 | 2 | %% ========================================================================== 3 | %% ---------------------------------------------------------------------------- 4 | %% RabbitMQ HTTP Authorization 5 | %% 6 | %% ---------------------------------------------------------------------------- 7 | 8 | {mapping, "auth_http.http_method", "rabbitmq_auth_backend_http.http_method", 9 | [{datatype, {enum, [get,post]}}]}. 10 | 11 | {mapping, "auth_http.user_path", "rabbitmq_auth_backend_http.user_path", 12 | [{datatype, string}, {validators, ["uri"]}]}. 13 | 14 | {mapping, "auth_http.vhost_path", "rabbitmq_auth_backend_http.vhost_path", 15 | [{datatype, string}, {validators, ["uri"]}]}. 16 | 17 | {mapping, "auth_http.resource_path", "rabbitmq_auth_backend_http.resource_path", 18 | [{datatype, string}, {validators, ["uri"]}]}. 19 | 20 | {mapping, "auth_http.topic_path", "rabbitmq_auth_backend_http.topic_path", 21 | [{datatype, string}, {validators, ["uri"]}]}. 22 | -------------------------------------------------------------------------------- /src/rabbit_auth_backend_http.erl: -------------------------------------------------------------------------------- 1 | %% This Source Code Form is subject to the terms of the Mozilla Public 2 | %% License, v. 2.0. If a copy of the MPL was not distributed with this 3 | %% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | %% 5 | %% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_auth_backend_http). 9 | 10 | -include_lib("rabbit_common/include/rabbit.hrl"). 11 | 12 | -behaviour(rabbit_authn_backend). 13 | -behaviour(rabbit_authz_backend). 14 | 15 | -export([description/0, p/1, q/1, join_tags/1]). 16 | -export([user_login_authentication/2, user_login_authorization/2, 17 | check_vhost_access/3, check_resource_access/4, check_topic_access/4, 18 | state_can_expire/0]). 19 | 20 | %% If keepalive connection is closed, retry N times before failing. 21 | -define(RETRY_ON_KEEPALIVE_CLOSED, 3). 22 | 23 | -define(RESOURCE_REQUEST_PARAMETERS, [username, vhost, resource, name, permission]). 24 | 25 | -define(SUCCESSFUL_RESPONSE_CODES, [200, 201]). 26 | 27 | %%-------------------------------------------------------------------- 28 | 29 | description() -> 30 | [{name, <<"HTTP">>}, 31 | {description, <<"HTTP authentication / authorisation">>}]. 32 | 33 | %%-------------------------------------------------------------------- 34 | 35 | user_login_authentication(Username, AuthProps) -> 36 | case http_req(p(user_path), q([{username, Username}|AuthProps])) of 37 | {error, _} = E -> E; 38 | "deny" -> {refused, "Denied by the backing HTTP service", []}; 39 | "allow" ++ Rest -> Tags = [rabbit_data_coercion:to_atom(T) || 40 | T <- string:tokens(Rest, " ")], 41 | {ok, #auth_user{username = Username, 42 | tags = Tags, 43 | impl = none}}; 44 | Other -> {error, {bad_response, Other}} 45 | end. 46 | 47 | user_login_authorization(Username, AuthProps) -> 48 | case user_login_authentication(Username, AuthProps) of 49 | {ok, #auth_user{impl = Impl}} -> {ok, Impl}; 50 | Else -> Else 51 | end. 52 | 53 | check_vhost_access(#auth_user{username = Username, tags = Tags}, VHost, undefined) -> 54 | do_check_vhost_access(Username, Tags, VHost, "", undefined); 55 | check_vhost_access(#auth_user{username = Username, tags = Tags}, VHost, 56 | AuthzData = #{peeraddr := PeerAddr}) when is_map(AuthzData) -> 57 | AuthzData1 = maps:remove(peeraddr, AuthzData), 58 | Ip = parse_peeraddr(PeerAddr), 59 | do_check_vhost_access(Username, Tags, VHost, Ip, AuthzData1). 60 | 61 | do_check_vhost_access(Username, Tags, VHost, Ip, AuthzData) -> 62 | OptionsParameters = context_as_parameters(AuthzData), 63 | bool_req(vhost_path, [{username, Username}, 64 | {vhost, VHost}, 65 | {ip, Ip}, 66 | {tags, join_tags(Tags)}] ++ OptionsParameters). 67 | 68 | check_resource_access(#auth_user{username = Username, tags = Tags}, 69 | #resource{virtual_host = VHost, kind = Type, name = Name}, 70 | Permission, 71 | AuthzContext) -> 72 | OptionsParameters = context_as_parameters(AuthzContext), 73 | bool_req(resource_path, [{username, Username}, 74 | {vhost, VHost}, 75 | {resource, Type}, 76 | {name, Name}, 77 | {permission, Permission}, 78 | {tags, join_tags(Tags)}] ++ OptionsParameters). 79 | 80 | check_topic_access(#auth_user{username = Username, tags = Tags}, 81 | #resource{virtual_host = VHost, kind = topic = Type, name = Name}, 82 | Permission, 83 | Context) -> 84 | OptionsParameters = context_as_parameters(Context), 85 | bool_req(topic_path, [{username, Username}, 86 | {vhost, VHost}, 87 | {resource, Type}, 88 | {name, Name}, 89 | {permission, Permission}, 90 | {tags, join_tags(Tags)}] ++ OptionsParameters). 91 | 92 | state_can_expire() -> false. 93 | 94 | %%-------------------------------------------------------------------- 95 | 96 | context_as_parameters(Options) when is_map(Options) -> 97 | % filter keys that would erase fixed parameters 98 | [{rabbit_data_coercion:to_atom(Key), maps:get(Key, Options)} 99 | || Key <- maps:keys(Options), 100 | lists:member( 101 | rabbit_data_coercion:to_atom(Key), 102 | ?RESOURCE_REQUEST_PARAMETERS) =:= false]; 103 | context_as_parameters(_) -> 104 | []. 105 | 106 | bool_req(PathName, Props) -> 107 | case http_req(p(PathName), q(Props)) of 108 | "deny" -> false; 109 | "allow" -> true; 110 | E -> E 111 | end. 112 | 113 | http_req(Path, Query) -> http_req(Path, Query, ?RETRY_ON_KEEPALIVE_CLOSED). 114 | 115 | http_req(Path, Query, Retry) -> 116 | case do_http_req(Path, Query) of 117 | {error, socket_closed_remotely} -> 118 | %% HTTP keepalive connection can no longer be used. Retry the request. 119 | case Retry > 0 of 120 | true -> http_req(Path, Query, Retry - 1); 121 | false -> {error, socket_closed_remotely} 122 | end; 123 | Other -> Other 124 | end. 125 | 126 | 127 | do_http_req(Path0, Query) -> 128 | URI = uri_parser:parse(Path0, [{port, 80}]), 129 | {host, Host} = lists:keyfind(host, 1, URI), 130 | {port, Port} = lists:keyfind(port, 1, URI), 131 | HostHdr = rabbit_misc:format("~s:~b", [Host, Port]), 132 | {ok, Method} = application:get_env(rabbitmq_auth_backend_http, http_method), 133 | Request = case rabbit_data_coercion:to_atom(Method) of 134 | get -> 135 | Path = Path0 ++ "?" ++ Query, 136 | rabbit_log:debug("auth_backend_http: GET ~s", [Path]), 137 | {Path, [{"Host", HostHdr}]}; 138 | post -> 139 | rabbit_log:debug("auth_backend_http: POST ~s", [Path0]), 140 | {Path0, [{"Host", HostHdr}], "application/x-www-form-urlencoded", Query} 141 | end, 142 | HttpOpts = case application:get_env(rabbitmq_auth_backend_http, 143 | ssl_options) of 144 | {ok, Opts} when is_list(Opts) -> [{ssl, Opts}]; 145 | _ -> [] 146 | end, 147 | 148 | case httpc:request(Method, Request, HttpOpts, []) of 149 | {ok, {{_HTTP, Code, _}, _Headers, Body}} -> 150 | rabbit_log:debug("auth_backend_http: response code is ~p, body: ~p", [Code, Body]), 151 | case lists:member(Code, ?SUCCESSFUL_RESPONSE_CODES) of 152 | true -> case parse_resp(Body) of 153 | {error, _} = E -> E; 154 | Resp -> Resp 155 | end; 156 | false -> {error, {Code, Body}} 157 | end; 158 | {error, _} = E -> 159 | E 160 | end. 161 | 162 | p(PathName) -> 163 | {ok, Path} = application:get_env(rabbitmq_auth_backend_http, PathName), 164 | Path. 165 | 166 | q(Args) -> 167 | string:join([escape(K, V) || {K, V} <- Args], "&"). 168 | 169 | escape(K, Map) when is_map(Map) -> 170 | string:join([escape(rabbit_data_coercion:to_list(K) ++ "." ++ rabbit_data_coercion:to_list(Key), Value) 171 | || {Key, Value} <- maps:to_list(Map)], "&"); 172 | escape(K, V) -> 173 | rabbit_data_coercion:to_list(K) ++ "=" ++ rabbit_http_util:quote_plus(V). 174 | 175 | parse_resp(Resp) -> string:to_lower(string:strip(Resp)). 176 | 177 | join_tags([]) -> ""; 178 | join_tags(Tags) -> 179 | Strings = [rabbit_data_coercion:to_list(T) || T <- Tags], 180 | string:join(Strings, " "). 181 | 182 | parse_peeraddr(PeerAddr) -> 183 | handle_inet_ntoa_peeraddr(inet:ntoa(PeerAddr), PeerAddr). 184 | 185 | handle_inet_ntoa_peeraddr({error, einval}, PeerAddr) -> 186 | rabbit_data_coercion:to_list(PeerAddr); 187 | handle_inet_ntoa_peeraddr(PeerAddrStr, _PeerAddr0) -> 188 | PeerAddrStr. 189 | -------------------------------------------------------------------------------- /src/rabbit_auth_backend_http_app.erl: -------------------------------------------------------------------------------- 1 | %% This Source Code Form is subject to the terms of the Mozilla Public 2 | %% License, v. 2.0. If a copy of the MPL was not distributed with this 3 | %% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | %% 5 | %% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_auth_backend_http_app). 9 | 10 | -behaviour(application). 11 | -export([start/2, stop/1]). 12 | 13 | -behaviour(supervisor). 14 | -export([init/1]). 15 | 16 | start(_Type, _StartArgs) -> 17 | supervisor:start_link({local,?MODULE},?MODULE,[]). 18 | 19 | stop(_State) -> 20 | ok. 21 | 22 | %%---------------------------------------------------------------------------- 23 | 24 | init([]) -> 25 | {ok, {{one_for_one,3,10},[]}}. 26 | -------------------------------------------------------------------------------- /test/auth_SUITE.erl: -------------------------------------------------------------------------------- 1 | %% This Source Code Form is subject to the terms of the Mozilla Public 2 | %% License, v. 2.0. If a copy of the MPL was not distributed with this 3 | %% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | %% 5 | %% Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | -module(auth_SUITE). 8 | 9 | -include_lib("common_test/include/ct.hrl"). 10 | -include_lib("eunit/include/eunit.hrl"). 11 | -include_lib("rabbit_common/include/rabbit.hrl"). 12 | 13 | -compile(export_all). 14 | 15 | -define(AUTH_PORT, 8000). 16 | -define(USER_PATH, "/auth/user"). 17 | -define(BACKEND_CONFIG, 18 | [{http_method, get}, 19 | {user_path, "http://localhost:" ++ integer_to_list(?AUTH_PORT) ++ ?USER_PATH}, 20 | {vhost_path, "http://localhost:" ++ integer_to_list(?AUTH_PORT) ++ "/auth/vhost"}, 21 | {resource_path, "http://localhost:" ++ integer_to_list(?AUTH_PORT) ++ "/auth/resource"}, 22 | {topic_path, "http://localhost:" ++ integer_to_list(?AUTH_PORT) ++ "/auth/topic"}]). 23 | -define(ALLOWED_USER, #{username => <<"Ala">>, 24 | password => <<"Kocur">>, 25 | tags => [policymaker, monitoring]}). 26 | -define(DENIED_USER, #{username => <<"Alice">>, password => <<"Cat">>}). 27 | 28 | all() -> [grants_access_to_user, denies_access_to_user]. 29 | 30 | init_per_suite(Config) -> 31 | configure_http_auth_backend(), 32 | #{username := Username, password := Password, tags := Tags} = ?ALLOWED_USER, 33 | start_http_auth_server(?AUTH_PORT, ?USER_PATH, #{Username => {Password, Tags}}), 34 | [{allowed_user, ?ALLOWED_USER}, {denied_user, ?DENIED_USER} | Config]. 35 | 36 | end_per_suite(_Config) -> 37 | stop_http_auth_server(). 38 | 39 | grants_access_to_user(Config) -> 40 | #{username := U, password := P, tags := T} = ?config(allowed_user, Config), 41 | ?assertMatch({ok, #auth_user{username = U, tags = T}}, 42 | rabbit_auth_backend_http:user_login_authentication(U, [{password, P}])). 43 | 44 | denies_access_to_user(Config) -> 45 | #{username := U, password := P} = ?config(denied_user, Config), 46 | ?assertMatch({refused, "Denied by the backing HTTP service", []}, 47 | rabbit_auth_backend_http:user_login_authentication(U, [{password, P}])). 48 | 49 | %%% HELPERS 50 | 51 | configure_http_auth_backend() -> 52 | {ok, _} = application:ensure_all_started(inets), 53 | [application:set_env(rabbitmq_auth_backend_http, K, V) || {K, V} <- ?BACKEND_CONFIG]. 54 | 55 | start_http_auth_server(Port, Path, Users) -> 56 | application:ensure_all_started(cowboy), 57 | Dispatch = cowboy_router:compile([{'_', [{Path, auth_http_mock, Users}]}]), 58 | {ok, _} = cowboy:start_clear( 59 | mock_http_auth_listener, [{port, Port}], #{env => #{dispatch => Dispatch}}). 60 | 61 | stop_http_auth_server() -> 62 | cowboy:stop_listener(mock_http_auth_listener). 63 | -------------------------------------------------------------------------------- /test/auth_http_mock.erl: -------------------------------------------------------------------------------- 1 | -module(auth_http_mock). 2 | 3 | -export([init/2]). 4 | 5 | %%% CALLBACKS 6 | 7 | init(Req = #{method := <<"GET">>}, Users) -> 8 | QsVals = cowboy_req:parse_qs(Req), 9 | Reply = authenticate(proplists:get_value(<<"username">>, QsVals), 10 | proplists:get_value(<<"password">>, QsVals), 11 | Users), 12 | Req2 = cowboy_req:reply(200, #{<<"content-type">> => <<"text/plain">>}, Reply, Req), 13 | {ok, Req2, Users}. 14 | 15 | %%% HELPERS 16 | 17 | authenticate(Username, Password, Users) -> 18 | case maps:get(Username, Users, undefined) of 19 | {MatchingPassword, Tags} when Password =:= MatchingPassword -> 20 | StringTags = lists:map(fun(T) -> io_lib:format("~s", [T]) end, Tags), 21 | <<"allow ", (list_to_binary(string:join(StringTags, " ")))/binary>>; 22 | {_OtherPassword, _} -> 23 | <<"deny">>; 24 | undefined -> 25 | <<"deny">> 26 | end. -------------------------------------------------------------------------------- /test/config_schema_SUITE.erl: -------------------------------------------------------------------------------- 1 | %% This Source Code Form is subject to the terms of the Mozilla Public 2 | %% License, v. 2.0. If a copy of the MPL was not distributed with this 3 | %% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | %% 5 | %% Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(config_schema_SUITE). 9 | 10 | -compile(export_all). 11 | 12 | all() -> 13 | [ 14 | run_snippets 15 | ]. 16 | 17 | %% ------------------------------------------------------------------- 18 | %% Testsuite setup/teardown. 19 | %% ------------------------------------------------------------------- 20 | 21 | init_per_suite(Config) -> 22 | rabbit_ct_helpers:log_environment(), 23 | Config1 = rabbit_ct_helpers:run_setup_steps(Config), 24 | rabbit_ct_config_schema:init_schemas(rabbitmq_auth_backend_http, Config1). 25 | 26 | 27 | end_per_suite(Config) -> 28 | rabbit_ct_helpers:run_teardown_steps(Config). 29 | 30 | init_per_testcase(Testcase, Config) -> 31 | rabbit_ct_helpers:testcase_started(Config, Testcase), 32 | Config1 = rabbit_ct_helpers:set_config(Config, [ 33 | {rmq_nodename_suffix, Testcase} 34 | ]), 35 | rabbit_ct_helpers:run_steps(Config1, 36 | rabbit_ct_broker_helpers:setup_steps() ++ 37 | rabbit_ct_client_helpers:setup_steps()). 38 | 39 | end_per_testcase(Testcase, Config) -> 40 | Config1 = rabbit_ct_helpers:run_steps(Config, 41 | rabbit_ct_client_helpers:teardown_steps() ++ 42 | rabbit_ct_broker_helpers:teardown_steps()), 43 | rabbit_ct_helpers:testcase_finished(Config1, Testcase). 44 | 45 | %% ------------------------------------------------------------------- 46 | %% Testcases. 47 | %% ------------------------------------------------------------------- 48 | 49 | run_snippets(Config) -> 50 | ok = rabbit_ct_broker_helpers:rpc(Config, 0, 51 | ?MODULE, run_snippets1, [Config]). 52 | 53 | run_snippets1(Config) -> 54 | rabbit_ct_config_schema:run_snippets(Config). 55 | 56 | -------------------------------------------------------------------------------- /test/config_schema_SUITE_data/rabbitmq_auth_backend_http.snippets: -------------------------------------------------------------------------------- 1 | [{all_keys, 2 | "auth_backends.1 = http 3 | auth_http.http_method = post 4 | auth_http.user_path = http://some-server/auth/user 5 | auth_http.vhost_path = http://some-server/auth/vhost 6 | auth_http.resource_path = http://some-server/auth/resource", 7 | [{rabbit,[{auth_backends,[rabbit_auth_backend_http]}]}, 8 | {rabbitmq_auth_backend_http, 9 | [{http_method, post}, 10 | {user_path,"http://some-server/auth/user"}, 11 | {vhost_path,"http://some-server/auth/vhost"}, 12 | {resource_path,"http://some-server/auth/resource"}]}], 13 | [rabbitmq_auth_backend_http]} 14 | 15 | , {default_http_method, 16 | "auth_backends.1 = http 17 | auth_http.user_path = http://some-server/auth/user 18 | auth_http.vhost_path = http://some-server/auth/vhost 19 | auth_http.resource_path = http://some-server/auth/resource", 20 | [{rabbit,[{auth_backends,[rabbit_auth_backend_http]}]}, 21 | {rabbitmq_auth_backend_http, 22 | [{user_path,"http://some-server/auth/user"}, 23 | {vhost_path,"http://some-server/auth/vhost"}, 24 | {resource_path,"http://some-server/auth/resource"}]}], 25 | [rabbitmq_auth_backend_http]} 26 | ]. 27 | -------------------------------------------------------------------------------- /test/unit_SUITE.erl: -------------------------------------------------------------------------------- 1 | %% This Source Code Form is subject to the terms of the Mozilla Public 2 | %% License, v. 2.0. If a copy of the MPL was not distributed with this 3 | %% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | %% 5 | %% Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(unit_SUITE). 9 | 10 | -include_lib("common_test/include/ct.hrl"). 11 | -include_lib("eunit/include/eunit.hrl"). 12 | 13 | -compile(export_all). 14 | 15 | all() -> 16 | [ 17 | {group, parallel_tests} 18 | ]. 19 | 20 | groups() -> 21 | [ 22 | {parallel_tests, [], [ 23 | query, 24 | join_tags 25 | ]} 26 | ]. 27 | 28 | init_per_group(_, Config) -> Config. 29 | end_per_group(_, Config) -> Config. 30 | 31 | query(_Config) -> 32 | ?assertEqual("username=guest&vhost=%2F&resource=topic&name=amp.topic&permission=write", 33 | rabbit_auth_backend_http:q([ 34 | {username, <<"guest">>}, 35 | {vhost, <<"/">>}, 36 | {resource, topic}, 37 | {name, <<"amp.topic">>}, 38 | {permission, write}])), 39 | 40 | ?assertEqual("username=guest&routing_key=a.b.c&variable_map.username=guest&variable_map.vhost=other-vhost", 41 | rabbit_auth_backend_http:q([ 42 | {username, <<"guest">>}, 43 | {routing_key,<<"a.b.c">>}, 44 | {variable_map, #{<<"username">> => <<"guest">>, 45 | <<"vhost">> => <<"other-vhost">>} 46 | }])). 47 | 48 | join_tags(_Config) -> 49 | ?assertEqual("management administrator custom", 50 | rabbit_auth_backend_http:join_tags([management, administrator, custom])), 51 | ?assertEqual("management administrator custom2", 52 | rabbit_auth_backend_http:join_tags(["management", "administrator", "custom2"])), 53 | ?assertEqual("management administrator custom3 group:dev", 54 | rabbit_auth_backend_http:join_tags([management, administrator, custom3, 'group:dev'])). 55 | --------------------------------------------------------------------------------