├── test ├── config_schema_SUITE_data │ ├── rabbit-mgmt │ │ └── access.log │ └── certs │ │ ├── cacert.pem │ │ ├── cert.pem │ │ └── key.pem ├── config_schema_SUITE.erl ├── rabbit_mgmt_runtime_parameters_util.erl └── rabbit_mgmt_test_unit_SUITE.erl ├── priv └── www │ ├── css │ └── evil.css │ ├── js │ ├── tmpl │ │ ├── status.ejs │ │ ├── 404.ejs │ │ ├── popup.ejs │ │ ├── login_uaa.ejs │ │ ├── channels.ejs │ │ ├── list-exchanges.ejs │ │ ├── memory-bar.ejs │ │ ├── memory-table.ejs │ │ ├── registry.ejs │ │ ├── login.ejs │ │ ├── columns-options.ejs │ │ ├── msg-detail-deliveries.ejs │ │ ├── messages.ejs │ │ ├── cluster-name.ejs │ │ ├── policy.ejs │ │ ├── msg-detail-publishes.ejs │ │ ├── consumers.ejs │ │ ├── rate-options.ejs │ │ ├── add-binding.ejs │ │ ├── feature-flags.ejs │ │ ├── vhost.ejs │ │ ├── layout.ejs │ │ ├── publish.ejs │ │ ├── bindings.ejs │ │ ├── binary.ejs │ │ ├── partition.ejs │ │ ├── exchange.ejs │ │ └── permissions.ejs │ └── singular │ │ ├── postauth.html │ │ ├── postaccess.html │ │ └── client_frame.html │ ├── favicon.ico │ ├── img │ ├── bg-red.png │ ├── expand.png │ ├── bg-binary.png │ ├── collapse.png │ ├── bg-red-dark.png │ ├── bg-green-dark.png │ └── bg-yellow-dark.png │ ├── cli │ └── index.html │ └── index.html ├── Caddyfile ├── .github ├── workflows │ └── test-jobs │ │ └── 10-dialyzer.yaml ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── src ├── rabbit_mgmt_wm_redirect.erl ├── rabbit_mgmt_extension.erl ├── rabbit_mgmt_sup_sup.erl ├── rabbit_mgmt_csp.erl ├── rabbit_mgmt_db_cache_sup.erl ├── rabbit_mgmt_hsts.erl ├── rabbit_mgmt_load_definitions.erl ├── rabbit_mgmt_headers.erl ├── rabbit_mgmt_wm_extensions.erl ├── rabbit_mgmt_wm_global_parameters.erl ├── rabbit_mgmt_wm_permissions.erl ├── rabbit_mgmt_wm_whoami.erl ├── rabbit_mgmt_wm_topic_permissions.erl ├── rabbit_mgmt_wm_queue_purge.erl ├── rabbit_mgmt_wm_feature_flags.erl ├── rabbit_mgmt_sup.erl ├── rabbit_mgmt_wm_users_bulk_delete.erl ├── rabbit_mgmt_wm_policies.erl ├── rabbit_mgmt_wm_operator_policies.erl ├── rabbit_mgmt_wm_permissions_vhost.erl ├── rabbit_mgmt_wm_topic_permissions_vhost.erl ├── rabbit_mgmt_wm_reset.erl ├── rabbit_mgmt_wm_connections_vhost.erl ├── rabbit_mgmt_wm_permissions_user.erl ├── rabbit_mgmt_wm_topic_permissions_user.erl ├── rabbit_mgmt_wm_channels.erl ├── rabbit_mgmt_wm_health_check_virtual_hosts.erl ├── rabbit_mgmt_wm_connections.erl ├── rabbit_mgmt_wm_channels_vhost.erl ├── rabbit_mgmt_wm_feature_flag_enable.erl ├── rabbit_mgmt_wm_nodes.erl ├── rabbit_mgmt_wm_connection_channels.erl ├── rabbit_mgmt_wm_vhost_restart.erl ├── rabbit_mgmt_wm_rebalance_queues.erl ├── rabbit_mgmt_wm_login.erl ├── rabbit_mgmt_wm_health_check_alarms.erl ├── rabbit_mgmt_wm_health_check_local_alarms.erl ├── rabbit_mgmt_wm_limits.erl ├── rabbit_mgmt_wm_auth.erl ├── rabbit_mgmt_wm_cluster_name.erl ├── rabbit_mgmt_wm_static.erl ├── rabbit_mgmt_wm_consumers.erl ├── rabbit_mgmt_wm_users.erl ├── rabbit_mgmt_wm_health_check_node_is_quorum_critical.erl ├── rabbit_mgmt_wm_health_check_node_is_mirror_sync_critical.erl ├── rabbit_mgmt_wm_user_limits.erl ├── rabbit_mgmt_wm_user_limit.erl ├── rabbit_mgmt_wm_queue_actions.erl ├── rabbit_mgmt_wm_limit.erl ├── rabbit_mgmt_wm_vhosts.erl ├── rabbit_mgmt_wm_channel.erl ├── rabbit_mgmt_wm_node_memory.erl ├── rabbit_mgmt_reset_handler.erl ├── rabbit_mgmt_wm_global_parameter.erl ├── rabbit_mgmt_wm_health_check_port_listener.erl ├── rabbit_mgmt_wm_user.erl ├── rabbit_mgmt_wm_node.erl ├── rabbit_mgmt_wm_aliveness_test.erl ├── rabbit_mgmt_wm_exchanges.erl ├── rabbit_mgmt_wm_auth_attempts.erl ├── rabbit_mgmt_wm_healthchecks.erl ├── rabbit_mgmt_wm_parameters.erl └── rabbit_mgmt_wm_node_memory_ets.erl ├── LICENSE-ISC-cowboy ├── include └── rabbit_mgmt.hrl ├── LICENSE-MIT-Flot ├── LICENSE-MIT-jQuery ├── LICENSE-MIT-Sammy ├── LICENSE-MIT-EJS ├── scripts └── seed.sh ├── LICENSE-BSD-base64js ├── LICENSE ├── README.md ├── Makefile ├── CODE_OF_CONDUCT.md └── .travis.yml /test/config_schema_SUITE_data/rabbit-mgmt/access.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /priv/www/css/evil.css: -------------------------------------------------------------------------------- 1 | #login { text-align: center; } 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/status.ejs: -------------------------------------------------------------------------------- 1 | <%= text %> 2 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | :2015 2 | log stdout 3 | errors stderr 4 | root priv/www 5 | proxy /api localhost:15672 6 | -------------------------------------------------------------------------------- /priv/www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/favicon.ico -------------------------------------------------------------------------------- /priv/www/img/bg-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/bg-red.png -------------------------------------------------------------------------------- /priv/www/img/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/expand.png -------------------------------------------------------------------------------- /priv/www/img/bg-binary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/bg-binary.png -------------------------------------------------------------------------------- /priv/www/img/collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/collapse.png -------------------------------------------------------------------------------- /priv/www/img/bg-red-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/bg-red-dark.png -------------------------------------------------------------------------------- /priv/www/img/bg-green-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/bg-green-dark.png -------------------------------------------------------------------------------- /priv/www/img/bg-yellow-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/HEAD/priv/www/img/bg-yellow-dark.png -------------------------------------------------------------------------------- /priv/www/js/tmpl/404.ejs: -------------------------------------------------------------------------------- 1 |
The object you clicked on was not found; it may have been deleted on the server.
4 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/popup.ejs: -------------------------------------------------------------------------------- 1 || <%= group.name %> | 11 |
12 |
|
25 |
|---|
| Name | 5 |Description | 6 | <% if (show_enabled) { %> 7 |Enabled | 8 | <% } %> 9 |
|---|---|---|
| <%= fmt_string(item.name) %> | 16 |<%= fmt_string(item.description) %> | 17 | <% if (show_enabled) { %> 18 |<%= fmt_boolean(item.enabled) %> | 19 | <% } %> 20 |
...node not running...
25 | <% } %> 26 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/login.ejs: -------------------------------------------------------------------------------- 1 || Channel | 7 | <% } else { %> 8 |Queue | 9 | <% } %> 10 |deliver / get | 11 |ack | 12 |
|---|---|---|---|
| <%= link_channel(del.channel_details.name) %> | 20 | <% } else { %> 21 |<%= link_queue(del.queue.vhost, del.queue.name) %> | 22 | <% } %> 23 |<%= fmt_detail_rate(del.stats, 'deliver_get') %> | 24 |<%= fmt_detail_rate(del.stats, 'ack') %> | 25 |
... no deliveries ...
30 | <% } %> 31 | -------------------------------------------------------------------------------- /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_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_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 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/messages.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | for (var i = 0; i < msgs.length; i++) { 3 | var msg = msgs[i]; 4 | %> 5 |The server reported <%= msg.message_count %> messages remaining.
8 || Exchange | 11 |<%= fmt_exchange(msg.exchange) %> | 12 |
|---|---|
| Routing Key | 15 |<%= fmt_string(msg.routing_key) %> | 16 |
| Redelivered | 19 |<%= fmt_boolean(msg.redelivered) %> | 20 |
| Properties | 23 |<%= fmt_table_short(msg.properties) %> | 24 |
| 27 | Payload 28 | <%= msg.payload_bytes %> bytes 29 | Encoding: <%= msg.payload_encoding %> 30 | | 31 |
32 | <%= fmt_maybe_wrap(msg.payload, msg.payload_encoding) %>33 | |
34 |
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 || Pattern | 9 |<%= fmt_string(policy.pattern) %> | 10 |
|---|---|
| Apply to | 13 |<%= fmt_string(policy['apply-to']) %> | 14 |
| Definition | 17 |<%= fmt_table_short(policy.definition) %> | 18 |
| Priority | 21 |<%= fmt_string(policy.priority) %> | 22 |
| Exchange | 10 | <% } else if (mode == 'exchange-incoming') { %> 11 |Channel | 12 | <% } else if (mode == 'exchange-outgoing') { %> 13 |Queue | 14 | <% } else { %> 15 |Exchange | 16 | <% } %> 17 |publish | 18 | <% if (col_confirm) { %> 19 |confirm | 20 | <% } %> 21 |
|---|---|---|---|---|---|
| <%= link_exchange(pub.exchange.vhost, pub.exchange.name) %> | 30 | <% } else if (mode == 'exchange-incoming') { %> 31 |<%= link_channel(pub.channel_details.name) %> | 32 | <% } else if (mode == 'exchange-outgoing') { %> 33 |<%= link_queue(pub.queue.vhost, pub.queue.name) %> | 34 | <% } else { %> 35 |<%= link_exchange(pub.exchange.vhost, pub.exchange.name) %> | 36 | <% } %> 37 |<%= fmt_detail_rate(pub.stats, 'publish') %> | 38 | <% if (col_confirm) { %> 39 |<%= fmt_detail_rate(pub.stats, 'confirm') %> | 40 | <% } %> 41 |
... no publishes ...
46 | <% } %> 47 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /priv/www/js/tmpl/consumers.ejs: -------------------------------------------------------------------------------- 1 | <% if (consumers.length > 0) { %> 2 || Channel | 7 |Consumer tag | 8 | <% } else { %> 9 |Consumer tag | 10 |Queue | 11 | <% } %> 12 |Ack required | 13 |Exclusive | 14 |Prefetch count | 15 |Active | 16 |Activity status | 17 |Arguments | 18 |
|---|---|---|---|---|---|---|---|---|---|
| <%= link_channel(consumer.channel_details.name) %> | 27 |<%= fmt_string(consumer.consumer_tag) %> | 28 | <% } else { %> 29 |<%= fmt_string(consumer.consumer_tag) %> | 30 |<%= link_queue(consumer.queue.vhost, consumer.queue.name) %> | 31 | <% } %> 32 |<%= fmt_boolean(consumer.ack_required) %> | 33 |<%= fmt_boolean(consumer.exclusive) %> | 34 |<%= consumer.prefetch_count %> | 35 |<%= fmt_boolean(consumer.active) %> | 36 |<%= fmt_activity_status(consumer.activity_status) %> | 37 |<%= fmt_table_short(consumer.arguments) %> | 38 |
... no consumers ...
43 | <% } %> 44 | -------------------------------------------------------------------------------- /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 | [](https://github.com/rabbitmq/rabbitmq-management/actions?query=workflow%3A%22Test+-+Erlang+22.3%22+branch%3A%22master%22) 10 | [](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 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | 57 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_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_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_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_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_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_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 | -------------------------------------------------------------------------------- /priv/www/cli/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
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 |
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 |
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 |
40 | Windows users will need to ensure Python is on
41 | their PATH, and invoke rabbitmqadmin as python.exe
42 | rabbitmqadmin.
43 |
| <%= fmt_sort('Name', 'name') %> | 12 |<%= fmt_sort('State', 'state') %> | 13 |Description | 14 |
|---|---|---|
| <%= fmt_string(feature_flag.name) %> | 31 |32 | <% if (feature_flag.state == "disabled") { %> 33 | 37 | <% } else { %> 38 | 41 | <%= fmt_string(feature_flag.state) %> 42 | 43 | <% } %> 44 | | 45 |
46 | <%= fmt_string(feature_flag.desc) %> 47 | <% if (feature_flag.doc_url) { %> 48 | 49 | <% } %> 50 | |
51 |
... no feature_flags ...
57 | <% } %> 58 |
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 |
| Tracing enabled: | 23 |<%= fmt_boolean(vhost.tracing) %> | 24 |||
|---|---|---|---|
| State: | 26 |
27 |
|
44 |
| To | 8 | <% } else { %> 9 |From | 10 | <% } %> 11 |Routing key | 12 |Arguments | 13 |14 | | |||||
|---|---|---|---|---|---|---|---|---|---|
| 24 | (Default exchange binding) 25 | | 26 | <% } else { %> 27 | <% if (mode == 'queue' || mode == 'exchange_destination') { %> 28 |29 | 30 | <%= link_exchange(binding.vhost, binding.source) %> 31 | 32 | | 33 | <% } else if (binding.destination_type == 'exchange') { %> 34 |35 | 36 | <%= link_exchange(binding.vhost, binding.destination) %> 37 | 38 | | 39 | <% } else { %> 40 |41 | 42 | <%= link_queue(binding.vhost, binding.destination) %> 43 | 44 | | 45 | <% } %> 46 |<%= fmt_string(binding.routing_key) %> | 47 |<%= fmt_table_short(binding.arguments) %> | 48 |49 | 57 | | 58 | <% } %> 59 ||||
... no bindings ...
66 | <% } %> 67 | -------------------------------------------------------------------------------- /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_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_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_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_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_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_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_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_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_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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 |
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 |
21 | The nature of the partition is as follows: 22 |
23 || Node | Was partitioned from | 26 |
|---|---|
| <%= fmt_node(partition.node) %> | 34 |
35 | <%
36 | for (var j = 0; j < partition.others.length; j++) {
37 | var other = partition.others[j];
38 | %>
39 | <%= other %> 40 | <% } %> 41 | |
42 |
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 |
77 | The values are: 78 |
79 || Node | net_ticktime |
|---|---|
| <%= nodes[i].name %> | 86 |<%= nodes[i].net_ticktime %> | 87 |
93 | This is a dangerous configuration; use of substantially
94 | unequal net_ticktime values can lead to partitions
95 | being falsely detected.
96 |
98 | More information on
100 | net_ticktime.
101 |
| Type | 15 |<%= fmt_exchange_type(exchange.type) %> | 16 |
|---|---|
| Features | 19 |<%= fmt_features(exchange) %> | 20 |
| Policy | 23 |<%= link_policy(exchange.vhost, exchange.policy) %> | 24 |
| 37 | <%= format('msg-detail-publishes', 38 | {'mode': 'exchange-incoming', 39 | 'object': exchange.incoming, 40 | 'label': 'Incoming '}) %> 41 | | 42 |43 | <%= format('msg-detail-publishes', 44 | {'mode': 'exchange-outgoing', 45 | 'object': exchange.outgoing, 46 | 'label': 'Outgoing '}) %> 47 | | 48 |
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 |⇓
72 | <% } %> 73 |This exchange
74 |⇓
75 | <%= format('bindings', {'mode': 'exchange_source', 'bindings': bindings_source}) %> 76 || User | 11 | <% } else { %> 12 |Virtual host | 13 | <% } %> 14 |Configure regexp | 15 |Write regexp | 16 |Read regexp | 17 |18 | |
|---|---|---|---|---|---|
| <%= link_user(permission.user) %> | 28 | <% } else { %> 29 |<%= link_vhost(permission.vhost) %> | 30 | <% } %> 31 |<%= fmt_string(permission.configure) %> | 32 |<%= fmt_string(permission.write) %> | 33 |<%= fmt_string(permission.read) %> | 34 |35 | 40 | | 41 |
... no permissions ...
47 | <% } %> 48 | 49 |