├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── test-erlang-otp-22.3.yaml │ ├── test-erlang-otp-23.0.yaml │ └── test-jobs │ └── 10-dialyzer.yaml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Caddyfile ├── LICENSE ├── LICENSE-APACHE2-excanvas ├── LICENSE-BSD-base64js ├── LICENSE-ISC-cowboy ├── LICENSE-MIT-EJS ├── LICENSE-MIT-Flot ├── LICENSE-MIT-Sammy ├── LICENSE-MIT-jQuery ├── LICENSE-MPL-RabbitMQ ├── Makefile ├── README.md ├── bin └── rabbitmqadmin ├── erlang.mk ├── include └── rabbit_mgmt.hrl ├── priv ├── schema │ └── rabbitmq_management.schema └── www │ ├── api │ └── index.html │ ├── cli │ └── index.html │ ├── css │ ├── evil.css │ └── main.css │ ├── favicon.ico │ ├── img │ ├── bg-binary.png │ ├── bg-green-dark.png │ ├── bg-red-dark.png │ ├── bg-red.png │ ├── bg-yellow-dark.png │ ├── collapse.png │ ├── expand.png │ ├── rabbitmqlogo-master-copy.svg │ └── rabbitmqlogo.svg │ ├── index.html │ └── js │ ├── base64.js │ ├── charts.js │ ├── dispatcher.js │ ├── ejs-1.0.js │ ├── ejs-1.0.min.js │ ├── excanvas.js │ ├── excanvas.min.js │ ├── formatters.js │ ├── global.js │ ├── jquery-3.5.1.js │ ├── jquery-3.5.1.min.js │ ├── jquery.flot-0.8.1.js │ ├── jquery.flot-0.8.1.min.js │ ├── jquery.flot-0.8.1.time.js │ ├── jquery.flot-0.8.1.time.min.js │ ├── json2-2016.10.28.js │ ├── main.js │ ├── prefs.js │ ├── sammy-0.7.6.js │ ├── sammy-0.7.6.min.js │ ├── singular │ ├── client_frame.html │ ├── postaccess.html │ ├── postauth.html │ ├── rpFrame.js │ ├── singular.js │ └── singular.umd.js │ └── tmpl │ ├── 404.ejs │ ├── add-binding.ejs │ ├── binary.ejs │ ├── bindings.ejs │ ├── channel.ejs │ ├── channels-list.ejs │ ├── channels.ejs │ ├── cluster-name.ejs │ ├── columns-options.ejs │ ├── connection.ejs │ ├── connections.ejs │ ├── consumers.ejs │ ├── exchange.ejs │ ├── exchanges.ejs │ ├── feature-flags.ejs │ ├── layout.ejs │ ├── limits.ejs │ ├── list-exchanges.ejs │ ├── login.ejs │ ├── login_uaa.ejs │ ├── memory-bar.ejs │ ├── memory-table.ejs │ ├── memory.ejs │ ├── messages.ejs │ ├── msg-detail-deliveries.ejs │ ├── msg-detail-publishes.ejs │ ├── node.ejs │ ├── overview.ejs │ ├── partition.ejs │ ├── permissions.ejs │ ├── policies.ejs │ ├── policy.ejs │ ├── popup.ejs │ ├── publish.ejs │ ├── queue.ejs │ ├── queues.ejs │ ├── rate-options.ejs │ ├── registry.ejs │ ├── status.ejs │ ├── topic-permissions.ejs │ ├── user.ejs │ ├── users.ejs │ ├── vhost.ejs │ └── vhosts.ejs ├── rabbitmq-components.mk ├── scripts └── seed.sh ├── src ├── rabbit_mgmt_app.erl ├── rabbit_mgmt_cors.erl ├── rabbit_mgmt_csp.erl ├── rabbit_mgmt_db.erl ├── rabbit_mgmt_db_cache.erl ├── rabbit_mgmt_db_cache_sup.erl ├── rabbit_mgmt_dispatcher.erl ├── rabbit_mgmt_extension.erl ├── rabbit_mgmt_headers.erl ├── rabbit_mgmt_hsts.erl ├── rabbit_mgmt_load_definitions.erl ├── rabbit_mgmt_reset_handler.erl ├── rabbit_mgmt_stats.erl ├── rabbit_mgmt_sup.erl ├── rabbit_mgmt_sup_sup.erl ├── rabbit_mgmt_util.erl ├── rabbit_mgmt_wm_aliveness_test.erl ├── rabbit_mgmt_wm_auth.erl ├── rabbit_mgmt_wm_auth_attempts.erl ├── rabbit_mgmt_wm_binding.erl ├── rabbit_mgmt_wm_bindings.erl ├── rabbit_mgmt_wm_channel.erl ├── rabbit_mgmt_wm_channels.erl ├── rabbit_mgmt_wm_channels_vhost.erl ├── rabbit_mgmt_wm_cluster_name.erl ├── rabbit_mgmt_wm_connection.erl ├── rabbit_mgmt_wm_connection_channels.erl ├── rabbit_mgmt_wm_connections.erl ├── rabbit_mgmt_wm_connections_vhost.erl ├── rabbit_mgmt_wm_consumers.erl ├── rabbit_mgmt_wm_definitions.erl ├── rabbit_mgmt_wm_exchange.erl ├── rabbit_mgmt_wm_exchange_publish.erl ├── rabbit_mgmt_wm_exchanges.erl ├── rabbit_mgmt_wm_extensions.erl ├── rabbit_mgmt_wm_feature_flag_enable.erl ├── rabbit_mgmt_wm_feature_flags.erl ├── rabbit_mgmt_wm_global_parameter.erl ├── rabbit_mgmt_wm_global_parameters.erl ├── rabbit_mgmt_wm_health_check_alarms.erl ├── rabbit_mgmt_wm_health_check_certificate_expiration.erl ├── rabbit_mgmt_wm_health_check_local_alarms.erl ├── rabbit_mgmt_wm_health_check_node_is_mirror_sync_critical.erl ├── rabbit_mgmt_wm_health_check_node_is_quorum_critical.erl ├── rabbit_mgmt_wm_health_check_port_listener.erl ├── rabbit_mgmt_wm_health_check_protocol_listener.erl ├── rabbit_mgmt_wm_health_check_virtual_hosts.erl ├── rabbit_mgmt_wm_healthchecks.erl ├── rabbit_mgmt_wm_limit.erl ├── rabbit_mgmt_wm_limits.erl ├── rabbit_mgmt_wm_login.erl ├── rabbit_mgmt_wm_node.erl ├── rabbit_mgmt_wm_node_memory.erl ├── rabbit_mgmt_wm_node_memory_ets.erl ├── rabbit_mgmt_wm_nodes.erl ├── rabbit_mgmt_wm_operator_policies.erl ├── rabbit_mgmt_wm_operator_policy.erl ├── rabbit_mgmt_wm_overview.erl ├── rabbit_mgmt_wm_parameter.erl ├── rabbit_mgmt_wm_parameters.erl ├── rabbit_mgmt_wm_permission.erl ├── rabbit_mgmt_wm_permissions.erl ├── rabbit_mgmt_wm_permissions_user.erl ├── rabbit_mgmt_wm_permissions_vhost.erl ├── rabbit_mgmt_wm_policies.erl ├── rabbit_mgmt_wm_policy.erl ├── rabbit_mgmt_wm_queue.erl ├── rabbit_mgmt_wm_queue_actions.erl ├── rabbit_mgmt_wm_queue_get.erl ├── rabbit_mgmt_wm_queue_purge.erl ├── rabbit_mgmt_wm_queues.erl ├── rabbit_mgmt_wm_rebalance_queues.erl ├── rabbit_mgmt_wm_redirect.erl ├── rabbit_mgmt_wm_reset.erl ├── rabbit_mgmt_wm_static.erl ├── rabbit_mgmt_wm_topic_permission.erl ├── rabbit_mgmt_wm_topic_permissions.erl ├── rabbit_mgmt_wm_topic_permissions_user.erl ├── rabbit_mgmt_wm_topic_permissions_vhost.erl ├── rabbit_mgmt_wm_user.erl ├── rabbit_mgmt_wm_user_limit.erl ├── rabbit_mgmt_wm_user_limits.erl ├── rabbit_mgmt_wm_users.erl ├── rabbit_mgmt_wm_users_bulk_delete.erl ├── rabbit_mgmt_wm_vhost.erl ├── rabbit_mgmt_wm_vhost_restart.erl ├── rabbit_mgmt_wm_vhosts.erl └── rabbit_mgmt_wm_whoami.erl └── test ├── cache_SUITE.erl ├── clustering_SUITE.erl ├── clustering_prop_SUITE.erl ├── config_schema_SUITE.erl ├── config_schema_SUITE_data ├── certs │ ├── cacert.pem │ ├── cert.pem │ └── key.pem ├── rabbit-mgmt │ └── access.log └── rabbitmq_management.snippets ├── listener_config_SUITE.erl ├── rabbit_mgmt_http_SUITE.erl ├── rabbit_mgmt_http_health_checks_SUITE.erl ├── rabbit_mgmt_only_http_SUITE.erl ├── rabbit_mgmt_rabbitmqadmin_SUITE.erl ├── rabbit_mgmt_runtime_parameters_util.erl ├── rabbit_mgmt_stats_SUITE.erl ├── rabbit_mgmt_test_db_SUITE.erl ├── rabbit_mgmt_test_unit_SUITE.erl └── stats_SUITE.erl /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for using RabbitMQ and for taking the time to report an 2 | issue. 3 | 4 | ## Does This Belong to GitHub or RabbitMQ Mailing List? 5 | 6 | *Important:* please first read the `CONTRIBUTING.md` document in the 7 | root of this repository. It will help you determine whether your 8 | feedback should be directed to the RabbitMQ mailing list [1] instead. 9 | 10 | ## Please Help Maintainers and Contributors Help You 11 | 12 | In order for the RabbitMQ team to investigate your issue, please provide 13 | **as much as possible** of the following details: 14 | 15 | * RabbitMQ version 16 | * Erlang version 17 | * RabbitMQ server and client application log files 18 | * A runnable code sample, terminal transcript or detailed set of 19 | instructions that can be used to reproduce the issue 20 | * RabbitMQ plugin information via `rabbitmq-plugins list` 21 | * Client library version (for all libraries used) 22 | * Operating system, version, and patch level 23 | 24 | Running the `rabbitmq-collect-env` [2] script can provide most of the 25 | information needed. Please make the archive available via a third-party 26 | service and note that **the script does not attempt to scrub any 27 | sensitive data**. 28 | 29 | If your issue involves RabbitMQ management UI or HTTP API, please also provide 30 | the following: 31 | 32 | * Browser and its version 33 | * What management UI page was used (if applicable) 34 | * How the HTTP API requests performed can be reproduced with `curl` 35 | * Operating system on which you are running your browser, and its version 36 | * Errors reported in the JavaScript console (if any) 37 | 38 | This information **greatly speeds up issue investigation** (or makes it 39 | possible to investigate it at all). Please help project maintainers and 40 | contributors to help you by providing it! 41 | 42 | 1. https://groups.google.com/forum/#!forum/rabbitmq-users 43 | 2. https://github.com/rabbitmq/support-tools/blob/master/scripts/rabbitmq-collect-env 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | 3 | Please describe the big picture of your changes here to communicate to the RabbitMQ team 4 | why we should accept this pull request. If it fixes a bug or resolves a feature request, 5 | be sure to link to that issue. 6 | 7 | A pull request that doesn't explain **why** the change was made has a much lower chance of 8 | being accepted. 9 | 10 | If English isn't your first language, don't worry about it and try to communicate the problem 11 | 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 | - [ ] Bugfix (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 existing functionality to not work as expected) 22 | - [ ] Documentation (correction or otherwise) 23 | - [ ] Cosmetics (whitespace, appearance) 24 | 25 | ## Checklist 26 | 27 | _Put an `x` in the boxes that apply. You can also fill these out after 28 | creating the PR. If you're unsure about any of them, don't hesitate to 29 | ask on the mailing list. We're here to help! This is simply a reminder 30 | of what we are 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 42 | discussion by explaining why you chose the solution you did and what 43 | alternatives you considered, etc. 44 | -------------------------------------------------------------------------------- /.github/workflows/test-jobs/10-dialyzer.yaml: -------------------------------------------------------------------------------- 1 | dialyzer: 2 | name: No-op Dialyzer 3 | runs-on: ubuntu-latest 4 | steps: 5 | - name: no-op 6 | run: | 7 | true 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sw? 2 | .*.sw? 3 | *.beam 4 | *.pem 5 | erl_crash.dump 6 | MnesiaCore.* 7 | /.erlang.mk/ 8 | /cover/ 9 | /debug/ 10 | /deps/ 11 | /doc/ 12 | /ebin/ 13 | /escript/ 14 | /escript.lock 15 | /logs/ 16 | /plugins/ 17 | /plugins.lock 18 | /sbin/ 19 | /sbin.lock 20 | /xrefr 21 | 22 | rabbitmq_management.d 23 | .rabbitmq_management.plt 24 | 25 | # Common Test 26 | ct_run* 27 | all_runs.html 28 | index.html 29 | ct_default.css 30 | ct_log_cache 31 | variables-ct* 32 | 33 | *.coverdata 34 | 35 | test/config_schema_SUITE_data/schema/ 36 | .vscode/* -------------------------------------------------------------------------------- /.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: Tu26VJ9BsXxL20xxwWk4cbCkZyqyxYmNpSSqco5r3FLeU5hk5Vkk+s2BareRvqKhKHFlvyxu8GwsKtajMvsieP6y5J99gSeub6fDOIskPz61bo0aKA9nbDuBFSG1Z5wgXx1XRo0yDatLxXCXe3FbThRsylG7XNjtRaru1/lwuVxfxPtBGQ1opvQX71sST3GYSPoBYR+JlcVpU+uDHMAzsP8J0m5rEpxcl821aTMk3iz90hBQMsoLTBmSQePPcNqOA/1OH75VfjuXR8JBXHvA9njrUBrsyxgHf2uOh3jAXdIrHZwZg/17+y7gNVqByfx/UpGb8XEpVkncg/cRyVIHMk7/gFCZkeVC1QkIN5+EPiGLF7u32x9QaT7Zqz57iLh3IJzED2dj12qWaeX8QypF1K1r5qq4pRrN6iEZx76stpZbyFT4XnExHRdzPuouy7yz1gDHF0HOxbNLowzc/jk7tuTp+qmDSR5tRvegAIH3TONegxXyB7smdbvdI6MCN5/GP2bGK7HiqYWCmTGHtJwgxBKc5XoV8ZjpXfKxG98WbK5RsSP1miRnmxSbxaV0Gai1hfFlanJFFxTA9584O+NVRXNNFMfnnt20Ts6OwoXTcJ/boIPjF5Mcm0eJ4nz4R18TArXE4B5S4pTk3eQkG1ACDigkYZ3fc6ws4cWrt8BZASI= 21 | - secure: fNEx9OXi2UisiYu0FiHJpV9+vWLB9DIUAIKG24GfUHVgZqFQOInBf5fEYrjlVgm5zNezSBS3hFNHXd/EXJF8KNgbf6mI0z4h4RyyQY98N+78tWvINoIawEeYpgC6NTI52MdaCfV+fTVWhiL0uP7mqWhLmll2bKXIy6HA6I9PnmiQSloNe64vUPF+UsVZHzzeabK4DR2VdI3h+BGXzOY9FG8Kt2voiXOLd2RFpVeN86FDTp+uVZY/K9e/MsktoK+XaZZ4qMAgm6lB32LVkzl3KA9ki6y6BY7le1m2c90hxAtBJGWZptkMb+VL0Fem39nEBnLjE0a0vIddp32PLJQmv6eopMfLay5BIkwtkRwv3P0uCwYd0bgYQSHF/gdTCcK1nr7fMhkQveBh6vmnbhrca7OeQRHz08+jo6EquUgNQZKmTZPWXQn9lS9mU/0EDLJJhn4KhJezGw6DcAAqB0KqmQedxtHMUT87by7LzhINwKZnm4y5WKA/W/zLI6dNqvIgc5C6UJh0EVgxa13GRmrnGmttV1dtLRQhiMJCbJykaekjPMULUmli0RbFz7bSFqFqEUsF+wwovyD+Y6D8KGOJdvvEYPdPIFpRPnhGUvH86JzsFdVKNJBicGI9LpCtlXlWNRbQIQ8uV5ze2HhxSJhtM6e6dB4d9yzpp6a81uR77bk= 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.10' 29 | otp_release: 30 | - '22.3' 31 | - '23.0' 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 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | :2015 2 | log stdout 3 | errors stderr 4 | root priv/www 5 | proxy /api localhost:15672 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This package, the RabbitMQ Management Plugin is licensed under the MPL 2.0. For the 2 | MPL 2.0, please see LICENSE-MPL-RabbitMQ. 3 | 4 | This package makes use of the following third party libraries: 5 | 6 | | Name | Website | License type | License file | 7 | | -------------- | ------------------------------------------------------ | ------------- | ------------------------ | 8 | | ExplorerCanvas | https://github.com/arv/explorercanvas | APACHE 2 | LICENSE-APACHE2-excanvas | 9 | | base64.js | https://code.google.com/p/stringencoders/ | BSD | LICENSE-BSD-base64js | 10 | | Cowboy | https://ninenines.eu/ | ISC | LICENSE-ISC-cowboy | 11 | | EJS | https://code.google.com/archive/p/embeddedjavascript/ | MIT | LICENSE-MIT-EJS | 12 | | Flot | https://github.com/flot/flot | MIT | LICENSE-MIT-Flot | 13 | | Sammy | https://code.quirkey.com/sammy/ | MIT | LICENSE-MIT-Sammy | 14 | | jQuery | https://jquery.com/ | MIT | LICENSE-MIT-jQuery | 15 | 16 | If you have any questions regarding licensing, please contact us at info@rabbitmq.com. 17 | -------------------------------------------------------------------------------- /LICENSE-BSD-base64js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 Nick Galbreath 3 | * https://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | -------------------------------------------------------------------------------- /LICENSE-ISC-cowboy: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2017, Loïc Hoguin 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /LICENSE-MIT-EJS: -------------------------------------------------------------------------------- 1 | EJS - Embedded JavaScript 2 | 3 | Copyright (c) 2007 Edward Benson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-MIT-Flot: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2014 IOLA and Ole Laursen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /LICENSE-MIT-Sammy: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Aaron Quint, Quirkey NYC, LLC 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /LICENSE-MIT-jQuery: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 John Resig, https://jquery.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = rabbitmq_management 2 | PROJECT_DESCRIPTION = RabbitMQ Management Console 3 | PROJECT_MOD = rabbit_mgmt_app 4 | 5 | define PROJECT_ENV 6 | [ 7 | {http_log_dir, none}, 8 | {load_definitions, none}, 9 | {management_db_cache_multiplier, 5}, 10 | {process_stats_gc_timeout, 300000}, 11 | {stats_event_max_backlog, 250}, 12 | 13 | {cors_allow_origins, []}, 14 | {cors_max_age, 1800}, 15 | {content_security_policy, "script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'"} 16 | ] 17 | endef 18 | 19 | define PROJECT_APP_EXTRA_KEYS 20 | {broker_version_requirements, []} 21 | endef 22 | 23 | DEPS = rabbit_common rabbit amqp_client cowboy cowlib rabbitmq_web_dispatch rabbitmq_management_agent 24 | TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers proper 25 | LOCAL_DEPS += mnesia ranch ssl crypto public_key 26 | 27 | # FIXME: Add Ranch as a BUILD_DEPS to be sure the correct version is picked. 28 | # See rabbitmq-components.mk. 29 | BUILD_DEPS += ranch 30 | 31 | DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk 32 | DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk 33 | 34 | # FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be 35 | # reviewed and merged. 36 | 37 | ERLANG_MK_REPO = https://github.com/rabbitmq/erlang.mk.git 38 | ERLANG_MK_COMMIT = rabbitmq-tmp 39 | 40 | include rabbitmq-components.mk 41 | include erlang.mk 42 | 43 | # -------------------------------------------------------------------- 44 | # Distribution. 45 | # -------------------------------------------------------------------- 46 | 47 | list-dist-deps:: 48 | @echo bin/rabbitmqadmin 49 | 50 | prepare-dist:: 51 | $(verbose) sed 's/%%VSN%%/$(PROJECT_VERSION)/' bin/rabbitmqadmin \ 52 | > $(EZ_DIR)/priv/www/cli/rabbitmqadmin 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## This was migrated to https://github.com/rabbitmq/rabbitmq-server 3 | 4 | This repository has been moved to the main unified RabbitMQ "monorepo", including all open issues. You can find the source under [/deps/rabbitmq_management](https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/rabbitmq_management). 5 | All issues have been transferred. 6 | 7 | ## Overview 8 | 9 | [![Test Erlang 22.3](https://img.shields.io/github/workflow/status/rabbitmq/rabbitmq-management/Test%20-%20Erlang%2022.3/master?label=Erlang%2022.3)](https://github.com/rabbitmq/rabbitmq-management/actions?query=workflow%3A%22Test+-+Erlang+22.3%22+branch%3A%22master%22) 10 | [![Test Erlang 23](https://img.shields.io/github/workflow/status/rabbitmq/rabbitmq-management/Test%20-%20Erlang%2021.3/master?label=Erlang%2023.0)](https://github.com/rabbitmq/rabbitmq-management/actions?query=workflow%3A%22Test+-+Erlang+23.0%22+branch%3A%22master%22) 11 | 12 | # RabbitMQ Management Plugin 13 | 14 | This plugin provides a management UI and HTTP API for RabbitMQ. 15 | 16 | ## Installation 17 | 18 | This plugin is included in the RabbitMQ distribution. Like all [plugins](https://www.rabbitmq.com/plugins.html), 19 | it has to be [enabled](https://www.rabbitmq.com/plugins.html#basics) before it can be used. 20 | 21 | 22 | ## Documentation 23 | 24 | * [RabbitMQ management UI documentation](https://www.rabbitmq.com/management.html). 25 | * [HTTP API documentation](https://www.rabbitmq.com/management.html#http-api) and [reference](https://raw.githack.com/rabbitmq/rabbitmq-management/rabbitmq_v3_6_9/priv/www/api/index.html) 26 | 27 | ## Copyright 28 | 29 | (c) 2007-2020 VMware, Inc. or its affiliates. 30 | -------------------------------------------------------------------------------- /include/rabbit_mgmt.hrl: -------------------------------------------------------------------------------- 1 | %% The contents of this file are subject to the Mozilla Public License 2 | %% Version 1.1 (the "License"); you may not use this file except in 3 | %% compliance with the License. You may obtain a copy of the License at 4 | %% https://www.mozilla.org/MPL/ 5 | %% 6 | %% Software distributed under the License is distributed on an "AS IS" 7 | %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 8 | %% License for the specific language governing rights and limitations 9 | %% under the License. 10 | %% 11 | %% The Original Code is RabbitMQ Management Console. 12 | %% 13 | %% The Initial Developer of the Original Code is GoPivotal, Inc. 14 | %% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 15 | %% 16 | 17 | -define(AUTH_REALM, "Basic realm=\"RabbitMQ Management\""). 18 | 19 | -define(HEALTH_CHECK_FAILURE_STATUS, 503). 20 | -------------------------------------------------------------------------------- /priv/www/cli/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | rabbitmqadmin 7 | 12 | 13 | 14 |

rabbitmqadmin

15 | 16 |

17 | rabbitmqadmin is an HTTP API-based management tool. It uses the same API as RabbitMQ management UI 18 | and provides access to the subset of the functionality in the UI from the command line. 19 | It is not meant to be a replacement for rabbitmqctl 20 | as there are operations that HTTP API intentionally does not expose. 21 |

22 | 23 |

24 | To use it, download it from this node (right click, 25 | Save As), make sure it is executable, and drop it in your PATH. Note that 26 | many browsers will rename the 27 | file rabbitmqadmin.txt. rabbitmqadmin requires Python 28 | 2.6 or later (both 2.x and 3.x series are supported). 29 | To use rabbitmqadmin with HTTPS, Python 2.7.9 is the minimum supported version. 30 |

31 | 32 |

33 | See the 34 | rabbitmqadmin page on the website for more information on 35 | its use, or invoke rabbitmqadmin --help for usage 36 | instructions. 37 |

38 | 39 |

40 | Windows users will need to ensure Python is on 41 | their PATH, and invoke rabbitmqadmin as python.exe 42 | rabbitmqadmin. 43 |

44 | 45 | 46 | -------------------------------------------------------------------------------- /priv/www/css/evil.css: -------------------------------------------------------------------------------- 1 | #login { text-align: center; } 2 | -------------------------------------------------------------------------------- /priv/www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/favicon.ico -------------------------------------------------------------------------------- /priv/www/img/bg-binary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/bg-binary.png -------------------------------------------------------------------------------- /priv/www/img/bg-green-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/bg-green-dark.png -------------------------------------------------------------------------------- /priv/www/img/bg-red-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/bg-red-dark.png -------------------------------------------------------------------------------- /priv/www/img/bg-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/bg-red.png -------------------------------------------------------------------------------- /priv/www/img/bg-yellow-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/bg-yellow-dark.png -------------------------------------------------------------------------------- /priv/www/img/collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/collapse.png -------------------------------------------------------------------------------- /priv/www/img/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/priv/www/img/expand.png -------------------------------------------------------------------------------- /priv/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | RabbitMQ Management 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 58 | 59 | 63 | 64 | 65 | 66 |
67 |
68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /priv/www/js/singular/client_frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 21 | 22 | -------------------------------------------------------------------------------- /priv/www/js/singular/postaccess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /priv/www/js/singular/postauth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/404.ejs: -------------------------------------------------------------------------------- 1 |

Not found

2 | 3 |

The object you clicked on was not found; it may have been deleted on the server.

4 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/add-binding.ejs: -------------------------------------------------------------------------------- 1 | <% if (mode == 'queue') { %> 2 |

Add binding to this queue

3 | <% } else { %> 4 |

Add binding from this exchange

5 | <% } %> 6 |
7 | 8 | <% if (mode == 'queue') { %> 9 | 10 | <% } else { %> 11 | 12 | <% } %> 13 | 14 | <% if (mode == 'queue') { %> 15 | 16 | 19 | 24 | 25 | <% } else { %> 26 | 27 | 33 | 37 | 38 | <% } %> 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
17 | 18 | 20 | 21 | 22 | * 23 |
28 | : 32 | 34 | 35 | * 36 |
48 | 49 |
50 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/binary.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | if (binary == "not_available") { 3 | %> 4 |

5 | Binary statistics not available. 6 |

7 | <% } else { %> 8 | <% 9 | var sections = {'queue_procs' : ['queue', 'Classic queues (masters)'], 10 | 'queue_slave_procs' : ['queue', 'Classic queues (mirrors)'], 11 | 'quorum_queue_procs' : ['queue', 'Quorum queues'], 12 | 'stream_queue_procs' : ['queue', 'Stream queues'], 13 | 'stream_queue_replica_reader_procs' : ['queue', 'Stream queues (replica reader)'], 14 | 'stream_queue_coordinator_procs' : ['queue', 'Stream queues (coordinator)'], 15 | 'connection_readers' : ['conn', 'Connection readers'], 16 | 'connection_writers' : ['conn', 'Connection writers'], 17 | 'connection_channels' : ['conn', 'Connection channels'], 18 | 'connection_other' : ['conn', 'Connections (other)'], 19 | 'msg_index' : ['table', 'Message store index'], 20 | 'mgmt_db' : ['table', 'Management database'], 21 | 'plugins' : ['proc', 'Plugins'], 22 | 'other' : ['system', 'Other binary references']}; 23 | var total_out = []; 24 | %> 25 | <%= format('memory-bar', {sections: sections, memory: binary, total_out: total_out}) %> 26 |   27 |
28 | <% 29 | var key = [[{name: 'Queues', colour: 'queue', 30 | keys: [['queue_procs', 'queues'], 31 | ['queue_slave_procs', 'mirrors'], 32 | ['quorum_queue_procs', 'quorum'], 33 | ['stream_queue_procs', 'stream'], 34 | ['stream_queue_replica_reader_procs', 'stream replica reader'], 35 | ['stream_queue_coordinator_procs', 'stream coordinator']]}], 36 | 37 | [{name: 'Connections', colour: 'conn', 38 | keys: [['connection_readers', 'readers'], 39 | ['connection_writers', 'writers'], 40 | ['connection_channels', 'channels'], 41 | ['connection_other', 'other']]}], 42 | 43 | [{name: 'Tables', colour: 'table', 44 | keys: [['msg_index', 'message store index'], 45 | ['mgmt_db', 'management database']]}], 46 | 47 | [{name: 'Processes', colour: 'proc', 48 | keys: [['plugins', 'plugins']]}, 49 | {name: 'System', colour: 'system', 50 | keys: [['other', 'other']]}]]; 51 | %> 52 | <%= format('memory-table', {key: key, memory: binary}) %> 53 |
54 | 55 |
56 | Last updated: <%= fmt_date(new Date()) %>.
57 | Total referenced binaries at last update: <%= fmt_bytes(total_out[0]) %> 58 | 59 |
60 | 61 | <% } %> 62 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/bindings.ejs: -------------------------------------------------------------------------------- 1 | <%= maybe_truncate(bindings) %> 2 | <% if (bindings.length > 0) { %> 3 | 4 | 5 | 6 | <% if (mode == 'exchange_source') { %> 7 | 8 | <% } else { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | 15 | 16 | 17 | <% 18 | for (var i = 0; i < bindings.length; i++) { 19 | var binding = bindings[i]; 20 | %> 21 | > 22 | <% if (binding.source == '') { %> 23 | 26 | <% } else { %> 27 | <% if (mode == 'queue' || mode == 'exchange_destination') { %> 28 | 33 | <% } else if (binding.destination_type == 'exchange') { %> 34 | 39 | <% } else { %> 40 | 45 | <% } %> 46 | 47 | 48 | 58 | <% } %> 59 | 60 | <% } %> 61 | 62 |
ToFromRouting keyArguments
24 | (Default exchange binding) 25 | 29 | 30 | <%= link_exchange(binding.vhost, binding.source) %> 31 | 32 | 35 | 36 | <%= link_exchange(binding.vhost, binding.destination) %> 37 | 38 | 41 | 42 | <%= link_queue(binding.vhost, binding.destination) %> 43 | 44 | <%= fmt_string(binding.routing_key) %><%= fmt_table_short(binding.arguments) %> 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 |
63 | 64 | <% } else { %> 65 |

... no bindings ...

66 | <% } %> 67 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/channels.ejs: -------------------------------------------------------------------------------- 1 |

Channels

2 |
3 | <%= paginate_ui(channels, 'channels') %> 4 |
5 |
6 | <%= format('channels-list', {'channels': channels.items, 'mode': 'standalone'}) %> 7 |
8 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/cluster-name.ejs: -------------------------------------------------------------------------------- 1 |

Cluster name: <%= fmt_string(cluster_name.name) %>

2 | 3 |

4 | The cluster name can be used by clients to identify clusters over 5 | AMQP connections, and is used by the shovel and federation plugins 6 | to identify which clusters a message has been routed through. 7 |

8 |

9 | Note that the cluster name is announced to clients in the AMQP 10 | server properties; i.e. before authentication has taken 11 | place. Therefore it should not be considered secret. 12 |

13 |

14 | The cluster name is generated by default from the name of the first 15 | node in the cluster, but can be changed. 16 |

17 | 18 |
19 |

Change name

20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 |
*
28 | 29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/columns-options.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | var mode = span.attr('for'); 3 | %> 4 | 5 |
6 | 7 | 8 | 9 | 12 | 13 | <% for (var group in COLUMNS[mode]) { 14 | var options = COLUMNS[mode][group]; %> 15 | 16 | 17 | 22 | <% } %> 23 | 24 |
10 |

Columns for this table

11 |
18 | <% for (var i = 0; i < options.length; i++) { %> 19 | <%= fmt_checkbox(mode + '-' + options[i][0], options[i][1], get_pref('column-' + mode + '-' + options[i][0]) == 'true') %> 20 | <% } %> 21 |
25 |
26 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/consumers.ejs: -------------------------------------------------------------------------------- 1 | <% if (consumers.length > 0) { %> 2 | 3 | 4 | 5 | <% if (mode == 'queue') { %> 6 | 7 | 8 | <% } else { %> 9 | 10 | 11 | <% } %> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <% 21 | for (var i = 0; i < consumers.length; i++) { 22 | var consumer = consumers[i]; 23 | %> 24 | > 25 | <% if (mode == 'queue') { %> 26 | 27 | 28 | <% } else { %> 29 | 30 | 31 | <% } %> 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | <% } %> 40 |
ChannelConsumer tagConsumer tagQueueAck requiredExclusivePrefetch countActive Activity statusArguments
<%= link_channel(consumer.channel_details.name) %><%= fmt_string(consumer.consumer_tag) %><%= fmt_string(consumer.consumer_tag) %><%= link_queue(consumer.queue.vhost, consumer.queue.name) %><%= fmt_boolean(consumer.ack_required) %><%= fmt_boolean(consumer.exclusive) %><%= consumer.prefetch_count %><%= fmt_boolean(consumer.active) %><%= fmt_activity_status(consumer.activity_status) %><%= fmt_table_short(consumer.arguments) %>
41 | <% } else { %> 42 |

... no consumers ...

43 | <% } %> 44 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/exchange.ejs: -------------------------------------------------------------------------------- 1 |

Exchange: <%= fmt_exchange(highlight_extra_whitespace(exchange.name)) %><%= fmt_maybe_vhost(exchange.vhost) %>

2 | 3 |
4 |

Overview

5 |
6 | <% if (!disable_stats) { %> 7 | <% if (rates_mode != 'none') { %> 8 | <%= message_rates('msg-rates-x', exchange.message_stats) %> 9 | <% } %> 10 | <% } %> 11 |

Details

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
Type<%= fmt_exchange_type(exchange.type) %>
Features<%= fmt_features(exchange) %>
Policy<%= link_policy(exchange.vhost, exchange.policy) %>
26 |
27 |
28 | 29 | <% if (!disable_stats) { %> 30 | <% if (rates_mode == 'detailed') { %> 31 |
32 |

Message rates breakdown

33 |
34 | 35 | 36 | 42 | 48 | 49 |
37 | <%= format('msg-detail-publishes', 38 | {'mode': 'exchange-incoming', 39 | 'object': exchange.incoming, 40 | 'label': 'Incoming '}) %> 41 | 43 | <%= format('msg-detail-publishes', 44 | {'mode': 'exchange-outgoing', 45 | 'object': exchange.outgoing, 46 | 'label': 'Outgoing '}) %> 47 |
50 |
51 |
52 | <% } %> 53 | <% } %> 54 | 55 | 56 |
57 |

Bindings

58 |
59 | <% if (exchange.name == "") { %> 60 |

Default exchange

61 |

62 | The default exchange is implicitly bound to every queue, with a 63 | routing key equal to the queue name. It is not possible to 64 | explicitly bind to, or unbind from the default exchange. It also 65 | cannot be deleted. 66 |

67 | <% } else { %> 68 |
69 | <% if (bindings_destination.length > 0) { %> 70 | <%= format('bindings', {'mode': 'exchange_destination', 'bindings': bindings_destination}) %> 71 |

72 | <% } %> 73 |

This exchange

74 |

75 | <%= format('bindings', {'mode': 'exchange_source', 'bindings': bindings_source}) %> 76 |
77 | <%= format('add-binding', {'mode': 'exchange_source', 'parent': exchange}) %> 78 | <% } %> 79 |
80 |
81 | 82 | <% if (!exchange.internal) { %> 83 | <%= format('publish', {'mode': 'exchange', 'exchange': exchange}) %> 84 | <% } %> 85 | 86 | <% if (exchange.name != "") { %> 87 |
88 |

Delete this exchange

89 |
90 |
91 | 92 | 93 | 94 |
95 |
96 |
97 | <% } %> 98 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/feature-flags.ejs: -------------------------------------------------------------------------------- 1 |

Feature Flags

2 |
3 |

All Feature Flags

4 |
5 | <%= filter_ui(feature_flags) %> 6 |
7 | <% if (feature_flags.length > 0) { %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <% 18 | for (var i = 0; i < feature_flags.length; i++) { 19 | var feature_flag = feature_flags[i]; 20 | var state_color = "grey"; 21 | if (feature_flag.state == "enabled") { 22 | state_color = "green"; 23 | } else if (feature_flag.state == "disabled") { 24 | state_color = "yellow"; 25 | } else if (feature_flag.state == "unsupported") { 26 | state_color = "red"; 27 | } 28 | %> 29 | > 30 | 31 | 45 | 51 | 52 | <% } %> 53 | 54 |
<%= fmt_sort('Name', 'name') %><%= fmt_sort('State', 'state') %>Description
<%= fmt_string(feature_flag.name) %> 32 | <% if (feature_flag.state == "disabled") { %> 33 |
34 | 35 | 36 |
37 | <% } else { %> 38 | 41 | <%= fmt_string(feature_flag.state) %> 42 | 43 | <% } %> 44 |
46 |

<%= fmt_string(feature_flag.desc) %>

47 | <% if (feature_flag.doc_url) { %> 48 |

[Learn more]

49 | <% } %> 50 |
55 | <% } else { %> 56 |

... no feature_flags ...

57 | <% } %> 58 |
59 |
60 |
61 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/layout.ejs: -------------------------------------------------------------------------------- 1 | 44 |
45 |
46 | 59 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/list-exchanges.ejs: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/login.ejs: -------------------------------------------------------------------------------- 1 |
2 |

RabbitMQ logo

3 | 4 |
5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
*
*
 
20 |
21 |
22 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/login_uaa.ejs: -------------------------------------------------------------------------------- 1 |
2 |

RabbitMQ logo

3 | 4 |
5 |
6 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/memory-bar.ejs: -------------------------------------------------------------------------------- 1 |
2 | <% 3 | var width = 800; 4 | 5 | var pseudo_total = 0 6 | for (var section in sections) { 7 | pseudo_total += memory[section]; 8 | } 9 | 10 | total_out[0] = pseudo_total; 11 | 12 | for (var section in sections) { 13 | if (memory[section] > 0) { 14 | var section_width = Math.round(width * memory[section] / pseudo_total); 15 | %> 16 |
19 |
20 | <% 21 | } 22 | } 23 | %> 24 |
25 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/memory-table.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | for (var i in key) { 3 | %> 4 | 5 | <% 6 | for (var j in key[i]) { 7 | var group = key[i][j]; 8 | %> 9 | 10 | 11 | 25 | 26 | <% } %> 27 |
<%= group.name %>
12 | 13 | <% 14 | for (var k in group.keys) { 15 | var name = group.keys[k][0]; 16 | var label = group.keys[k][1]; 17 | %> 18 | 19 | 20 | 21 | 22 | <% } %> 23 |
<%= fmt_bytes(memory[name]) %><%= label %>
24 |
28 | <% } %> 29 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/messages.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | for (var i = 0; i < msgs.length; i++) { 3 | var msg = msgs[i]; 4 | %> 5 |
6 |

Message <%= i+1 %>

7 |

The server reported <%= msg.message_count %> messages remaining.

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 34 | 35 |
Exchange<%= fmt_exchange(msg.exchange) %>
Routing Key<%= fmt_string(msg.routing_key) %>
Redelivered<%= fmt_boolean(msg.redelivered) %>
Properties<%= fmt_table_short(msg.properties) %>
27 | Payload 28 | <%= msg.payload_bytes %> bytes 29 | Encoding: <%= msg.payload_encoding %> 30 | 32 |
<%= fmt_maybe_wrap(msg.payload, msg.payload_encoding) %>
33 |
36 |
37 | <% 38 | } 39 | %> 40 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/msg-detail-deliveries.ejs: -------------------------------------------------------------------------------- 1 |

Deliveries

2 | <% if (object && object.length > 0) { %> 3 | 4 | 5 | <% if (mode == 'queue') { %> 6 | 7 | <% } else { %> 8 | 9 | <% } %> 10 | 11 | 12 | 13 | <% 14 | for (var i = 0; i < object.length; i++) { 15 | var del = object[i]; 16 | %> 17 | > 18 | <% if (mode == 'queue') { %> 19 | 20 | <% } else { %> 21 | 22 | <% } %> 23 | 24 | 25 | 26 | <% } %> 27 |
ChannelQueuedeliver / getack
<%= link_channel(del.channel_details.name) %><%= link_queue(del.queue.vhost, del.queue.name) %><%= fmt_detail_rate(del.stats, 'deliver_get') %><%= fmt_detail_rate(del.stats, 'ack') %>
28 | <% } else { %> 29 |

... no deliveries ...

30 | <% } %> 31 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/msg-detail-publishes.ejs: -------------------------------------------------------------------------------- 1 |

<%= label %>

2 | <% if (object && object.length > 0) { %> 3 | <% 4 | var col_confirm = mode != 'exchange-outgoing'; 5 | %> 6 | 7 | 8 | <% if (mode == 'channel') { %> 9 | 10 | <% } else if (mode == 'exchange-incoming') { %> 11 | 12 | <% } else if (mode == 'exchange-outgoing') { %> 13 | 14 | <% } else { %> 15 | 16 | <% } %> 17 | 18 | <% if (col_confirm) { %> 19 | 20 | <% } %> 21 | 22 | <% 23 | for (var i = 0; i < object.length; i++) { 24 | var pub = object[i]; 25 | %> 26 | > 27 | 28 | <% if (mode == 'channel') { %> 29 | 30 | <% } else if (mode == 'exchange-incoming') { %> 31 | 32 | <% } else if (mode == 'exchange-outgoing') { %> 33 | 34 | <% } else { %> 35 | 36 | <% } %> 37 | 38 | <% if (col_confirm) { %> 39 | 40 | <% } %> 41 | 42 | <% } %> 43 |
ExchangeChannelQueueExchangepublishconfirm
<%= link_exchange(pub.exchange.vhost, pub.exchange.name) %><%= link_channel(pub.channel_details.name) %><%= link_queue(pub.queue.vhost, pub.queue.name) %><%= link_exchange(pub.exchange.vhost, pub.exchange.name) %><%= fmt_detail_rate(pub.stats, 'publish') %><%= fmt_detail_rate(pub.stats, 'confirm') %>
44 | <% } else { %> 45 |

... no publishes ...

46 | <% } %> 47 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/partition.ejs: -------------------------------------------------------------------------------- 1 |
2 | <% 3 | var partitions = []; 4 | for (var i = 0; i < nodes.length; i++) { 5 | var node = nodes[i]; 6 | if (node.partitions != undefined && node.partitions.length != 0) { 7 | partitions.push({'node': node.name, 8 | 'others': node.partitions}); 9 | } 10 | } 11 | if (partitions.length > 0) { 12 | %> 13 |

14 | Network partition detected

15 | Mnesia reports that this RabbitMQ cluster has experienced a 16 | network partition. There is a risk of losing data. Please read 17 | RabbitMQ 18 | documentation about network partitions and the possible solutions. 19 |

20 |

21 | The nature of the partition is as follows: 22 |

23 | 24 | 25 | 26 | 27 | 28 | <% 29 | for (var i = 0; i < partitions.length; i++) { 30 | var partition = partitions[i]; 31 | %> 32 | > 33 | 34 | 42 | 43 | <% } %> 44 |
NodeWas partitioned from
<%= fmt_node(partition.node) %> 35 | <% 36 | for (var j = 0; j < partition.others.length; j++) { 37 | var other = partition.others[j]; 38 | %> 39 | <%= other %>
40 | <% } %> 41 |
45 |

46 | While running in this partitioned state, changes (such as queue or 47 | exchange declaration and binding) which take place in one partition 48 | will not be visible to other partition(s). Other behaviour is not 49 | guaranteed. 50 |

51 |

52 | More information on 54 | network partitions. 55 |

56 | <% } %> 57 | <% 58 | var ticktime = null; 59 | var ticktimes_unequal = false; 60 | for (var i = 0; i < nodes.length; i++) { 61 | var node_ticktime = nodes[i].net_ticktime; 62 | if (node_ticktime != undefined) { 63 | 64 | if (ticktime != null && node_ticktime != ticktime) { 65 | ticktimes_unequal = true; 66 | } 67 | ticktime = nodes[i].net_ticktime; 68 | } 69 | } 70 | if (ticktimes_unequal) { 71 | %> 72 |

73 | The kernel net_ticktime values are set 74 | differently for different nodes in this cluster. 75 |

76 |

77 | The values are: 78 |

79 | 80 | 81 | <% 82 | for (var i = 0; i < nodes.length; i++) { 83 | %> 84 | > 85 | 86 | 87 | 88 | <% 89 | } 90 | %> 91 |
Nodenet_ticktime
<%= nodes[i].name %><%= nodes[i].net_ticktime %>
92 |

93 | This is a dangerous configuration; use of substantially 94 | unequal net_ticktime values can lead to partitions 95 | being falsely detected. 96 |

97 |

98 | More information on 100 | net_ticktime. 101 |

102 | <% 103 | } 104 | %> 105 |
106 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/permissions.ejs: -------------------------------------------------------------------------------- 1 |
2 |

Permissions

3 |
4 |

Current permissions

5 | <% if (permissions.length > 0) { %> 6 | 7 | 8 | 9 | <% if (mode == 'vhost') { %> 10 | 11 | <% } else { %> 12 | 13 | <% } %> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | <% 22 | for (var i = 0; i < permissions.length; i++) { 23 | var permission = permissions[i]; 24 | %> 25 | > 26 | <% if (mode == 'vhost') { %> 27 | 28 | <% } else { %> 29 | 30 | <% } %> 31 | 32 | 33 | 34 | 41 | 42 | <% } %> 43 | 44 |
UserVirtual hostConfigure regexpWrite regexpRead regexp
<%= link_user(permission.user) %><%= link_vhost(permission.vhost) %><%= fmt_string(permission.configure) %><%= fmt_string(permission.write) %><%= fmt_string(permission.read) %> 35 |
36 | 37 | 38 | 39 |
40 |
45 | <% } else { %> 46 |

... no permissions ...

47 | <% } %> 48 | 49 |

Set permission

50 |
51 | 52 | 53 | <% if (mode == 'vhost') { %> 54 | 55 | 63 | <% } else { %> 64 | 65 | 73 | <% } %> 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
User 56 | 57 | 62 | 66 | 67 | 72 |
88 | 89 |
90 |
91 |
92 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/policy.ejs: -------------------------------------------------------------------------------- 1 |

Policy: <%= fmt_string(policy.name) %><%= fmt_maybe_vhost(policy.vhost) %>

2 | 3 |
4 |

Overview

5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
Pattern<%= fmt_string(policy.pattern) %>
Apply to<%= fmt_string(policy['apply-to']) %>
Definition<%= fmt_table_short(policy.definition) %>
Priority<%= fmt_string(policy.priority) %>
24 |
25 |
26 | 27 |
28 |

Delete this policy

29 |
30 |
31 | 32 | 33 | 34 | 35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/popup.ejs: -------------------------------------------------------------------------------- 1 |
2 | <%= text %> 3 |
4 |
5 | Close 6 |
7 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/publish.ejs: -------------------------------------------------------------------------------- 1 |
2 |

Publish message

3 |
4 |
5 | <% if (mode == 'queue') { %> 6 | 7 | 8 | <% } else { %> 9 | 10 | 11 | <% } %> 12 | 13 | 14 | <% if (mode == 'queue') { %> 15 | 16 | 17 | 18 | <% } else { %> 19 | 20 | 21 | 22 | 23 | <% } %> 24 | <% if (mode == 'queue' && is_classic(queue)) { %> 25 | 26 | 27 | 33 | 34 | <% } else { %> 35 | 36 | <% } %> 37 | 38 | 44 | 47 | 48 | 49 | 55 | 58 | 59 | 60 | 61 | 62 | 63 |
Message will be published to the default exchange with routing key <%= fmt_string(queue.name) %>, routing it to this queue.
28 | 32 |
39 | 43 | 45 |
46 |
50 | 54 | 56 |
57 |
64 | 65 |
66 |
67 |
68 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/rate-options.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | var id = span.attr('for'); 3 | var mode = get_pref('rate-mode-' + id); 4 | var size = get_pref('chart-size-' + id); 5 | var range_pref = get_pref('chart-range'); 6 | %> 7 | 8 |
9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 54 | 55 |
13 |

This time series

14 |
19 | <%= fmt_radio('mode', 'Chart', 'chart', mode) %> 20 | <%= fmt_radio('mode', 'Current value', 'curr', mode) %> 21 | <% if (id != 'node-stats') { %> 22 | <%= fmt_radio('mode', 'Moving average', 'avg', mode) %> 23 | <% } %> 24 |
29 | <%= fmt_radio('size', 'Small', 'small', size) %> 30 | <%= fmt_radio('size', 'Medium', 'medium', size) %> 31 | <%= fmt_radio('size', 'Large', 'large', size) %> 32 |
36 |

All time series

37 |
42 | <% 43 | var range_type = get_chart_range_type(id); 44 | for (var i = 0; i < CHART_RANGES[range_type].length; ++i) { 45 | var data = CHART_RANGES[range_type][i]; 46 | var range = data[0]; 47 | var desc = data[1]; 48 | %> 49 | <%= fmt_radio('range', desc, range, range_pref) %> 50 | <% 51 | } 52 | %> 53 |
56 |
57 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/registry.ejs: -------------------------------------------------------------------------------- 1 | <% if (node.running) { %> 2 | 3 | 4 | 5 | 6 | <% if (show_enabled) { %> 7 | 8 | <% } %> 9 | 10 | <% 11 | for (var i = 0; i < list.length; i++) { 12 | var item = list[i]; 13 | %> 14 | > 15 | 16 | 17 | <% if (show_enabled) { %> 18 | 19 | <% } %> 20 | 21 | <% } %> 22 |
NameDescriptionEnabled
<%= fmt_string(item.name) %><%= fmt_string(item.description) %><%= fmt_boolean(item.enabled) %>
23 | <% } else {%> 24 |

...node not running...

25 | <% } %> 26 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/status.ejs: -------------------------------------------------------------------------------- 1 | <%= text %> 2 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/vhost.ejs: -------------------------------------------------------------------------------- 1 |

Virtual Host: <%= fmt_string(vhost.name) %>

2 | 3 | <% if (permissions.length == 0) { %> 4 |

5 | No users have permission to access this virtual host.
6 | Use "Set Permission" below to grant users permission to access this virtual host. 7 |

8 | <% } %> 9 | 10 | <% if (!disable_stats) { %> 11 |
12 |

Overview

13 |
14 | <%= queue_lengths('lengths-vhost', vhost) %> 15 | <% if (rates_mode != 'none') { %> 16 | <%= message_rates('msg-rates-vhost', vhost.message_stats) %> 17 | <% } %> 18 | <%= data_rates('data-rates-vhost', vhost, 'Data rates') %> 19 |

Details

20 | 21 | 22 | 23 | 24 | 25 | 26 | 44 | 45 |
Tracing enabled:<%= fmt_boolean(vhost.tracing) %>
State: 27 | 28 | <% for (var node in vhost.cluster_state) { %> 29 | 30 | 31 | 40 | 41 | <% } %> 42 |
<%= fmt_escape_html(node) %> :<%= vhost.cluster_state[node] %> 32 | <% if (vhost.cluster_state[node] == "stopped"){ %> 33 |
34 | 35 | 36 | 37 |
38 | <% } %> 39 |
43 |
46 |
47 |
48 | <% } %> 49 | 50 | <%= format('permissions', {'mode': 'vhost', 'permissions': permissions, 'users': users, 'parent': vhost}) %> 51 | 52 | <%= format('topic-permissions', {'mode': 'vhost', 'topic_permissions': topic_permissions, 'users':users, 'parent': vhost, 'exchanges': exchanges}) %> 53 | 54 |
55 |

Delete this vhost

56 |
57 |
58 | 59 | 60 |
61 |
62 |
63 | -------------------------------------------------------------------------------- /scripts/seed.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # use admin context to add user and client 4 | uaac token client get admin -s adminsecret 5 | 6 | uaac user add rabbit_user -p rabbit_password --email rabbit_user@example.com 7 | 8 | # these groups will end up in the scope of the users 9 | uaac group add "rabbitmq.read:*/*" 10 | uaac group add "rabbitmq.write:*/*" 11 | uaac group add "rabbitmq.configure:*/*" 12 | uaac group add "rabbitmq.tag:management" 13 | uaac group add "rabbitmq.tag:administrator" 14 | 15 | uaac member add "rabbitmq.read:*/*" rabbit_user 16 | uaac member add "rabbitmq.write:*/*" rabbit_user 17 | uaac member add "rabbitmq.configure:*/*" rabbit_user 18 | uaac member add "rabbitmq.tag:management" rabbit_user 19 | uaac member add "rabbitmq.tag:administrator" rabbit_user 20 | 21 | # add the client for the management plugin. It has the implicit grant type. 22 | # add e.g. --access_token_validity 60 --refresh_token_validity 3600 to experiment with token validity 23 | uaac client add rabbit_user_client \ 24 | --name rabbit_user_client \ 25 | --secret '' \ 26 | --scope 'rabbitmq.* openid' \ 27 | --authorized_grant_types implicit \ 28 | --autoapprove true \ 29 | --redirect_uri 'http://localhost:15672/**' 30 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_csp.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 | %% Sets CSP header(s) on the response if configured, 9 | %% see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP. 10 | 11 | -module(rabbit_mgmt_csp). 12 | 13 | -export([set_headers/1]). 14 | 15 | -define(CSP_HEADER, <<"content-security-policy">>). 16 | 17 | %% 18 | %% API 19 | %% 20 | 21 | set_headers(ReqData) -> 22 | case application:get_env(rabbitmq_management, content_security_policy) of 23 | undefined -> ReqData; 24 | {ok, Value} -> 25 | cowboy_req:set_resp_header(?CSP_HEADER, 26 | rabbit_data_coercion:to_binary(Value), 27 | ReqData) 28 | end. 29 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_db_cache_sup.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 | -module(rabbit_mgmt_db_cache_sup). 8 | 9 | -behaviour(supervisor). 10 | 11 | %% API functions 12 | -export([start_link/0]). 13 | 14 | %% Supervisor callbacks 15 | -export([init/1]). 16 | 17 | %%%=================================================================== 18 | %%% API functions 19 | %%%=================================================================== 20 | 21 | start_link() -> 22 | supervisor:start_link({local, ?MODULE}, ?MODULE, []). 23 | 24 | %%%=================================================================== 25 | %%% Supervisor callbacks 26 | %%%=================================================================== 27 | 28 | init([]) -> 29 | {ok, {{one_for_one, 5, 10}, []}}. 30 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_extension.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_extension). 9 | 10 | %% Return a Cowboy dispatcher table to integrate 11 | -callback dispatcher() -> [{string(), atom(), [atom()]}]. 12 | 13 | %% Return a proplist of information for the web UI to integrate 14 | %% this extension. Currently the proplist should have one key, 15 | %% 'javascript', the name of a javascript file to load and run. 16 | -callback web_ui() -> proplists:proplist(). 17 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_headers.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 | %% This module contains helper functions that control 9 | %% response headers related to CORS, CSP, HSTS and so on. 10 | -module(rabbit_mgmt_headers). 11 | 12 | -export([set_common_permission_headers/2]). 13 | -export([set_cors_headers/2, set_hsts_headers/2, set_csp_headers/2]). 14 | 15 | %% 16 | %% API 17 | %% 18 | 19 | set_cors_headers(ReqData, Module) -> 20 | rabbit_mgmt_cors:set_headers(ReqData, Module). 21 | 22 | set_hsts_headers(ReqData, _Module) -> 23 | rabbit_mgmt_hsts:set_headers(ReqData). 24 | 25 | set_csp_headers(ReqData, _Module) -> 26 | rabbit_mgmt_csp:set_headers(ReqData). 27 | 28 | set_common_permission_headers(ReqData0, EndpointModule) -> 29 | lists:foldl(fun(Fun, ReqData) -> 30 | Fun(ReqData, EndpointModule) 31 | end, ReqData0, 32 | [fun set_csp_headers/2, 33 | fun set_hsts_headers/2, 34 | fun set_cors_headers/2]). 35 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_hsts.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 | %% Sets HSTS header(s) on the response if configured, 9 | %% see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security. 10 | 11 | -module(rabbit_mgmt_hsts). 12 | 13 | -export([set_headers/1]). 14 | 15 | -define(HSTS_HEADER, <<"strict-transport-security">>). 16 | 17 | %% 18 | %% API 19 | %% 20 | 21 | set_headers(ReqData) -> 22 | case application:get_env(rabbitmq_management, strict_transport_security) of 23 | undefined -> ReqData; 24 | {ok, Value} -> 25 | cowboy_req:set_resp_header(?HSTS_HEADER, 26 | rabbit_data_coercion:to_binary(Value), 27 | ReqData) 28 | end. 29 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_load_definitions.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_mgmt_load_definitions). 9 | 10 | -include_lib("rabbit_common/include/rabbit.hrl"). 11 | 12 | -export([boot/0, maybe_load_definitions/0, maybe_load_definitions_from/2]). 13 | 14 | %% This module exists for backwards compatibility only. 15 | %% Definition import functionality is now a core server feature. 16 | 17 | boot() -> 18 | rabbit_log:debug("Will import definitions file from management.load_definitions"), 19 | rabbit_definitions:maybe_load_definitions(rabbitmq_management, load_definitions). 20 | 21 | maybe_load_definitions() -> 22 | rabbit_definitions:maybe_load_definitions(). 23 | 24 | maybe_load_definitions_from(true, Dir) -> 25 | rabbit_definitions:maybe_load_definitions_from(true, Dir); 26 | maybe_load_definitions_from(false, File) -> 27 | rabbit_definitions:maybe_load_definitions_from(false, File). 28 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_reset_handler.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 | %% When management extensions are enabled and/or disabled at runtime, the 9 | %% management web dispatch mechanism needs to be reset. This event handler 10 | %% deals with responding to 'plugins_changed' events for management 11 | %% extensions, forcing a reset when necessary. 12 | 13 | -module(rabbit_mgmt_reset_handler). 14 | 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | -behaviour(gen_event). 18 | 19 | -export([init/1, handle_call/2, handle_event/2, handle_info/2, 20 | terminate/2, code_change/3]). 21 | 22 | -rabbit_boot_step({?MODULE, 23 | [{description, "management extension handling"}, 24 | {mfa, {gen_event, add_handler, 25 | [rabbit_event, ?MODULE, []]}}, 26 | {cleanup, {gen_event, delete_handler, 27 | [rabbit_event, ?MODULE, []]}}, 28 | {requires, rabbit_event}, 29 | {enables, recovery}]}). 30 | 31 | -import(rabbit_misc, [pget/2, pget/3]). 32 | 33 | %%---------------------------------------------------------------------------- 34 | 35 | init([]) -> 36 | {ok, []}. 37 | 38 | handle_call(_Request, State) -> 39 | {ok, not_understood, State}. 40 | 41 | handle_event(#event{type = plugins_changed, props = Details}, State) -> 42 | Enabled = pget(enabled, Details), 43 | Disabled = pget(disabled, Details), 44 | case extensions_changed(Enabled ++ Disabled) of 45 | true -> 46 | _ = rabbit_mgmt_app:reset_dispatcher(Disabled), 47 | ok; 48 | false -> ok 49 | end, 50 | {ok, State}; 51 | 52 | handle_event(_Event, State) -> 53 | {ok, State}. 54 | 55 | handle_info(_Info, State) -> 56 | {ok, State}. 57 | 58 | terminate(_Arg, _State) -> 59 | ok. 60 | 61 | code_change(_OldVsn, State, _Extra) -> 62 | {ok, State}. 63 | 64 | %%---------------------------------------------------------------------------- 65 | 66 | %% We explicitly ignore the case where management has been 67 | %% started/stopped since the dispatcher is either freshly created or 68 | %% about to vanish. 69 | extensions_changed(Apps) -> 70 | not lists:member(rabbitmq_management, Apps) andalso 71 | lists:any(fun is_extension/1, [Mod || App <- Apps, Mod <- mods(App)]). 72 | 73 | is_extension(Mod) -> 74 | lists:member(rabbit_mgmt_extension, 75 | pget(behaviour, Mod:module_info(attributes), [])). 76 | 77 | mods(App) -> 78 | {ok, Modules} = application:get_key(App, modules), 79 | Modules. 80 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_sup.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_sup). 9 | 10 | -behaviour(supervisor). 11 | 12 | -export([init/1]). 13 | -export([start_link/0]). 14 | -export([setup_wm_logging/0]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_metrics.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | -include_lib("rabbit_common/include/rabbit_core_metrics.hrl"). 19 | 20 | init([]) -> 21 | DB = {rabbit_mgmt_db, {rabbit_mgmt_db, start_link, []}, 22 | permanent, ?WORKER_WAIT, worker, [rabbit_mgmt_db]}, 23 | WP = {management_worker_pool_sup, {worker_pool_sup, start_link, [3, management_worker_pool]}, 24 | permanent, ?SUPERVISOR_WAIT, supervisor, [management_worker_pool_sup]}, 25 | DBC = {rabbit_mgmt_db_cache_sup, {rabbit_mgmt_db_cache_sup, start_link, []}, 26 | permanent, ?SUPERVISOR_WAIT, supervisor, [rabbit_mgmt_db_cache_sup]}, 27 | {ok, {{one_for_one, 100, 1}, [DB, WP, DBC]}}. 28 | 29 | start_link() -> 30 | Res = supervisor:start_link({local, ?MODULE}, ?MODULE, []), 31 | setup_wm_logging(), 32 | Res. 33 | 34 | %% While the project has switched to Cowboy for HTTP handling, we still use 35 | %% the logger from Webmachine; at least until RabbitMQ switches to Lager or 36 | %% similar. 37 | setup_wm_logging() -> 38 | {ok, LogDir} = application:get_env(rabbitmq_management, http_log_dir), 39 | case LogDir of 40 | none -> ok; 41 | _ -> webmachine_log:add_handler(webmachine_log_handler, [LogDir]) 42 | end. 43 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_sup_sup.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_mgmt_sup_sup). 9 | 10 | -behaviour(supervisor2). 11 | 12 | -export([init/1]). 13 | -export([start_link/0, start_child/0]). 14 | 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | start_child() -> 18 | supervisor2:start_child(?MODULE, sup()). 19 | 20 | sup() -> 21 | {rabbit_mgmt_sup, {rabbit_mgmt_sup, start_link, []}, 22 | temporary, ?SUPERVISOR_WAIT, supervisor, [rabbit_mgmt_sup]}. 23 | 24 | init([]) -> 25 | {ok, {{one_for_one, 0, 1}, [sup()]}}. 26 | 27 | start_link() -> 28 | supervisor2:start_link({local, ?MODULE}, ?MODULE, []). 29 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_aliveness_test.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_mgmt_wm_aliveness_test). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include("rabbit_mgmt.hrl"). 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("amqp_client/include/amqp_client.hrl"). 17 | 18 | -define(QUEUE, <<"aliveness-test">>). 19 | 20 | %%-------------------------------------------------------------------- 21 | 22 | init(Req, _State) -> 23 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 24 | 25 | variances(Req, Context) -> 26 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 27 | 28 | content_types_provided(ReqData, Context) -> 29 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 30 | 31 | resource_exists(ReqData, Context) -> 32 | {case rabbit_mgmt_util:vhost(ReqData) of 33 | not_found -> false; 34 | _ -> true 35 | end, ReqData, Context}. 36 | 37 | to_json(ReqData, Context) -> 38 | rabbit_mgmt_util:with_channel( 39 | rabbit_mgmt_util:vhost(ReqData), 40 | ReqData, 41 | Context, 42 | fun(Ch) -> 43 | #'queue.declare_ok'{queue = ?QUEUE} = amqp_channel:call(Ch, #'queue.declare'{ 44 | queue = ?QUEUE 45 | }), 46 | ok = amqp_channel:call(Ch, #'basic.publish'{routing_key = ?QUEUE}, #amqp_msg{ 47 | payload = <<"test_message">> 48 | }), 49 | case amqp_channel:call(Ch, #'basic.get'{queue = ?QUEUE, no_ack = true}) of 50 | {#'basic.get_ok'{}, _} -> 51 | %% Don't delete the queue. If this is pinged every few 52 | %% seconds we don't want to create a mnesia transaction 53 | %% each time. 54 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 55 | #'basic.get_empty'{} -> 56 | Reason = <<"aliveness-test queue is empty">>, 57 | failure(Reason, ReqData, Context); 58 | Error -> 59 | Reason = rabbit_data_coercion:to_binary(Error), 60 | failure(Reason, ReqData, Context) 61 | end 62 | end 63 | ). 64 | 65 | failure(Reason, ReqData0, Context0) -> 66 | Body = #{status => failed, reason => Reason}, 67 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData0, Context0), 68 | {stop, cowboy_req:reply(?HEALTH_CHECK_FAILURE_STATUS, #{}, Response, ReqData1), Context1}. 69 | 70 | is_authorized(ReqData, Context) -> 71 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 72 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_auth.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_mgmt_wm_auth). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([variances/2]). 12 | 13 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 14 | -include_lib("rabbit_common/include/rabbit.hrl"). 15 | 16 | %%-------------------------------------------------------------------- 17 | 18 | init(Req, _State) -> 19 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 20 | 21 | variances(Req, Context) -> 22 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 23 | 24 | content_types_provided(ReqData, Context) -> 25 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 26 | 27 | to_json(ReqData, Context) -> 28 | EnableUAA = application:get_env(rabbitmq_management, enable_uaa, false), 29 | Data = case EnableUAA of 30 | true -> 31 | UAAClientId = application:get_env(rabbitmq_management, uaa_client_id, ""), 32 | UAALocation = application:get_env(rabbitmq_management, uaa_location, ""), 33 | case is_invalid([UAAClientId, UAALocation]) of 34 | true -> 35 | rabbit_log:warning("Disabling OAuth 2 authorization, relevant configuration settings are missing", []), 36 | [{enable_uaa, false}, {uaa_client_id, <<>>}, {uaa_location, <<>>}]; 37 | false -> 38 | [{enable_uaa, true}, 39 | {uaa_client_id, rabbit_data_coercion:to_binary(UAAClientId)}, 40 | {uaa_location, rabbit_data_coercion:to_binary(UAALocation)}] 41 | end; 42 | false -> 43 | [{enable_uaa, false}, {uaa_client_id, <<>>}, {uaa_location, <<>>}] 44 | end, 45 | rabbit_mgmt_util:reply(Data, ReqData, Context). 46 | 47 | is_authorized(ReqData, Context) -> 48 | {true, ReqData, Context}. 49 | 50 | is_invalid(List) -> 51 | lists:any(fun(V) -> V == "" end, List). 52 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_auth_attempts.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_mgmt_wm_auth_attempts). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, allowed_methods/2, is_authorized/2, 11 | delete_resource/2, resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -import(rabbit_misc, [pget/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | init(Req, [Mode]) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), 22 | {Mode, #context{}}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_provided(ReqData, Context) -> 28 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 29 | 30 | allowed_methods(ReqData, Context) -> 31 | {[<<"HEAD">>, <<"GET">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 32 | 33 | resource_exists(ReqData, Context) -> 34 | {node_exists(ReqData, get_node(ReqData)), ReqData, Context}. 35 | 36 | to_json(ReqData, {Mode, Context}) -> 37 | rabbit_mgmt_util:reply(augment(Mode, ReqData), ReqData, Context). 38 | 39 | is_authorized(ReqData, {Mode, Context}) -> 40 | {Res, Req2, Context2} = rabbit_mgmt_util:is_authorized_monitor(ReqData, Context), 41 | {Res, Req2, {Mode, Context2}}. 42 | 43 | delete_resource(ReqData, Context) -> 44 | Node = get_node(ReqData), 45 | case node_exists(ReqData, Node) of 46 | false -> 47 | {false, ReqData, Context}; 48 | true -> 49 | case rpc:call(Node, rabbit_core_metrics, reset_auth_attempt_metrics, [], infinity) of 50 | {badrpc, _} -> {false, ReqData, Context}; 51 | ok -> {true, ReqData, Context} 52 | end 53 | end. 54 | %%-------------------------------------------------------------------- 55 | get_node(ReqData) -> 56 | list_to_atom(binary_to_list(rabbit_mgmt_util:id(node, ReqData))). 57 | 58 | node_exists(ReqData, Node) -> 59 | case [N || N <- rabbit_mgmt_wm_nodes:all_nodes(ReqData), 60 | proplists:get_value(name, N) == Node] of 61 | [] -> false; 62 | [_] -> true 63 | end. 64 | 65 | augment(Mode, ReqData) -> 66 | Node = get_node(ReqData), 67 | case node_exists(ReqData, Node) of 68 | false -> 69 | not_found; 70 | true -> 71 | Fun = case Mode of 72 | all -> get_auth_attempts; 73 | by_source -> get_auth_attempts_by_source 74 | end, 75 | case rpc:call(Node, rabbit_core_metrics, Fun, [], infinity) of 76 | {badrpc, _} -> not_available; 77 | Result -> Result 78 | end 79 | end. 80 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_channel.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_mgmt_wm_channel). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | case rabbit_mgmt_util:disable_stats(ReqData) of 30 | false -> 31 | case channel(ReqData) of 32 | not_found -> {false, ReqData, Context}; 33 | _Conn -> {true, ReqData, Context} 34 | end; 35 | true -> 36 | {false, ReqData, Context} 37 | end. 38 | 39 | to_json(ReqData, Context) -> 40 | case rabbit_mgmt_util:disable_stats(ReqData) of 41 | false -> 42 | Payload = rabbit_mgmt_format:clean_consumer_details( 43 | rabbit_mgmt_format:strip_pids(channel(ReqData))), 44 | rabbit_mgmt_util:reply( 45 | maps:from_list(Payload), 46 | ReqData, Context); 47 | true -> 48 | rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context) 49 | end. 50 | 51 | is_authorized(ReqData, Context) -> 52 | case rabbit_mgmt_util:disable_stats(ReqData) of 53 | false -> 54 | try 55 | rabbit_mgmt_util:is_authorized_user(ReqData, Context, channel(ReqData)) 56 | catch 57 | {error, invalid_range_parameters, Reason} -> 58 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 59 | end; 60 | true -> 61 | rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context) 62 | end. 63 | 64 | %%-------------------------------------------------------------------- 65 | 66 | channel(ReqData) -> 67 | rabbit_mgmt_db:get_channel(rabbit_mgmt_util:id(channel, ReqData), 68 | rabbit_mgmt_util:range(ReqData)). 69 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_channels.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_mgmt_wm_channels). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | augmented/2]). 12 | -export([variances/2]). 13 | 14 | -import(rabbit_misc, [pget/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_provided(ReqData, Context) -> 28 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 29 | 30 | to_json(ReqData, Context) -> 31 | case rabbit_mgmt_util:disable_stats(ReqData) of 32 | false -> 33 | try 34 | rabbit_mgmt_util:reply_list_or_paginate(augmented(ReqData, Context), 35 | ReqData, Context) 36 | catch 37 | {error, invalid_range_parameters, Reason} -> 38 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 39 | end; 40 | true -> 41 | rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context) 42 | end. 43 | 44 | is_authorized(ReqData, Context) -> 45 | rabbit_mgmt_util:is_authorized(ReqData, Context). 46 | 47 | augmented(ReqData, Context) -> 48 | rabbit_mgmt_util:filter_conn_ch_list( 49 | rabbit_mgmt_db:get_all_channels( 50 | rabbit_mgmt_util:range(ReqData)), ReqData, Context). 51 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_channels_vhost.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) 2010-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_channels_vhost). 9 | 10 | %% Lists channels in a vhost 11 | 12 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 13 | augmented/2, resource_exists/2]). 14 | -export([variances/2]). 15 | 16 | -import(rabbit_misc, [pget/2]). 17 | 18 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 19 | -include_lib("rabbit_common/include/rabbit.hrl"). 20 | 21 | %%-------------------------------------------------------------------- 22 | 23 | init(Req, _State) -> 24 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | resource_exists(ReqData, Context) -> 33 | {rabbit_vhost:exists(rabbit_mgmt_util:id(vhost, ReqData)), ReqData, Context}. 34 | 35 | to_json(ReqData, Context) -> 36 | case rabbit_mgmt_util:disable_stats(ReqData) of 37 | false -> 38 | try 39 | rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context) 40 | catch 41 | {error, invalid_range_parameters, Reason} -> 42 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 43 | end; 44 | true -> 45 | rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context) 46 | end. 47 | 48 | is_authorized(ReqData, Context) -> 49 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 50 | 51 | augmented(ReqData, Context) -> 52 | rabbit_mgmt_util:filter_conn_ch_list( 53 | rabbit_mgmt_db:get_all_channels( 54 | rabbit_mgmt_util:range(ReqData)), ReqData, Context). 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_cluster_name.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_mgmt_wm_cluster_name). 9 | 10 | -export([init/2, resource_exists/2, to_json/2, 11 | content_types_provided/2, content_types_accepted/2, 12 | is_authorized/2, allowed_methods/2, accept_content/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("amqp_client/include/amqp_client.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | content_types_accepted(ReqData, Context) -> 30 | {[{'*', accept_content}], ReqData, Context}. 31 | 32 | allowed_methods(ReqData, Context) -> 33 | {[<<"HEAD">>, <<"GET">>, <<"PUT">>, <<"OPTIONS">>], ReqData, Context}. 34 | 35 | resource_exists(ReqData, Context) -> 36 | {true, ReqData, Context}. 37 | 38 | to_json(ReqData, Context) -> 39 | rabbit_mgmt_util:reply( 40 | [{name, rabbit_nodes:cluster_name()}], ReqData, Context). 41 | 42 | accept_content(ReqData0, Context = #context{user = #user{username = Username}}) -> 43 | rabbit_mgmt_util:with_decode( 44 | [name], ReqData0, Context, fun([Name], _, ReqData) -> 45 | rabbit_nodes:set_cluster_name( 46 | as_binary(Name), Username), 47 | {true, ReqData, Context} 48 | end). 49 | 50 | is_authorized(ReqData, Context) -> 51 | case cowboy_req:method(ReqData) of 52 | <<"PUT">> -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context); 53 | _ -> rabbit_mgmt_util:is_authorized(ReqData, Context) 54 | end. 55 | 56 | as_binary(Val) when is_binary(Val) -> 57 | Val; 58 | as_binary(Val) when is_list(Val) -> 59 | list_to_binary(Val). 60 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_connection_channels.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_mgmt_wm_connection_channels). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | case rabbit_mgmt_wm_connection:conn(ReqData) of 30 | error -> {false, ReqData, Context}; 31 | _Conn -> {true, ReqData, Context} 32 | end. 33 | 34 | to_json(ReqData, Context) -> 35 | Name = proplists:get_value(name, rabbit_mgmt_wm_connection:conn(ReqData)), 36 | Chs = rabbit_mgmt_db:get_all_channels(rabbit_mgmt_util:range(ReqData)), 37 | rabbit_mgmt_util:reply_list( 38 | [Ch || Ch <- rabbit_mgmt_util:filter_conn_ch_list(Chs, ReqData, Context), 39 | conn_name(Ch) =:= Name], 40 | ReqData, Context). 41 | 42 | is_authorized(ReqData, Context) -> 43 | try 44 | rabbit_mgmt_util:is_authorized_user( 45 | ReqData, Context, rabbit_mgmt_wm_connection:conn(ReqData)) 46 | catch 47 | {error, invalid_range_parameters, Reason} -> 48 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 49 | end. 50 | 51 | %%-------------------------------------------------------------------- 52 | 53 | conn_name(Ch) -> 54 | proplists:get_value(name, proplists:get_value(connection_details, Ch)). 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_connections.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_mgmt_wm_connections). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | augmented/2]). 12 | -export([variances/2]). 13 | 14 | -import(rabbit_misc, [pget/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_provided(ReqData, Context) -> 28 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 29 | 30 | to_json(ReqData, Context) -> 31 | try 32 | Connections = do_connections_query(ReqData, Context), 33 | rabbit_mgmt_util:reply_list_or_paginate(Connections, ReqData, Context) 34 | catch 35 | {error, invalid_range_parameters, Reason} -> 36 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 37 | end. 38 | 39 | is_authorized(ReqData, Context) -> 40 | rabbit_mgmt_util:is_authorized(ReqData, Context). 41 | 42 | augmented(ReqData, Context) -> 43 | rabbit_mgmt_util:filter_conn_ch_list( 44 | rabbit_mgmt_db:get_all_connections( 45 | rabbit_mgmt_util:range_ceil(ReqData)), ReqData, Context). 46 | 47 | do_connections_query(ReqData, Context) -> 48 | case rabbit_mgmt_util:disable_stats(ReqData) of 49 | false -> 50 | augmented(ReqData, Context); 51 | true -> 52 | rabbit_mgmt_util:filter_tracked_conn_list(rabbit_connection_tracking:list(), 53 | ReqData, Context) 54 | end. 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_connections_vhost.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) 2010-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_connections_vhost). 9 | 10 | %% Lists connections in a vhost 11 | 12 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 13 | augmented/2, resource_exists/2]). 14 | -export([variances/2]). 15 | 16 | -import(rabbit_misc, [pget/2]). 17 | 18 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 19 | -include_lib("rabbit_common/include/rabbit.hrl"). 20 | 21 | %%-------------------------------------------------------------------- 22 | 23 | init(Req, _State) -> 24 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | resource_exists(ReqData, Context) -> 33 | {rabbit_vhost:exists(rabbit_mgmt_util:id(vhost, ReqData)), ReqData, Context}. 34 | 35 | to_json(ReqData, Context) -> 36 | try 37 | rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context) 38 | catch 39 | {error, invalid_range_parameters, Reason} -> 40 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 41 | end. 42 | 43 | is_authorized(ReqData, Context) -> 44 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 45 | 46 | augmented(ReqData, Context) -> 47 | rabbit_mgmt_util:filter_conn_ch_list( 48 | rabbit_mgmt_db:get_all_connections( 49 | rabbit_mgmt_util:range_ceil(ReqData)), ReqData, Context). 50 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_consumers.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 | -module(rabbit_mgmt_wm_consumers). 8 | 9 | -export([init/2, to_json/2, content_types_provided/2, resource_exists/2, 10 | is_authorized/2]). 11 | -export([variances/2]). 12 | 13 | -import(rabbit_misc, [pget/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("rabbit_common/include/rabbit.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {case rabbit_mgmt_util:vhost(ReqData) of 31 | not_found -> false; 32 | none -> true; % none means `all` 33 | _ -> true 34 | end, ReqData, Context}. 35 | 36 | to_json(ReqData, Context = #context{user = User}) -> 37 | case rabbit_mgmt_util:disable_stats(ReqData) of 38 | false -> 39 | Arg = case rabbit_mgmt_util:vhost(ReqData) of 40 | none -> all; 41 | VHost -> VHost 42 | end, 43 | Consumers = rabbit_mgmt_format:strip_pids(rabbit_mgmt_db:get_all_consumers(Arg)), 44 | Formatted = [rabbit_mgmt_format:format_consumer_arguments(C) || C <- Consumers], 45 | rabbit_mgmt_util:reply_list( 46 | filter_user(Formatted, User), ReqData, Context); 47 | true -> 48 | rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context) 49 | end. 50 | 51 | is_authorized(ReqData, Context) -> 52 | rabbit_mgmt_util:is_authorized(ReqData, Context). 53 | 54 | filter_user(List, #user{username = Username, tags = Tags}) -> 55 | case rabbit_mgmt_util:is_monitor(Tags) of 56 | true -> List; 57 | false -> [I || I <- List, 58 | pget(user, pget(channel_details, I)) == Username] 59 | end. 60 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_exchanges.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_mgmt_wm_exchanges). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | resource_exists/2, basic/1, augmented/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | -define(DEFAULT_SORT, ["vhost", "name"]). 18 | 19 | -define(BASIC_COLUMNS, ["vhost", "name", "type", "durable", "auto_delete", 20 | "internal", "arguments", "pid"]). 21 | 22 | %%-------------------------------------------------------------------- 23 | 24 | init(Req, _State) -> 25 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 26 | 27 | variances(Req, Context) -> 28 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 29 | 30 | content_types_provided(ReqData, Context) -> 31 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 32 | 33 | resource_exists(ReqData, Context) -> 34 | {case exchanges0(ReqData) of 35 | vhost_not_found -> false; 36 | _ -> true 37 | end, ReqData, Context}. 38 | 39 | to_json(ReqData, Context) -> 40 | try 41 | Basic = rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, 42 | Context), 43 | Data = rabbit_mgmt_util:augment_resources(Basic, ?DEFAULT_SORT, 44 | ?BASIC_COLUMNS, ReqData, 45 | Context, fun augment/2), 46 | rabbit_mgmt_util:reply(Data, ReqData, Context) 47 | catch 48 | {error, invalid_range_parameters, Reason} -> 49 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 50 | end. 51 | 52 | is_authorized(ReqData, Context) -> 53 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 54 | 55 | %%-------------------------------------------------------------------- 56 | 57 | augment(Basic, ReqData) -> 58 | case rabbit_mgmt_util:disable_stats(ReqData) of 59 | false -> 60 | rabbit_mgmt_db:augment_exchanges(Basic, rabbit_mgmt_util:range(ReqData), 61 | basic); 62 | true -> 63 | Basic 64 | end. 65 | 66 | augmented(ReqData, Context) -> 67 | rabbit_mgmt_db:augment_exchanges( 68 | rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), 69 | rabbit_mgmt_util:range(ReqData), basic). 70 | 71 | basic(ReqData) -> 72 | [rabbit_mgmt_format:exchange(X) || X <- exchanges0(ReqData)]. 73 | 74 | exchanges0(ReqData) -> 75 | rabbit_mgmt_util:all_or_one_vhost(ReqData, fun rabbit_exchange:info_all/1). 76 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_extensions.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_extensions). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([variances/2]). 12 | 13 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 14 | -include_lib("rabbit_common/include/rabbit.hrl"). 15 | 16 | %%-------------------------------------------------------------------- 17 | 18 | init(Req, _State) -> 19 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 20 | 21 | variances(Req, Context) -> 22 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 23 | 24 | content_types_provided(ReqData, Context) -> 25 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 26 | 27 | to_json(ReqData, Context) -> 28 | Modules = rabbit_mgmt_dispatcher:modules([]), 29 | rabbit_mgmt_util:reply( 30 | [Module:web_ui() || Module <- Modules], ReqData, Context). 31 | 32 | is_authorized(ReqData, Context) -> 33 | rabbit_mgmt_util:is_authorized(ReqData, Context). 34 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_feature_flag_enable.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) 2019-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_feature_flag_enable). 9 | 10 | -export([init/2, 11 | content_types_accepted/2, is_authorized/2, 12 | allowed_methods/2, accept_content/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("rabbit_common/include/rabbit.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _Args) -> 21 | {cowboy_rest, 22 | rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), 23 | #context{}}. 24 | 25 | variances(Req, Context) -> 26 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 27 | 28 | content_types_accepted(ReqData, Context) -> 29 | {[{{<<"application">>, <<"json">>, '*'}, accept_content}], ReqData, Context}. 30 | 31 | allowed_methods(ReqData, Context) -> 32 | {[<<"PUT">>, <<"OPTIONS">>], ReqData, Context}. 33 | 34 | is_authorized(ReqData, Context) -> 35 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 36 | 37 | accept_content(ReqData, #context{} = Context) -> 38 | NameS = rabbit_mgmt_util:id(name, ReqData), 39 | try 40 | Name = list_to_existing_atom(binary_to_list(NameS)), 41 | case rabbit_feature_flags:enable(Name) of 42 | ok -> 43 | {true, ReqData, Context}; 44 | {error, Reason1} -> 45 | FormattedReason1 = rabbit_ff_extra:format_error(Reason1), 46 | rabbit_mgmt_util:bad_request( 47 | list_to_binary(FormattedReason1), ReqData, Context) 48 | end 49 | catch 50 | _:badarg -> 51 | Reason2 = unsupported, 52 | FormattedReason2 = rabbit_ff_extra:format_error(Reason2), 53 | rabbit_mgmt_util:bad_request( 54 | list_to_binary(FormattedReason2), ReqData, Context) 55 | end. 56 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_feature_flags.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) 2019-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_feature_flags). 9 | 10 | -export([init/2, to_json/2, 11 | content_types_provided/2, 12 | is_authorized/2, allowed_methods/2]). 13 | -export([variances/2]). 14 | -export([feature_flags/0]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _Args) -> 22 | {cowboy_rest, 23 | rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), 24 | #context{}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | allowed_methods(ReqData, Context) -> 33 | {[<<"HEAD">>, <<"GET">>, <<"OPTIONS">>], ReqData, Context}. 34 | 35 | to_json(ReqData, Context) -> 36 | rabbit_mgmt_util:reply_list(feature_flags(), ReqData, Context). 37 | 38 | is_authorized(ReqData, Context) -> 39 | {Res, Req2, Context2} = rabbit_mgmt_util:is_authorized_admin(ReqData, Context), 40 | {Res, Req2, Context2}. 41 | 42 | %%-------------------------------------------------------------------- 43 | 44 | feature_flags() -> 45 | rabbit_ff_extra:cli_info(). 46 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_global_parameter.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_mgmt_wm_global_parameter). 9 | 10 | -export([init/2, resource_exists/2, to_json/2, 11 | content_types_provided/2, content_types_accepted/2, 12 | is_authorized/2, allowed_methods/2, accept_content/2, 13 | delete_resource/2]). 14 | -export([variances/2]). 15 | 16 | -import(rabbit_misc, [pget/2]). 17 | 18 | -include_lib("rabbit_common/include/rabbit.hrl"). 19 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 20 | 21 | %%-------------------------------------------------------------------- 22 | 23 | init(Req, _State) -> 24 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | content_types_accepted(ReqData, Context) -> 33 | {[{'*', accept_content}], ReqData, Context}. 34 | 35 | allowed_methods(ReqData, Context) -> 36 | {[<<"HEAD">>, <<"GET">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 37 | 38 | resource_exists(ReqData, Context) -> 39 | {case parameter(ReqData) of 40 | not_found -> false; 41 | _ -> true 42 | end, ReqData, Context}. 43 | 44 | to_json(ReqData, Context) -> 45 | rabbit_mgmt_util:reply(rabbit_mgmt_format:parameter(parameter(ReqData)), 46 | ReqData, Context). 47 | 48 | accept_content(ReqData0, Context = #context{user = #user{username = Username}}) -> 49 | rabbit_mgmt_util:with_decode( 50 | [value], ReqData0, Context, 51 | fun([Value], _, ReqData) -> 52 | Val = if is_map(Value) -> maps:to_list(Value); 53 | true -> Value 54 | end, 55 | rabbit_runtime_parameters:set_global(name(ReqData), Val, Username), 56 | {true, ReqData, Context} 57 | end). 58 | 59 | delete_resource(ReqData, Context = #context{user = #user{username = Username}}) -> 60 | ok = rabbit_runtime_parameters:clear_global(name(ReqData), Username), 61 | {true, ReqData, Context}. 62 | 63 | is_authorized(ReqData, Context) -> 64 | rabbit_mgmt_util:is_authorized_global_parameters(ReqData, Context). 65 | 66 | %%-------------------------------------------------------------------- 67 | 68 | parameter(ReqData) -> 69 | rabbit_runtime_parameters:lookup_global(name(ReqData)). 70 | 71 | name(ReqData) -> rabbit_data_coercion:to_atom(rabbit_mgmt_util:id(name, ReqData)). 72 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_global_parameters.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_mgmt_wm_global_parameters). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([variances/2]). 12 | -export([basic/0]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | 16 | %%-------------------------------------------------------------------- 17 | 18 | init(Req, _State) -> 19 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 20 | 21 | variances(Req, Context) -> 22 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 23 | 24 | content_types_provided(ReqData, Context) -> 25 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 26 | 27 | to_json(ReqData, Context) -> 28 | rabbit_mgmt_util:reply_list(basic(), ReqData, Context). 29 | 30 | is_authorized(ReqData, Context) -> 31 | rabbit_mgmt_util:is_authorized_global_parameters(ReqData, Context). 32 | 33 | %%-------------------------------------------------------------------- 34 | 35 | basic() -> 36 | rabbit_runtime_parameters:list_global(). 37 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_alarms.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 | %% An HTTP API counterpart of 'rabbitmq-diagnostics check_alarms' 9 | -module(rabbit_mgmt_wm_health_check_alarms). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include("rabbit_mgmt.hrl"). 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {true, ReqData, Context}. 31 | 32 | to_json(ReqData, Context) -> 33 | Timeout = case cowboy_req:header(<<"timeout">>, ReqData) of 34 | undefined -> 70000; 35 | Val -> list_to_integer(binary_to_list(Val)) 36 | end, 37 | case rabbit_alarm:get_alarms(Timeout) of 38 | [] -> 39 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 40 | Xs when length(Xs) > 0 -> 41 | Msg = "There are alarms in effect in the cluster", 42 | failure(Msg, Xs, ReqData, Context) 43 | end. 44 | 45 | failure(Message, Alarms0, ReqData, Context) -> 46 | Alarms = rabbit_alarm:format_as_maps(Alarms0), 47 | Body = #{ 48 | status => failed, 49 | reason => rabbit_data_coercion:to_binary(Message), 50 | alarms => Alarms 51 | }, 52 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData, Context), 53 | {stop, cowboy_req:reply(?HEALTH_CHECK_FAILURE_STATUS, #{}, Response, ReqData1), Context1}. 54 | 55 | is_authorized(ReqData, Context) -> 56 | rabbit_mgmt_util:is_authorized(ReqData, Context). 57 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_local_alarms.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 | %% An HTTP API counterpart of 'rabbitmq-dignoastics check_local_alarms' 9 | -module(rabbit_mgmt_wm_health_check_local_alarms). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include("rabbit_mgmt.hrl"). 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {true, ReqData, Context}. 31 | 32 | to_json(ReqData, Context) -> 33 | Timeout = case cowboy_req:header(<<"timeout">>, ReqData) of 34 | undefined -> 70000; 35 | Val -> list_to_integer(binary_to_list(Val)) 36 | end, 37 | case rabbit_alarm:get_local_alarms(Timeout) of 38 | [] -> 39 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 40 | Xs when length(Xs) > 0 -> 41 | Msg = "There are alarms in effect on the node", 42 | failure(Msg, Xs, ReqData, Context) 43 | end. 44 | 45 | failure(Message, Alarms0, ReqData, Context) -> 46 | Alarms = rabbit_alarm:format_as_maps(Alarms0), 47 | Body = #{ 48 | status => failed, 49 | reason => rabbit_data_coercion:to_binary(Message), 50 | alarms => Alarms 51 | }, 52 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData, Context), 53 | {stop, cowboy_req:reply(?HEALTH_CHECK_FAILURE_STATUS, #{}, Response, ReqData1), Context1}. 54 | 55 | is_authorized(ReqData, Context) -> 56 | rabbit_mgmt_util:is_authorized(ReqData, Context). 57 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_node_is_mirror_sync_critical.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 | %% An HTTP API counterpart of 'rabbitmq-diagnostics check_if_node_is_quorum_critical' 9 | -module(rabbit_mgmt_wm_health_check_node_is_mirror_sync_critical). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {true, ReqData, Context}. 30 | 31 | to_json(ReqData, Context) -> 32 | case rabbit_nodes:is_single_node_cluster() of 33 | true -> 34 | rabbit_mgmt_util:reply([{status, ok}, 35 | {reason, <<"single node cluster">>}], ReqData, Context); 36 | false -> 37 | case rabbit_amqqueue:list_local_mirrored_classic_without_synchronised_mirrors_for_cli() of 38 | [] -> 39 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 40 | Qs when length(Qs) > 0 -> 41 | Msg = <<"There are classic mirrored queues without online synchronised mirrors">>, 42 | failure(Msg, Qs, ReqData, Context) 43 | end 44 | end. 45 | 46 | failure(Message, Qs, ReqData, Context) -> 47 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply([{status, failed}, 48 | {reason, Message}, 49 | {queues, Qs}], 50 | ReqData, Context), 51 | {stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}. 52 | 53 | is_authorized(ReqData, Context) -> 54 | rabbit_mgmt_util:is_authorized(ReqData, Context). 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_node_is_quorum_critical.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 | %% An HTTP API counterpart of 'rabbitmq-diagnostics check_if_node_is_quorum_critical' 9 | -module(rabbit_mgmt_wm_health_check_node_is_quorum_critical). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {true, ReqData, Context}. 30 | 31 | to_json(ReqData, Context) -> 32 | case rabbit_nodes:is_single_node_cluster() of 33 | true -> 34 | rabbit_mgmt_util:reply([{status, ok}, 35 | {reason, <<"single node cluster">>}], ReqData, Context); 36 | false -> 37 | case rabbit_quorum_queue:list_with_minimum_quorum_for_cli() of 38 | [] -> 39 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 40 | Qs when length(Qs) > 0 -> 41 | Msg = <<"There are quorum queues that would lose their quorum if the target node is shut down">>, 42 | failure(Msg, Qs, ReqData, Context) 43 | end 44 | end. 45 | 46 | failure(Message, Qs, ReqData, Context) -> 47 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply([{status, failed}, 48 | {reason, Message}, 49 | {queues, Qs}], 50 | ReqData, Context), 51 | {stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}. 52 | 53 | is_authorized(ReqData, Context) -> 54 | rabbit_mgmt_util:is_authorized(ReqData, Context). 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_port_listener.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 | %% An HTTP API counterpart of 'rabbitmq-diagnostics check_port_listener' 9 | -module(rabbit_mgmt_wm_health_check_port_listener). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("rabbit_common/include/rabbit.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {case port(ReqData) of 31 | none -> false; 32 | _ -> true 33 | end, ReqData, Context}. 34 | 35 | to_json(ReqData, Context) -> 36 | try 37 | Port = binary_to_integer(port(ReqData)), 38 | Listeners = rabbit_networking:active_listeners(), 39 | Local = [L || #listener{node = N} = L <- Listeners, N == node()], 40 | PortListeners = [L || #listener{port = P} = L <- Local, P == Port], 41 | case PortListeners of 42 | [] -> 43 | Msg = <<"No active listener">>, 44 | failure(Msg, Port, [P || #listener{port = P} <- Local], ReqData, Context); 45 | _ -> 46 | rabbit_mgmt_util:reply([{status, ok}, 47 | {port, Port}], ReqData, Context) 48 | end 49 | catch 50 | error:badarg -> 51 | rabbit_mgmt_util:bad_request(<<"Invalid port">>, ReqData, Context) 52 | end. 53 | 54 | failure(Message, Missing, Ports, ReqData, Context) -> 55 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply([{status, failed}, 56 | {reason, Message}, 57 | {missing, Missing}, 58 | {ports, Ports}], 59 | ReqData, Context), 60 | {stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}. 61 | 62 | is_authorized(ReqData, Context) -> 63 | rabbit_mgmt_util:is_authorized(ReqData, Context). 64 | 65 | port(ReqData) -> 66 | rabbit_mgmt_util:id(port, ReqData). 67 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_health_check_virtual_hosts.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 | %% An HTTP API counterpart of 'rabbitmq-diagnostics check_virtual_hosts' 9 | -module(rabbit_mgmt_wm_health_check_virtual_hosts). 10 | 11 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 12 | -export([resource_exists/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {true, ReqData, Context}. 30 | 31 | to_json(ReqData, Context) -> 32 | case rabbit_vhost_sup_sup:check() of 33 | [] -> 34 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 35 | Vs when length(Vs) > 0 -> 36 | Msg = <<"Some virtual hosts are down">>, 37 | failure(Msg, Vs, ReqData, Context) 38 | end. 39 | 40 | failure(Message, Vs, ReqData, Context) -> 41 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply([{status, failed}, 42 | {reason, Message}, 43 | {'virtual-hosts', Vs}], 44 | ReqData, Context), 45 | {stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}. 46 | 47 | is_authorized(ReqData, Context) -> 48 | rabbit_mgmt_util:is_authorized(ReqData, Context). 49 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_healthchecks.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 | %% This original One True Health Check™ has been deprecated as too coarse-grained, 9 | %% intrusive and prone to false positives under load. 10 | -module(rabbit_mgmt_wm_healthchecks). 11 | 12 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 13 | -export([resource_exists/2]). 14 | -export([variances/2]). 15 | 16 | -include("rabbit_mgmt.hrl"). 17 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_provided(ReqData, Context) -> 28 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 29 | 30 | resource_exists(ReqData, Context) -> 31 | {case node0(ReqData) of 32 | not_found -> false; 33 | _ -> true 34 | end, ReqData, Context}. 35 | 36 | to_json(ReqData, Context) -> 37 | Node = node0(ReqData), 38 | Timeout = case cowboy_req:header(<<"timeout">>, ReqData) of 39 | undefined -> 70000; 40 | Val -> list_to_integer(binary_to_list(Val)) 41 | end, 42 | case rabbit_health_check:node(Node, Timeout) of 43 | ok -> 44 | rabbit_mgmt_util:reply([{status, ok}], ReqData, Context); 45 | {badrpc, timeout} -> 46 | ErrMsg = rabbit_mgmt_format:print("node ~p health check timed out", [Node]), 47 | failure(ErrMsg, ReqData, Context); 48 | {badrpc, Err} -> 49 | failure(rabbit_mgmt_format:print("~p", Err), ReqData, Context); 50 | {error_string, Err} -> 51 | S = rabbit_mgmt_format:escape_html_tags( 52 | rabbit_data_coercion:to_list(rabbit_mgmt_format:print(Err))), 53 | failure(S, ReqData, Context) 54 | end. 55 | 56 | failure(Message, ReqData, Context) -> 57 | {Response, ReqData1, Context1} = rabbit_mgmt_util:reply([{status, failed}, 58 | {reason, Message}], 59 | ReqData, Context), 60 | {stop, cowboy_req:reply(?HEALTH_CHECK_FAILURE_STATUS, #{}, Response, ReqData1), Context1}. 61 | 62 | is_authorized(ReqData, Context) -> 63 | rabbit_mgmt_util:is_authorized(ReqData, Context). 64 | 65 | node0(ReqData) -> 66 | Node = case rabbit_mgmt_util:id(node, ReqData) of 67 | none -> 68 | node(); 69 | Node0 -> 70 | list_to_atom(binary_to_list(Node0)) 71 | end, 72 | case [N || N <- rabbit_mgmt_wm_nodes:all_nodes(ReqData), 73 | proplists:get_value(name, N) == Node] of 74 | [] -> not_found; 75 | [_] -> Node 76 | end. 77 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_limit.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_mgmt_wm_limit). 9 | 10 | -export([init/2, 11 | content_types_accepted/2, is_authorized/2, 12 | allowed_methods/2, accept_content/2, 13 | delete_resource/2]). 14 | -export([variances/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_accepted(ReqData, Context) -> 28 | {[{{<<"application">>, <<"json">>, '*'}, accept_content}], ReqData, Context}. 29 | 30 | allowed_methods(ReqData, Context) -> 31 | {[<<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 32 | 33 | accept_content(ReqData0, Context = #context{user = #user{username = Username}}) -> 34 | case rabbit_mgmt_util:vhost(ReqData0) of 35 | not_found -> 36 | rabbit_mgmt_util:not_found(vhost_not_found, ReqData0, Context); 37 | VHost -> 38 | rabbit_mgmt_util:with_decode( 39 | [value], ReqData0, Context, 40 | fun([Value], _Body, ReqData) -> 41 | Name = rabbit_mgmt_util:id(name, ReqData), 42 | case rabbit_vhost_limit:update_limit(VHost, Name, Value, 43 | Username) of 44 | ok -> 45 | {true, ReqData, Context}; 46 | {error_string, Reason} -> 47 | rabbit_mgmt_util:bad_request( 48 | list_to_binary(Reason), ReqData, Context) 49 | end 50 | end) 51 | end. 52 | 53 | delete_resource(ReqData, Context = #context{user = #user{username = Username}}) -> 54 | ok = rabbit_vhost_limit:clear_limit(rabbit_mgmt_util:vhost(ReqData), 55 | name(ReqData), Username), 56 | {true, ReqData, Context}. 57 | 58 | 59 | is_authorized(ReqData, Context) -> 60 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 61 | 62 | %%-------------------------------------------------------------------- 63 | 64 | name(ReqData) -> rabbit_mgmt_util:id(name, ReqData). 65 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_limits.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_mgmt_wm_limits). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, 11 | resource_exists/2, is_authorized/2, allowed_methods/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | allowed_methods(ReqData, Context) -> 26 | {[<<"GET">>, <<"OPTIONS">>], ReqData, Context}. 27 | 28 | %% Admin user can see all vhosts 29 | 30 | is_authorized(ReqData, Context) -> 31 | rabbit_mgmt_util:is_authorized_vhost_visible(ReqData, Context). 32 | 33 | content_types_provided(ReqData, Context) -> 34 | {[{<<"application/json">>, to_json}], ReqData, Context}. 35 | 36 | resource_exists(ReqData, Context) -> 37 | {case rabbit_mgmt_util:vhost(ReqData) of 38 | not_found -> false; 39 | _ -> true 40 | end, ReqData, Context}. 41 | 42 | to_json(ReqData, Context) -> 43 | rabbit_mgmt_util:reply_list(limits(ReqData, Context), [], ReqData, Context). 44 | 45 | limits(ReqData, Context) -> 46 | case rabbit_mgmt_util:vhost(ReqData) of 47 | none -> 48 | User = Context#context.user, 49 | VisibleVhosts = rabbit_mgmt_util:list_visible_vhosts_names(User), 50 | [ [{vhost, VHost}, {value, Value}] 51 | || {VHost, Value} <- rabbit_vhost_limit:list(), 52 | lists:member(VHost, VisibleVhosts) ]; 53 | VHost when is_binary(VHost) -> 54 | case rabbit_vhost_limit:list(VHost) of 55 | [] -> []; 56 | Value -> [[{vhost, VHost}, {value, Value}]] 57 | end 58 | end. 59 | %%-------------------------------------------------------------------- 60 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_login.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_login). 9 | 10 | -export([init/2, is_authorized/2, 11 | allowed_methods/2, accept_content/2, content_types_provided/2, 12 | content_types_accepted/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("amqp_client/include/amqp_client.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | allowed_methods(ReqData, Context) -> 27 | {[<<"POST">>, <<"OPTIONS">>], ReqData, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | content_types_accepted(ReqData, Context) -> 33 | {[{{<<"application">>, <<"x-www-form-urlencoded">>, '*'}, accept_content}], ReqData, Context}. 34 | 35 | is_authorized(#{method := <<"OPTIONS">>} = ReqData, Context) -> 36 | {true, ReqData, Context}; 37 | is_authorized(ReqData0, Context) -> 38 | {ok, Body, ReqData} = cowboy_req:read_urlencoded_body(ReqData0), 39 | Username = proplists:get_value(<<"username">>, Body), 40 | Password = proplists:get_value(<<"password">>, Body), 41 | case rabbit_mgmt_util:is_authorized_user(ReqData, Context, Username, Password) of 42 | {true, ReqData1, Context1} -> 43 | Value = base64:encode(<>), 44 | {true, cowboy_req:set_resp_cookie(<<"auth">>, Value, ReqData1), Context1}; 45 | Other -> 46 | Other 47 | end. 48 | 49 | accept_content(ReqData, Context) -> 50 | rabbit_mgmt_util:post_respond(do_login(ReqData, Context)). 51 | 52 | do_login(ReqData, Context) -> 53 | rabbit_mgmt_util:reply(ok, ReqData, Context). 54 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_node.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_mgmt_wm_node). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case node0(ReqData) of 30 | not_found -> false; 31 | _ -> true 32 | end, ReqData, Context}. 33 | 34 | to_json(ReqData, Context) -> 35 | rabbit_mgmt_util:reply(node0(ReqData), ReqData, Context). 36 | 37 | is_authorized(ReqData, Context) -> 38 | rabbit_mgmt_util:is_authorized_monitor(ReqData, Context). 39 | 40 | %%-------------------------------------------------------------------- 41 | 42 | node0(ReqData) -> 43 | Node = list_to_atom(binary_to_list(rabbit_mgmt_util:id(node, ReqData))), 44 | [Data] = node_data(Node, ReqData), 45 | augment(ReqData, Node, Data). 46 | 47 | augment(ReqData, Node, Data) -> 48 | lists:foldl(fun (Key, DataN) -> augment(Key, ReqData, Node, DataN) end, 49 | Data, [memory, binary]). 50 | 51 | augment(Key, ReqData, Node, Data) -> 52 | case rabbit_mgmt_util:qs_val(list_to_binary(atom_to_list(Key)), ReqData) of 53 | <<"true">> -> Res = case rpc:call(Node, rabbit_vm, Key, [], infinity) of 54 | {badrpc, _} -> not_available; 55 | Result -> Result 56 | end, 57 | [{Key, Res} | Data]; 58 | _ -> Data 59 | end. 60 | 61 | node_data(Node, ReqData) -> 62 | S = rabbit_mnesia:status(), 63 | Nodes = proplists:get_value(nodes, S), 64 | Running = proplists:get_value(running_nodes, S), 65 | Type = find_type(Node, Nodes), 66 | Basic = [[{name, Node}, {running, lists:member(Node, Running)}, {type, Type}]], 67 | case rabbit_mgmt_util:disable_stats(ReqData) of 68 | false -> 69 | rabbit_mgmt_db:augment_nodes(Basic, rabbit_mgmt_util:range_ceil(ReqData)); 70 | true -> 71 | Basic 72 | end. 73 | 74 | find_type(Node, [{Type, Nodes} | Rest]) -> 75 | case lists:member(Node, Nodes) of 76 | true -> Type; 77 | false -> find_type(Node, Rest) 78 | end. 79 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_node_memory.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_mgmt_wm_node_memory). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, [Mode]) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), {Mode, #context{}}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {node_exists(ReqData, get_node(ReqData)), ReqData, Context}. 30 | 31 | to_json(ReqData, {Mode, Context}) -> 32 | rabbit_mgmt_util:reply(augment(Mode, ReqData), ReqData, {Mode, Context}). 33 | 34 | is_authorized(ReqData, {Mode, Context}) -> 35 | {Res, RD, C} = rabbit_mgmt_util:is_authorized_monitor(ReqData, Context), 36 | {Res, RD, {Mode, C}}. 37 | 38 | %%-------------------------------------------------------------------- 39 | get_node(ReqData) -> 40 | list_to_atom(binary_to_list(rabbit_mgmt_util:id(node, ReqData))). 41 | 42 | node_exists(ReqData, Node) -> 43 | case [N || N <- rabbit_mgmt_wm_nodes:all_nodes(ReqData), 44 | proplists:get_value(name, N) == Node] of 45 | [] -> false; 46 | [_] -> true 47 | end. 48 | 49 | augment(Mode, ReqData) -> 50 | Node = get_node(ReqData), 51 | case node_exists(ReqData, Node) of 52 | false -> 53 | not_found; 54 | true -> 55 | case rpc:call(Node, rabbit_vm, memory, [], infinity) of 56 | {badrpc, _} -> [{memory, not_available}]; 57 | Result -> [{memory, format(Mode, Result)}] 58 | end 59 | end. 60 | 61 | format(absolute, Result) -> 62 | Result; 63 | format(relative, Result) -> 64 | {value, {total, Totals}, Rest} = lists:keytake(total, 1, Result), 65 | Total = proplists:get_value(rss, Totals), 66 | [{total, 100} | [{K, percentage(V, Total)} || {K, V} <- Rest, 67 | K =/= strategy]]. 68 | 69 | percentage(Part, Total) -> 70 | case round((Part/Total) * 100) of 71 | 0 when Part =/= 0 -> 72 | 1; 73 | Int -> 74 | Int 75 | end. 76 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_node_memory_ets.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_mgmt_wm_node_memory_ets). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([resource_exists/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, [Mode]) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), {Mode, #context{}}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {node_exists(ReqData, get_node(ReqData)), ReqData, Context}. 30 | 31 | to_json(ReqData, {Mode, Context}) -> 32 | rabbit_mgmt_util:reply(augment(Mode, ReqData), ReqData, {Mode, Context}). 33 | 34 | is_authorized(ReqData, {Mode, Context}) -> 35 | {Res, RD, C} = rabbit_mgmt_util:is_authorized_monitor(ReqData, Context), 36 | {Res, RD, {Mode, C}}. 37 | 38 | %%-------------------------------------------------------------------- 39 | get_node(ReqData) -> 40 | list_to_atom(binary_to_list(rabbit_mgmt_util:id(node, ReqData))). 41 | 42 | get_filter(ReqData) -> 43 | case rabbit_mgmt_util:id(filter, ReqData) of 44 | none -> all; 45 | <<"management">> -> rabbit_mgmt_storage; 46 | Other when is_binary(Other) -> list_to_atom(binary_to_list(Other)); 47 | _ -> all 48 | end. 49 | 50 | node_exists(ReqData, Node) -> 51 | case [N || N <- rabbit_mgmt_wm_nodes:all_nodes(ReqData), 52 | proplists:get_value(name, N) == Node] of 53 | [] -> false; 54 | [_] -> true 55 | end. 56 | 57 | augment(Mode, ReqData) -> 58 | Node = get_node(ReqData), 59 | Filter = get_filter(ReqData), 60 | case node_exists(ReqData, Node) of 61 | false -> 62 | not_found; 63 | true -> 64 | case rpc:call(Node, rabbit_vm, ets_tables_memory, 65 | [Filter], infinity) of 66 | {badrpc, _} -> [{ets_tables_memory, not_available}]; 67 | [] -> [{ets_tables_memory, no_tables}]; 68 | Result -> [{ets_tables_memory, format(Mode, Result)}] 69 | end 70 | end. 71 | 72 | format(absolute, Result) -> 73 | Total = lists:sum([V || {_K,V} <- Result]), 74 | [{total, Total} | Result]; 75 | format(relative, Result) -> 76 | Total = lists:sum([V || {_K,V} <- Result]), 77 | [{total, 100} | [{K, percentage(V, Total)} || {K, V} <- Result]]. 78 | 79 | percentage(Part, Total) -> 80 | case round((Part/Total) * 100) of 81 | 0 when Part =/= 0 -> 82 | 1; 83 | Int -> 84 | Int 85 | end. 86 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_nodes.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_mgmt_wm_nodes). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([all_nodes/1, all_nodes_raw/0]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | to_json(ReqData, Context) -> 29 | try 30 | rabbit_mgmt_util:reply_list(all_nodes(ReqData), ReqData, Context) 31 | catch 32 | {error, invalid_range_parameters, Reason} -> 33 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 34 | end. 35 | 36 | is_authorized(ReqData, Context) -> 37 | rabbit_mgmt_util:is_authorized_monitor(ReqData, Context). 38 | 39 | %%-------------------------------------------------------------------- 40 | 41 | all_nodes(ReqData) -> 42 | case rabbit_mgmt_util:disable_stats(ReqData) of 43 | false -> 44 | rabbit_mgmt_db:augment_nodes( 45 | all_nodes_raw(), rabbit_mgmt_util:range_ceil(ReqData)); 46 | true -> 47 | all_nodes_raw() 48 | end. 49 | 50 | all_nodes_raw() -> 51 | S = rabbit_mnesia:status(), 52 | Nodes = proplists:get_value(nodes, S), 53 | Types = proplists:get_keys(Nodes), 54 | Running = proplists:get_value(running_nodes, S), 55 | [[{name, Node}, {type, Type}, {running, lists:member(Node, Running)}] || 56 | Type <- Types, Node <- proplists:get_value(Type, Nodes)]. 57 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_operator_policies.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_mgmt_wm_operator_policies). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | resource_exists/2, basic/1]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {[{<<"application/json">>, to_json}], ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case basic(ReqData) of 30 | not_found -> false; 31 | _ -> true 32 | end, ReqData, Context}. 33 | 34 | to_json(ReqData, Context) -> 35 | rabbit_mgmt_util:reply_list( 36 | rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), 37 | ["priority"], ReqData, Context). 38 | 39 | is_authorized(ReqData, Context) -> 40 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 41 | 42 | %%-------------------------------------------------------------------- 43 | 44 | basic(ReqData) -> 45 | case rabbit_mgmt_util:vhost(ReqData) of 46 | not_found -> not_found; 47 | none -> rabbit_policy:list_op(); 48 | VHost -> rabbit_policy:list_op(VHost) 49 | end. 50 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_parameters.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_mgmt_wm_parameters). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | resource_exists/2, basic/1]). 12 | -export([fix_shovel_publish_properties/1]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("rabbit_common/include/rabbit.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | content_types_provided(ReqData, Context) -> 27 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {case basic(ReqData) of 31 | not_found -> false; 32 | _ -> true 33 | end, ReqData, Context}. 34 | 35 | to_json(ReqData, Context) -> 36 | rabbit_mgmt_util:reply_list( 37 | rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), 38 | ReqData, Context). 39 | 40 | is_authorized(ReqData, Context) -> 41 | rabbit_mgmt_util:is_authorized_policies(ReqData, Context). 42 | 43 | %%-------------------------------------------------------------------- 44 | 45 | %% Hackish fix to make sure we return a JSON object instead of an empty list 46 | %% when the publish-properties value is empty. Should be removed in 3.7.0 47 | %% when we switch to a new JSON library. 48 | fix_shovel_publish_properties(P) -> 49 | case lists:keyfind(component, 1, P) of 50 | {_, <<"shovel">>} -> 51 | case lists:keytake(value, 1, P) of 52 | {value, {_, Values}, P2} -> 53 | case lists:keytake(<<"publish-properties">>, 1, Values) of 54 | {_, {_, []}, Values2} -> 55 | P2 ++ [{value, Values2 ++ [{<<"publish-properties">>, empty_struct}]}]; 56 | _ -> 57 | P 58 | end; 59 | _ -> P 60 | end; 61 | _ -> P 62 | end. 63 | 64 | basic(ReqData) -> 65 | Raw = case rabbit_mgmt_util:id(component, ReqData) of 66 | none -> rabbit_runtime_parameters:list(); 67 | Name -> case rabbit_mgmt_util:vhost(ReqData) of 68 | none -> rabbit_runtime_parameters:list_component( 69 | Name); 70 | not_found -> not_found; 71 | VHost -> rabbit_runtime_parameters:list( 72 | VHost, Name) 73 | end 74 | end, 75 | case Raw of 76 | not_found -> not_found; 77 | _ -> [rabbit_mgmt_format:parameter(fix_shovel_publish_properties(P)) || P <- Raw] 78 | end. 79 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_permissions.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_mgmt_wm_permissions). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([permissions/0]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | to_json(ReqData, Context) -> 29 | rabbit_mgmt_util:reply_list(permissions(), ["vhost", "user"], 30 | ReqData, Context). 31 | 32 | is_authorized(ReqData, Context) -> 33 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 34 | 35 | %%-------------------------------------------------------------------- 36 | 37 | permissions() -> 38 | rabbit_auth_backend_internal:list_permissions(). 39 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_permissions_user.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_mgmt_wm_permissions_user). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, resource_exists/2, 11 | is_authorized/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case rabbit_mgmt_wm_user:user(ReqData) of 30 | {ok, _} -> true; 31 | {error, _} -> false 32 | end, ReqData, Context}. 33 | 34 | to_json(ReqData, Context) -> 35 | User = rabbit_mgmt_util:id(user, ReqData), 36 | rabbit_mgmt_util:catch_no_such_user_or_vhost( 37 | fun() -> 38 | Perms = rabbit_auth_backend_internal:list_user_permissions(User), 39 | rabbit_mgmt_util:reply_list([[{user, User} | Rest] || Rest <- Perms], 40 | ["vhost", "user"], ReqData, Context) 41 | end, 42 | fun() -> 43 | rabbit_mgmt_util:bad_request(vhost_or_user_not_found, ReqData, Context) 44 | end). 45 | 46 | is_authorized(ReqData, Context) -> 47 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 48 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_permissions_vhost.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_mgmt_wm_permissions_vhost). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, resource_exists/2, 11 | is_authorized/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {rabbit_vhost:exists(rabbit_mgmt_wm_vhost:id(ReqData)), ReqData, Context}. 30 | 31 | to_json(ReqData, Context) -> 32 | VHost = rabbit_mgmt_util:id(vhost, ReqData), 33 | rabbit_mgmt_util:catch_no_such_user_or_vhost( 34 | fun() -> 35 | Perms = rabbit_auth_backend_internal:list_vhost_permissions(VHost), 36 | rabbit_mgmt_util:reply_list([[{vhost, VHost} | Rest] || Rest <- Perms], 37 | ["vhost", "user"], ReqData, Context) 38 | end, 39 | fun() -> 40 | rabbit_mgmt_util:bad_request(vhost_or_user_not_found, ReqData, Context) 41 | end). 42 | 43 | is_authorized(ReqData, Context) -> 44 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 45 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_policies.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_mgmt_wm_policies). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2, 11 | resource_exists/2, basic/1]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case basic(ReqData) of 30 | not_found -> false; 31 | _ -> true 32 | end, ReqData, Context}. 33 | 34 | to_json(ReqData, Context) -> 35 | rabbit_mgmt_util:reply_list( 36 | rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), 37 | ["priority"], ReqData, Context). 38 | 39 | is_authorized(ReqData, Context) -> 40 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 41 | 42 | %%-------------------------------------------------------------------- 43 | 44 | basic(ReqData) -> 45 | case rabbit_mgmt_util:vhost(ReqData) of 46 | not_found -> not_found; 47 | none -> rabbit_policy:list(); 48 | VHost -> rabbit_policy:list(VHost) 49 | end. 50 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_queue_actions.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_queue_actions). 9 | 10 | -export([init/2, resource_exists/2, is_authorized/2, 11 | allowed_methods/2, content_types_accepted/2, accept_content/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("amqp_client/include/amqp_client.hrl"). 16 | -include_lib("rabbit/include/amqqueue.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, _State) -> 21 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 22 | 23 | variances(Req, Context) -> 24 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 25 | 26 | allowed_methods(ReqData, Context) -> 27 | {[<<"POST">>, <<"OPTIONS">>], ReqData, Context}. 28 | 29 | resource_exists(ReqData, Context) -> 30 | {case rabbit_mgmt_wm_queue:queue(ReqData) of 31 | not_found -> false; 32 | _ -> true 33 | end, ReqData, Context}. 34 | 35 | content_types_accepted(ReqData, Context) -> 36 | {[{'*', accept_content}], ReqData, Context}. 37 | 38 | accept_content(ReqData, Context) -> 39 | rabbit_mgmt_util:post_respond(do_it(ReqData, Context)). 40 | 41 | do_it(ReqData0, Context) -> 42 | VHost = rabbit_mgmt_util:vhost(ReqData0), 43 | QName = rabbit_mgmt_util:id(queue, ReqData0), 44 | rabbit_mgmt_util:with_decode( 45 | [action], ReqData0, Context, 46 | fun([Action], _Body, ReqData) -> 47 | rabbit_amqqueue:with( 48 | rabbit_misc:r(VHost, queue, QName), 49 | fun(Q) -> action(Action, Q, ReqData, Context) end) 50 | end). 51 | 52 | is_authorized(ReqData, Context) -> 53 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 54 | 55 | %%-------------------------------------------------------------------- 56 | 57 | action(<<"sync">>, Q, ReqData, Context) when ?is_amqqueue(Q) -> 58 | QPid = amqqueue:get_pid(Q), 59 | spawn(fun() -> rabbit_amqqueue:sync_mirrors(QPid) end), 60 | {true, ReqData, Context}; 61 | 62 | action(<<"cancel_sync">>, Q, ReqData, Context) when ?is_amqqueue(Q) -> 63 | QPid = amqqueue:get_pid(Q), 64 | _ = rabbit_amqqueue:cancel_sync_mirrors(QPid), 65 | {true, ReqData, Context}; 66 | 67 | action(Else, _Q, ReqData, Context) -> 68 | rabbit_mgmt_util:bad_request({unknown, Else}, ReqData, Context). 69 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_queue_purge.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_mgmt_wm_queue_purge). 9 | 10 | -export([init/2, resource_exists/2, is_authorized/2, allowed_methods/2, 11 | delete_resource/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("amqp_client/include/amqp_client.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | allowed_methods(ReqData, Context) -> 26 | {[<<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case rabbit_mgmt_wm_queue:queue(ReqData) of 30 | not_found -> false; 31 | _ -> true 32 | end, ReqData, Context}. 33 | 34 | delete_resource(ReqData, Context) -> 35 | Name = rabbit_mgmt_util:id(queue, ReqData), 36 | rabbit_mgmt_util:direct_request( 37 | 'queue.purge', 38 | fun rabbit_mgmt_format:format_accept_content/1, 39 | [{queue, Name}], "Error purging queue: ~s", ReqData, Context). 40 | 41 | is_authorized(ReqData, Context) -> 42 | rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). 43 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_rebalance_queues.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_mgmt_wm_rebalance_queues). 9 | 10 | -export([init/2, service_available/2, resource_exists/2, 11 | content_types_provided/2, content_types_accepted/2, 12 | is_authorized/2, allowed_methods/2, accept_content/2]). 13 | -export([variances/2]). 14 | 15 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 16 | -include_lib("rabbit_common/include/rabbit.hrl"). 17 | 18 | %%-------------------------------------------------------------------- 19 | 20 | init(Req, [Mode]) -> 21 | Headers = rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), 22 | {cowboy_rest, Headers, {Mode, #context{}}}. 23 | 24 | service_available(Req, {{queues, all}, _Context}=State) -> 25 | {true, Req, State}; 26 | service_available(Req, State) -> 27 | {false, Req, State}. 28 | 29 | variances(Req, State) -> 30 | {[<<"accept-encoding">>, <<"origin">>], Req, State}. 31 | 32 | content_types_provided(Req, State) -> 33 | {[{{<<"text">>, <<"plain">>, '*'}, undefined}], Req, State}. 34 | 35 | content_types_accepted(Req, State) -> 36 | {[{'*', accept_content}], Req, State}. 37 | 38 | allowed_methods(Req, State) -> 39 | {[<<"POST">>, <<"OPTIONS">>], Req, State}. 40 | 41 | resource_exists(Req, State) -> 42 | {true, Req, State}. 43 | 44 | accept_content(Req, {_Mode, #context{user = #user{username = Username}}}=State) -> 45 | try 46 | rabbit_log:info("User '~s' has initiated a queue rebalance", [Username]), 47 | spawn(fun() -> 48 | rabbit_amqqueue:rebalance(all, <<".*">>, <<".*">>) 49 | end), 50 | {true, Req, State} 51 | catch 52 | {error, Reason} -> 53 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), Req, State) 54 | end. 55 | 56 | is_authorized(Req0, {Mode, Context0}) -> 57 | {Res, Req1, Context1} = rabbit_mgmt_util:is_authorized_admin(Req0, Context0), 58 | {Res, Req1, {Mode, Context1}}. 59 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_redirect.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) 2010-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_redirect). 9 | -export([init/2]). 10 | 11 | init(Req0, RedirectTo) -> 12 | Req = cowboy_req:reply(301, #{<<"location">> => RedirectTo}, Req0), 13 | {ok, Req, RedirectTo}. 14 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_reset.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_mgmt_wm_reset). 9 | 10 | -export([init/2, is_authorized/2, resource_exists/2, 11 | allowed_methods/2, delete_resource/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | 16 | %%-------------------------------------------------------------------- 17 | 18 | init(Req, _State) -> 19 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 20 | 21 | variances(Req, Context) -> 22 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 23 | 24 | allowed_methods(ReqData, Context) -> 25 | {[<<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 26 | 27 | resource_exists(ReqData, Context) -> 28 | case get_node(ReqData) of 29 | none -> {true, ReqData, Context}; 30 | {ok, Node} -> {lists:member(Node, rabbit_nodes:all_running()), 31 | ReqData, Context} 32 | end. 33 | 34 | delete_resource(ReqData, Context) -> 35 | case get_node(ReqData) of 36 | none -> 37 | rabbit_mgmt_storage:reset_all(); 38 | {ok, Node} -> 39 | rpc:call(Node, rabbit_mgmt_storage, reset, []) 40 | end, 41 | {true, ReqData, Context}. 42 | 43 | is_authorized(ReqData, Context) -> 44 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 45 | 46 | 47 | get_node(ReqData) -> 48 | case rabbit_mgmt_util:id(node, ReqData) of 49 | none -> 50 | none; 51 | Node0 -> 52 | Node = list_to_atom(binary_to_list(Node0)), 53 | {ok, Node} 54 | end. 55 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_static.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) 2010-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | %% Alias for cowboy_static that accepts a list of directories 9 | %% where static files can be found. 10 | 11 | -module(rabbit_mgmt_wm_static). 12 | 13 | -include_lib("kernel/include/file.hrl"). 14 | 15 | -export([init/2]). 16 | -export([malformed_request/2]). 17 | -export([forbidden/2]). 18 | -export([content_types_provided/2]). 19 | -export([resource_exists/2]). 20 | -export([last_modified/2]). 21 | -export([generate_etag/2]). 22 | -export([get_file/2]). 23 | 24 | 25 | init(Req0, {priv_file, _App, _Path}=Opts) -> 26 | Req1 = rabbit_mgmt_headers:set_common_permission_headers(Req0, ?MODULE), 27 | cowboy_static:init(Req1, Opts); 28 | init(Req0, [{App, Path}]) -> 29 | Req1 = rabbit_mgmt_headers:set_common_permission_headers(Req0, ?MODULE), 30 | do_init(Req1, App, Path); 31 | init(Req0, [{App, Path}|Tail]) -> 32 | Req1 = rabbit_mgmt_headers:set_common_permission_headers(Req0, ?MODULE), 33 | PathInfo = cowboy_req:path_info(Req1), 34 | Filepath = filename:join([code:priv_dir(App), Path|PathInfo]), 35 | %% We use erl_prim_loader because the file may be inside an .ez archive. 36 | FileInfo = erl_prim_loader:read_file_info(binary_to_list(Filepath)), 37 | case FileInfo of 38 | {ok, #file_info{type = regular}} -> do_init(Req1, App, Path); 39 | {ok, #file_info{type = symlink}} -> do_init(Req1, App, Path); 40 | _ -> init(Req0, Tail) 41 | end. 42 | 43 | do_init(Req, App, Path) -> 44 | cowboy_static:init(Req, {priv_dir, App, Path}). 45 | 46 | malformed_request(Req, State) -> 47 | cowboy_static:malformed_request(Req, State). 48 | 49 | forbidden(Req, State) -> 50 | cowboy_static:forbidden(Req, State). 51 | 52 | content_types_provided(Req, State) -> 53 | cowboy_static:content_types_provided(Req, State). 54 | 55 | resource_exists(Req, State) -> 56 | cowboy_static:resource_exists(Req, State). 57 | 58 | last_modified(Req, State) -> 59 | cowboy_static:last_modified(Req, State). 60 | 61 | generate_etag(Req, State) -> 62 | cowboy_static:generate_etag(Req, State). 63 | 64 | get_file(Req, State) -> 65 | cowboy_static:get_file(Req, State). 66 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_topic_permissions.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_mgmt_wm_topic_permissions). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([topic_permissions/0]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {[{<<"application/json">>, to_json}], ReqData, Context}. 27 | 28 | to_json(ReqData, Context) -> 29 | rabbit_mgmt_util:reply_list(topic_permissions(), ["vhost", "user"], 30 | ReqData, Context). 31 | 32 | is_authorized(ReqData, Context) -> 33 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 34 | 35 | %%-------------------------------------------------------------------- 36 | 37 | topic_permissions() -> 38 | rabbit_auth_backend_internal:list_topic_permissions(). 39 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_topic_permissions_user.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_mgmt_wm_topic_permissions_user). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, resource_exists/2, 11 | is_authorized/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {[{<<"application/json">>, to_json}], ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {case rabbit_mgmt_wm_user:user(ReqData) of 30 | {ok, _} -> true; 31 | {error, _} -> false 32 | end, ReqData, Context}. 33 | 34 | to_json(ReqData, Context) -> 35 | User = rabbit_mgmt_util:id(user, ReqData), 36 | rabbit_mgmt_util:catch_no_such_user_or_vhost( 37 | fun() -> 38 | Perms = rabbit_auth_backend_internal:list_user_topic_permissions(User), 39 | rabbit_mgmt_util:reply_list([[{user, User} | Rest] || Rest <- Perms], 40 | ["vhost", "user"], ReqData, Context) 41 | end, 42 | fun() -> 43 | rabbit_mgmt_util:bad_request(vhost_or_user_not_found, ReqData, Context) 44 | end). 45 | 46 | is_authorized(ReqData, Context) -> 47 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 48 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_topic_permissions_vhost.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_mgmt_wm_topic_permissions_vhost). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, resource_exists/2, 11 | is_authorized/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | content_types_provided(ReqData, Context) -> 26 | {[{<<"application/json">>, to_json}], ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | {rabbit_vhost:exists(rabbit_mgmt_wm_vhost:id(ReqData)), ReqData, Context}. 30 | 31 | to_json(ReqData, Context) -> 32 | VHost = rabbit_mgmt_util:id(vhost, ReqData), 33 | rabbit_mgmt_util:catch_no_such_user_or_vhost( 34 | fun() -> 35 | Perms = rabbit_auth_backend_internal:list_vhost_topic_permissions(VHost), 36 | rabbit_mgmt_util:reply_list([[{vhost, VHost} | Rest] || Rest <- Perms], 37 | ["vhost", "user"], ReqData, Context) 38 | end, 39 | fun() -> 40 | rabbit_mgmt_util:bad_request(vhost_or_user_not_found, ReqData, Context) 41 | end). 42 | 43 | is_authorized(ReqData, Context) -> 44 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 45 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_user.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_mgmt_wm_user). 9 | 10 | -export([init/2, resource_exists/2, to_json/2, 11 | content_types_provided/2, content_types_accepted/2, 12 | is_authorized/2, allowed_methods/2, accept_content/2, 13 | delete_resource/2, user/1, put_user/2, put_user/3]). 14 | -export([variances/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_provided(ReqData, Context) -> 28 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 29 | 30 | content_types_accepted(ReqData, Context) -> 31 | {[{'*', accept_content}], ReqData, Context}. 32 | 33 | allowed_methods(ReqData, Context) -> 34 | {[<<"HEAD">>, <<"GET">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 35 | 36 | resource_exists(ReqData, Context) -> 37 | {case user(ReqData) of 38 | {ok, _} -> true; 39 | {error, _} -> false 40 | end, ReqData, Context}. 41 | 42 | to_json(ReqData, Context) -> 43 | {ok, User} = user(ReqData), 44 | rabbit_mgmt_util:reply(rabbit_mgmt_format:internal_user(User), 45 | ReqData, Context). 46 | 47 | accept_content(ReqData0, Context = #context{user = #user{username = ActingUser}}) -> 48 | Username = rabbit_mgmt_util:id(user, ReqData0), 49 | rabbit_mgmt_util:with_decode( 50 | [], ReqData0, Context, 51 | fun(_, User, ReqData) -> 52 | put_user(User#{name => Username}, ActingUser), 53 | {true, ReqData, Context} 54 | end). 55 | 56 | delete_resource(ReqData, Context = #context{user = #user{username = ActingUser}}) -> 57 | User = rabbit_mgmt_util:id(user, ReqData), 58 | rabbit_auth_backend_internal:delete_user(User, ActingUser), 59 | {true, ReqData, Context}. 60 | 61 | is_authorized(ReqData, Context) -> 62 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 63 | 64 | %%-------------------------------------------------------------------- 65 | 66 | user(ReqData) -> 67 | rabbit_auth_backend_internal:lookup_user(rabbit_mgmt_util:id(user, ReqData)). 68 | 69 | put_user(User, ActingUser) -> 70 | put_user(User, undefined, ActingUser). 71 | 72 | put_user(User, Version, ActingUser) -> 73 | rabbit_auth_backend_internal:put_user(User, Version, ActingUser). 74 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_user_limit.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) 2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_user_limit). 9 | 10 | -export([init/2, 11 | content_types_accepted/2, is_authorized/2, 12 | allowed_methods/2, accept_content/2, 13 | delete_resource/2]). 14 | -export([variances/2]). 15 | 16 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 17 | -include_lib("rabbit_common/include/rabbit.hrl"). 18 | 19 | %%-------------------------------------------------------------------- 20 | 21 | init(Req, _State) -> 22 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 23 | 24 | variances(Req, Context) -> 25 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 26 | 27 | content_types_accepted(ReqData, Context) -> 28 | {[{{<<"application">>, <<"json">>, '*'}, accept_content}], ReqData, Context}. 29 | 30 | allowed_methods(ReqData, Context) -> 31 | {[<<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}. 32 | 33 | accept_content(ReqData0, Context = #context{user = #user{username = ActingUser}}) -> 34 | case rabbit_mgmt_util:id(user, ReqData0) of 35 | not_found -> 36 | rabbit_mgmt_util:not_found(user_not_found, ReqData0, Context); 37 | Username -> 38 | rabbit_mgmt_util:with_decode( 39 | [value], ReqData0, Context, 40 | fun([Value], _Body, ReqData) -> 41 | Limit = #{name(ReqData) => Value}, 42 | case rabbit_auth_backend_internal:set_user_limits(Username, Limit, ActingUser) of 43 | ok -> 44 | {true, ReqData, Context}; 45 | {error_string, Reason} -> 46 | rabbit_mgmt_util:bad_request( 47 | list_to_binary(Reason), ReqData, Context) 48 | end 49 | end) 50 | end. 51 | 52 | delete_resource(ReqData, Context = #context{user = #user{username = ActingUser}}) -> 53 | ok = rabbit_auth_backend_internal:clear_user_limits( 54 | rabbit_mgmt_util:id(user, ReqData), name(ReqData), ActingUser), 55 | {true, ReqData, Context}. 56 | 57 | is_authorized(ReqData, Context) -> 58 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 59 | 60 | %%-------------------------------------------------------------------- 61 | 62 | name(ReqData) -> rabbit_mgmt_util:id(name, ReqData). 63 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_user_limits.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) 2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_user_limits). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, 11 | resource_exists/2, is_authorized/2, allowed_methods/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | allowed_methods(ReqData, Context) -> 26 | {[<<"GET">>, <<"OPTIONS">>], ReqData, Context}. 27 | 28 | is_authorized(ReqData, Context) -> 29 | rabbit_mgmt_util:is_authorized_vhost_visible(ReqData, Context). 30 | 31 | content_types_provided(ReqData, Context) -> 32 | {[{<<"application/json">>, to_json}], ReqData, Context}. 33 | 34 | resource_exists(ReqData, Context) -> 35 | {case user(ReqData) of 36 | none -> true; 37 | Username -> rabbit_auth_backend_internal:exists(Username) 38 | end, ReqData, Context}. 39 | 40 | to_json(ReqData, Context) -> 41 | rabbit_mgmt_util:reply_list(limits(ReqData, Context), [], ReqData, Context). 42 | 43 | limits(ReqData, _Context) -> 44 | case user(ReqData) of 45 | none -> 46 | [ [{user, internal_user:get_username(U)}, {value, maps:to_list(internal_user:get_limits(U))}] 47 | || U <- rabbit_auth_backend_internal:all_users(), 48 | internal_user:get_limits(U) =/= #{}]; 49 | Username when is_binary(Username) -> 50 | case rabbit_auth_backend_internal:get_user_limits(Username) of 51 | Value when is_map(Value) -> 52 | case maps:size(Value) of 53 | 0 -> []; 54 | _ -> [[{user, Username}, {value, maps:to_list(Value)}]] 55 | end; 56 | undefined -> 57 | [] 58 | end 59 | end. 60 | %%-------------------------------------------------------------------- 61 | 62 | user(ReqData) -> 63 | rabbit_mgmt_util:id(user, ReqData). 64 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_users.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_mgmt_wm_users). 9 | 10 | -export([init/2, to_json/2, 11 | content_types_provided/2, 12 | is_authorized/2, allowed_methods/2]). 13 | -export([variances/2]). 14 | -export([users/1]). 15 | 16 | -import(rabbit_misc, [pget/2]). 17 | 18 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 19 | -include_lib("rabbit_common/include/rabbit.hrl"). 20 | 21 | %%-------------------------------------------------------------------- 22 | 23 | init(Req, [Mode]) -> 24 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), {Mode, #context{}}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | allowed_methods(ReqData, Context) -> 33 | {[<<"HEAD">>, <<"GET">>, <<"OPTIONS">>], ReqData, Context}. 34 | 35 | to_json(ReqData, {Mode, Context}) -> 36 | rabbit_mgmt_util:reply_list(users(Mode), ReqData, Context). 37 | 38 | is_authorized(ReqData, {Mode, Context}) -> 39 | {Res, Req2, Context2} = rabbit_mgmt_util:is_authorized_admin(ReqData, Context), 40 | {Res, Req2, {Mode, Context2}}. 41 | 42 | %%-------------------------------------------------------------------- 43 | 44 | users(all) -> 45 | [begin 46 | {ok, User} = rabbit_auth_backend_internal:lookup_user(pget(user, U)), 47 | rabbit_mgmt_format:internal_user(User) 48 | end || U <- rabbit_auth_backend_internal:list_users()]; 49 | users(without_permissions) -> 50 | lists:foldl(fun(U, Acc) -> 51 | Username = pget(user, U), 52 | case rabbit_auth_backend_internal:list_user_permissions(Username) of 53 | [] -> 54 | {ok, User} = rabbit_auth_backend_internal:lookup_user(Username), 55 | [rabbit_mgmt_format:internal_user(User) | Acc]; 56 | _ -> 57 | Acc 58 | end 59 | end, [], rabbit_auth_backend_internal:list_users()). 60 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_users_bulk_delete.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_mgmt_wm_users_bulk_delete). 9 | 10 | -export([init/2, 11 | content_types_accepted/2, 12 | content_types_provided/2, 13 | is_authorized/2, 14 | allowed_methods/2, accept_content/2]). 15 | -export([variances/2]). 16 | 17 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 18 | -include_lib("rabbit_common/include/rabbit.hrl"). 19 | 20 | %%-------------------------------------------------------------------- 21 | 22 | init(Req, _State) -> 23 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 24 | 25 | variances(Req, Context) -> 26 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 27 | 28 | content_types_accepted(ReqData, Context) -> 29 | {[{'*', accept_content}], ReqData, Context}. 30 | 31 | content_types_provided(ReqData, Context) -> 32 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 33 | 34 | allowed_methods(ReqData, Context) -> 35 | {[<<"POST">>, <<"OPTIONS">>], ReqData, Context}. 36 | 37 | is_authorized(ReqData, Context) -> 38 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 39 | 40 | accept_content(ReqData0, Context = #context{user = #user{username = ActingUser}}) -> 41 | rabbit_mgmt_util:with_decode( 42 | [users], ReqData0, Context, 43 | fun([Users], _, ReqData) -> 44 | [rabbit_auth_backend_internal:delete_user(User, ActingUser) 45 | || User <- Users], 46 | {true, ReqData, Context} 47 | end). 48 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_vhost_restart.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) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_wm_vhost_restart). 9 | 10 | -export([init/2, resource_exists/2, is_authorized/2, 11 | allowed_methods/2, content_types_accepted/2, accept_content/2]). 12 | -export([variances/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("amqp_client/include/amqp_client.hrl"). 16 | 17 | %%-------------------------------------------------------------------- 18 | 19 | init(Req, _State) -> 20 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 21 | 22 | variances(Req, Context) -> 23 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 24 | 25 | allowed_methods(ReqData, Context) -> 26 | {[<<"POST">>, <<"OPTIONS">>], ReqData, Context}. 27 | 28 | resource_exists(ReqData, Context) -> 29 | VHost = id(ReqData), 30 | {rabbit_vhost:exists(VHost), ReqData, Context}. 31 | 32 | content_types_accepted(ReqData, Context) -> 33 | {[{'*', accept_content}], ReqData, Context}. 34 | 35 | accept_content(ReqData, Context) -> 36 | VHost = id(ReqData), 37 | NodeB = rabbit_mgmt_util:id(node, ReqData), 38 | Node = binary_to_atom(NodeB, utf8), 39 | case rabbit_vhost_sup_sup:start_vhost(VHost, Node) of 40 | {ok, _} -> 41 | {true, ReqData, Context}; 42 | {error, {already_started, _}} -> 43 | {true, ReqData, Context}; 44 | {error, Err} -> 45 | Message = io_lib:format("Request to node ~s failed with ~p", 46 | [Node, Err]), 47 | rabbit_mgmt_util:bad_request(list_to_binary(Message), ReqData, Context) 48 | end. 49 | 50 | is_authorized(ReqData, Context) -> 51 | rabbit_mgmt_util:is_authorized_admin(ReqData, Context). 52 | 53 | %%-------------------------------------------------------------------- 54 | 55 | id(ReqData) -> 56 | rabbit_mgmt_util:id(vhost, ReqData). 57 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_vhosts.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_mgmt_wm_vhosts). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([variances/2]). 12 | -export([basic/0, augmented/2]). 13 | 14 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 15 | -include_lib("rabbit_common/include/rabbit.hrl"). 16 | 17 | -define(BASIC_COLUMNS, ["name", "tracing", "pid"]). 18 | 19 | -define(DEFAULT_SORT, ["name"]). 20 | 21 | %%-------------------------------------------------------------------- 22 | 23 | init(Req, _State) -> 24 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 25 | 26 | variances(Req, Context) -> 27 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 28 | 29 | content_types_provided(ReqData, Context) -> 30 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 31 | 32 | to_json(ReqData, Context = #context{user = User}) -> 33 | try 34 | Basic = [rabbit_vhost:info(V) 35 | || V <- rabbit_mgmt_util:list_visible_vhosts(User)], 36 | Data = rabbit_mgmt_util:augment_resources(Basic, ?DEFAULT_SORT, 37 | ?BASIC_COLUMNS, ReqData, 38 | Context, fun augment/2), 39 | rabbit_mgmt_util:reply(Data, ReqData, Context) 40 | catch 41 | {error, invalid_range_parameters, Reason} -> 42 | rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context) 43 | end. 44 | 45 | is_authorized(ReqData, Context) -> 46 | rabbit_mgmt_util:is_authorized(ReqData, Context). 47 | 48 | %%-------------------------------------------------------------------- 49 | 50 | augment(Basic, ReqData) -> 51 | case rabbit_mgmt_util:disable_stats(ReqData) of 52 | false -> 53 | rabbit_mgmt_db:augment_vhosts(Basic, rabbit_mgmt_util:range(ReqData)); 54 | true -> 55 | Basic 56 | end. 57 | 58 | augmented(ReqData, #context{user = User}) -> 59 | case rabbit_mgmt_util:disable_stats(ReqData) of 60 | false -> 61 | rabbit_mgmt_db:augment_vhosts( 62 | [rabbit_vhost:info(V) || V <- rabbit_mgmt_util:list_visible_vhosts(User)], 63 | rabbit_mgmt_util:range(ReqData)); 64 | true -> 65 | [rabbit_vhost:info(V) || V <- rabbit_mgmt_util:list_visible_vhosts(User)] 66 | end. 67 | 68 | basic() -> 69 | rabbit_vhost:info_all([name]). 70 | -------------------------------------------------------------------------------- /src/rabbit_mgmt_wm_whoami.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_mgmt_wm_whoami). 9 | 10 | -export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). 11 | -export([variances/2]). 12 | 13 | -include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). 14 | -include_lib("rabbit_common/include/rabbit.hrl"). 15 | 16 | %%-------------------------------------------------------------------- 17 | 18 | init(Req, _State) -> 19 | {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. 20 | 21 | variances(Req, Context) -> 22 | {[<<"accept-encoding">>, <<"origin">>], Req, Context}. 23 | 24 | content_types_provided(ReqData, Context) -> 25 | {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. 26 | 27 | to_json(ReqData, Context = #context{user = User}) -> 28 | FormattedUser = rabbit_mgmt_format:user(User), 29 | Expiration = case application:get_env(rabbitmq_management, login_session_timeout) of 30 | undefined -> []; 31 | {ok, Val} -> [{login_session_timeout, Val}] 32 | end, 33 | rabbit_mgmt_util:reply(FormattedUser ++ Expiration, ReqData, Context). 34 | 35 | is_authorized(ReqData, Context) -> 36 | rabbit_mgmt_util:is_authorized(ReqData, Context). 37 | -------------------------------------------------------------------------------- /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_management, 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/certs/cacert.pem: -------------------------------------------------------------------------------- 1 | I'm not a certificate 2 | -------------------------------------------------------------------------------- /test/config_schema_SUITE_data/certs/cert.pem: -------------------------------------------------------------------------------- 1 | I'm not a certificate 2 | -------------------------------------------------------------------------------- /test/config_schema_SUITE_data/certs/key.pem: -------------------------------------------------------------------------------- 1 | I'm not a certificate 2 | -------------------------------------------------------------------------------- /test/config_schema_SUITE_data/rabbit-mgmt/access.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/543906f01ccd0344aff648f21bb6b5156b2a2ca2/test/config_schema_SUITE_data/rabbit-mgmt/access.log -------------------------------------------------------------------------------- /test/rabbit_mgmt_runtime_parameters_util.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_mgmt_runtime_parameters_util). 9 | -behaviour(rabbit_runtime_parameter). 10 | -behaviour(rabbit_policy_validator). 11 | 12 | -include_lib("rabbit_common/include/rabbit.hrl"). 13 | 14 | -export([validate/5, notify/5, notify_clear/4]). 15 | -export([register/0, unregister/0]). 16 | -export([validate_policy/1]). 17 | -export([register_policy_validator/0, unregister_policy_validator/0]). 18 | 19 | %---------------------------------------------------------------------------- 20 | 21 | register() -> 22 | rabbit_registry:register(runtime_parameter, <<"test">>, ?MODULE). 23 | 24 | unregister() -> 25 | rabbit_registry:unregister(runtime_parameter, <<"test">>). 26 | 27 | validate(_, <<"test">>, <<"good">>, _Term, _User) -> ok; 28 | validate(_, <<"test">>, <<"maybe">>, <<"good">>, _User) -> ok; 29 | validate(_, <<"test">>, <<"admin">>, _Term, none) -> ok; 30 | validate(_, <<"test">>, <<"admin">>, _Term, User) -> 31 | case lists:member(administrator, User#user.tags) of 32 | true -> ok; 33 | false -> {error, "meh", []} 34 | end; 35 | validate(_, <<"test">>, _, _, _) -> {error, "meh", []}. 36 | 37 | notify(_, _, _, _, _) -> ok. 38 | notify_clear(_, _, _, _) -> ok. 39 | 40 | %---------------------------------------------------------------------------- 41 | 42 | register_policy_validator() -> 43 | rabbit_registry:register(policy_validator, <<"testeven">>, ?MODULE), 44 | rabbit_registry:register(policy_validator, <<"testpos">>, ?MODULE). 45 | 46 | unregister_policy_validator() -> 47 | rabbit_registry:unregister(policy_validator, <<"testeven">>), 48 | rabbit_registry:unregister(policy_validator, <<"testpos">>). 49 | 50 | validate_policy([{<<"testeven">>, Terms}]) when is_list(Terms) -> 51 | case length(Terms) rem 2 =:= 0 of 52 | true -> ok; 53 | false -> {error, "meh", []} 54 | end; 55 | 56 | validate_policy([{<<"testpos">>, Terms}]) when is_list(Terms) -> 57 | case lists:all(fun (N) -> is_integer(N) andalso N > 0 end, Terms) of 58 | true -> ok; 59 | false -> {error, "meh", []} 60 | end; 61 | 62 | validate_policy(_) -> 63 | {error, "meh", []}. 64 | -------------------------------------------------------------------------------- /test/rabbit_mgmt_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) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | %% 7 | 8 | -module(rabbit_mgmt_test_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, [parallel], [ 23 | tokenise_test, 24 | pack_binding_test, 25 | path_prefix_test 26 | ]} 27 | ]. 28 | 29 | %% ------------------------------------------------------------------- 30 | %% Setup/teardown. 31 | %% ------------------------------------------------------------------- 32 | 33 | init_per_group(_, Config) -> 34 | Config. 35 | 36 | end_per_group(_, Config) -> 37 | Config. 38 | 39 | %% ------------------------------------------------------------------- 40 | %% Test cases. 41 | %% ------------------------------------------------------------------- 42 | 43 | tokenise_test(_Config) -> 44 | [] = rabbit_mgmt_format:tokenise(""), 45 | ["foo"] = rabbit_mgmt_format:tokenise("foo"), 46 | ["foo", "bar"] = rabbit_mgmt_format:tokenise("foo~bar"), 47 | ["foo", "", "bar"] = rabbit_mgmt_format:tokenise("foo~~bar"), 48 | ok. 49 | 50 | pack_binding_test(_Config) -> 51 | assert_binding(<<"~">>, 52 | <<"">>, []), 53 | assert_binding(<<"foo">>, 54 | <<"foo">>, []), 55 | assert_binding(<<"foo%7Ebar%2Fbash">>, 56 | <<"foo~bar/bash">>, []), 57 | assert_binding(<<"foo%7Ebar%7Ebash">>, 58 | <<"foo~bar~bash">>, []), 59 | ok. 60 | 61 | path_prefix_test(_Config) -> 62 | Got0 = rabbit_mgmt_util:get_path_prefix(), 63 | ?assertEqual("", Got0), 64 | 65 | Pfx0 = "/custom-prefix", 66 | application:set_env(rabbitmq_management, path_prefix, Pfx0), 67 | Got1 = rabbit_mgmt_util:get_path_prefix(), 68 | ?assertEqual(Pfx0, Got1), 69 | 70 | Pfx1 = "custom-prefix", 71 | application:set_env(rabbitmq_management, path_prefix, Pfx1), 72 | Got2 = rabbit_mgmt_util:get_path_prefix(), 73 | ?assertEqual(Pfx0, Got2), 74 | 75 | Pfx2 = <<"custom-prefix">>, 76 | application:set_env(rabbitmq_management, path_prefix, Pfx2), 77 | Got3 = rabbit_mgmt_util:get_path_prefix(), 78 | ?assertEqual(Pfx0, Got3). 79 | 80 | %%-------------------------------------------------------------------- 81 | 82 | assert_binding(Packed, Routing, Args) -> 83 | case rabbit_mgmt_format:pack_binding_props(Routing, Args) of 84 | Packed -> 85 | ok; 86 | Act -> 87 | throw({pack, Routing, Args, expected, Packed, got, Act}) 88 | end. 89 | --------------------------------------------------------------------------------