Management HTTP API
The RabbitMQ-compatible management HTTP subset on port 15672 — endpoints, authentication, tags, visibility, and definitions export/import.
The connector can serve an opt-in, read-mostly subset of RabbitMQ's management HTTP API —
/api/overview, /api/queues, /api/exchanges, /api/bindings, /api/aliveness-test, plus
definitions.json export and import — so tools written against RabbitMQ (rabbitmqadmin, CI
health checks, Terraform providers, ops scripts) keep working. It runs on a second, dedicated
HTTP listener, never the dashboard's own /api, and shapes its replies on RabbitMQ 4.3.4,
measured against a real broker.
Enabling
| Field | Default | Env var |
|---|---|---|
Connectors.Amqp.Management.Enable | false | CONNECTORS_AMQP_MANAGEMENT_ENABLE |
Connectors.Amqp.Management.Port | 15672 (RabbitMQ's own management port) | CONNECTORS_AMQP_MANAGEMENT_PORT |
[Connectors.Amqp.Management]
Enable = true
Port = 15672The listener starts only beside a running AMQP 0-9-1 connector: if it is enabled but the connector did not start (disabled, or it failed open), the server logs a warning and continues without the management listener. A bind failure on the management port is a soft-fail like every other AMQP listener — logged, and the server continues with everything else running.
Port conflicts are refused at boot and on every settings save: the management port must
differ from the core gRPC/REST/HTTP ports, the shared AMQP 5672/5671 ports, and the MQTT, STOMP,
AWS, GCP and Kafka ports. The check runs whenever Management.Enable = true, independent of
Connectors.Amqp.Enable.
TLS follows the server-wide security mode, on the same port. There is no separate TLS port:
when the global Security block configures a mode other than none, the listener serves TLS or
mutual TLS on the one configured port; otherwise it serves plain HTTP.
While the broker is not ready, every request — including one with no Authorization header —
gets 503 with {"error":"service_unavailable","reason":"broker not ready"}.
Authentication
HTTP Basic, checked against Connectors.Amqp.Credentials — the same connector-local credential
store SASL PLAIN/AMQPLAIN uses, in the same order:
- A credential store is configured: both the username and password are checked against it.
- No store, but
Authentication.Enable = true: the Basic password must be a valid KubeMQ platform token; the username is not checked. - No store and
Authentication.Enable = false: any credentials are accepted.
No certificate logins. SASL EXTERNAL has no equivalent here — HTTP Basic is the only
mechanism this listener offers, whatever Connectors.Amqp.SslCertLogin is set to.
A wrong password, an unknown username, and an empty username all produce the byte-identical reply, so a client can never use the response to enumerate valid usernames:
{"error":"not_authorized","reason":"Not_Authorized"}A request with no Authorization header gets an empty body and the challenge header
WWW-Authenticate: Basic realm="RabbitMQ Management" with status 401.
Tags
Every endpoint requires any one of RabbitMQ's four management-class tags on the
authenticated user — management, policymaker, monitoring, administrator — configured per
credential via Connectors.Amqp.Credentials[].Tags. A store user with none of the four is
refused on every route:
{"error":"not_authorised","reason":"Not management user"}GET/POST /api/definitions additionally require the administrator tag; a management-class
user without it gets {"error":"not_authorised","reason":"Not administrator user"}.
A platform-token login, and the no-store/no-authentication login, both count as
administrator — by policy, not by a tag they carry — so they reach every endpoint,
including both definitions routes.
monitoring (or administrator) widens GET /api/overview's object_totals/queue_totals to
every vhost rather than just the caller's own visible set. It does not widen any object
list — measured RabbitMQ behavior, not a KubeMQ choice.
Visibility
A store user's Permissions entries (see
Users and permissions) also scope what the
listener shows: a user holding at least one entry sees only the vhosts it has an entry for (a
wildcard Vhost: "" entry sees every vhost); a user with no entries, a platform token, and the
no-authentication login all see every vhost. A store user tagged administrator also sees every
vhost regardless of its entries, as RabbitMQ 4.3.4 does.
When platform (Casbin) authorization is enabled, list endpoints additionally filter through the
same Read check the wire runs — a queue absent from /api/queues because the caller's policy
denies Read on it is the same decision basic.consume would make.
Two 404 bodies, for two different reasons:
| When | Body |
|---|---|
| The caller cannot see the vhost or object at all — whether or not it exists | {"error":"not_found","reason":"Not Found"} |
| The caller can see the vhost, but the named object does not exist; or the path names nothing | {"error":"Object Not Found","reason":"Not Found"} |
RabbitMQ tells a scoped caller when a vhost does not exist; this connector never makes that distinction, so the body never discloses existence to a caller not permitted to see it.
Endpoints
| Method & path | Fields emitted |
|---|---|
GET /api/overview | cluster_name, exchange_types, management_version, object_totals{channels, connections, exchanges, queues[, consumers]}, product_name, product_version, queue_totals{messages, messages_ready, messages_unacknowledged}, rabbitmq_version |
GET /api/queues, /api/queues/{vhost}, /api/queues/{vhost}/{name} | arguments, auto_delete, consumers, durable, exclusive, messages, messages_ready, messages_unacknowledged, name, state (always "running"), type (the declared x-queue-type, else "classic"), vhost |
GET /api/exchanges, /api/exchanges/{vhost}, /api/exchanges/{vhost}/{name} | arguments, auto_delete, durable, internal, name, type, vhost — includes the pre-declared exchanges |
GET /api/bindings, /api/bindings/{vhost} | source, vhost, destination, destination_type, routing_key, arguments, properties_key — includes one synthesized default-exchange binding per queue |
GET /api/aliveness-test/{vhost} | {"status":"ok"} on success; {"status":"failed","reason":"<text>"} on failure (503) |
GET /api/definitions | administrator only — see Definitions export |
POST /api/definitions | administrator only — see Definitions import |
Message counts come from the same computation the dashboard uses, so they can lag the true
state by up to one snapshot refresh (about 5 seconds) — the same lag RabbitMQ's own default
stats emission has. Connection and channel counts in object_totals are node-local;
topology and message counts are cluster-wide.
properties_key is RabbitMQ's own form encoding of the routing key: [A-Za-z0-9._-] kept,
a space becomes +, every other byte becomes % plus two capital hex digits (orders.# →
orders.%23), and an empty key encodes to ~. A binding that carries arguments omits it.
product_name is KubeMQ, never RabbitMQ. rabbitmq_version, management_version and
rabbit_version are all 4.3.4 — the API level these shapes mirror, for tools that branch on
the version string, not a claim about what product answered.
Aliveness
GET /api/aliveness-test/{vhost} runs a real round-trip through the connector's own
topology and message path: it declares a server-named queue (amq.gen-…, never the literal
aliveness-test, so it cannot collide with a queue you own), publishes one message to it
through the default exchange, receives it back and compares the body, then deletes the queue —
under a 3-second deadline for the whole round-trip.
The check needs a real permission on the vhost, not just visibility: a store user with
Permissions entries, none covering the vhost, is refused — 401 with
{"error":"not_authorised","reason":"Access refused."} if it can still see the vhost (an
administrator), the usual 404 otherwise.
Definitions export
GET /api/definitions, administrator only. Contains vhosts, queues, exchanges
(excluding the pre-declared ones), bindings, users (name and tags only), and
permissions (exact-vhost entries only — a wildcard Vhost: "" entry has no RabbitMQ form and
is omitted). topic_permissions, policies, parameters and global_parameters are always
empty arrays.
The export never contains a password, a password hash, or a hashing algorithm name.
Definitions import
POST /api/definitions, administrator only, applies each entry through the same
declare/bind code path an AMQP client's own queue.declare/exchange.declare/queue.bind
takes — the same argument validation, the same durable persistence, the same cluster
replication. Administrator import bypasses the connector's own permission layer for every
create, mirroring RabbitMQ; platform (Casbin) authorization still runs per entry.
Every entry in the request body is attempted, in order — vhosts, users, permissions, exchanges, queues, bindings — and one entry's refusal never stops the ones after it. RabbitMQ stops at the first error; this connector deliberately does not, so a migration run reports everything that needs fixing in one pass.
204 No Content: every entry applied, with no caveat.400 Bad Request: every entry was still attempted — readapplied,unappliedandreportto find out which:
{
"error": "bad_request",
"reason": "<the first entry that was not applied>",
"applied": 3,
"unapplied": 2,
"report": [
{"kind": "policy", "vhost": "m3v", "name": "m3policy", "applied": false, "reason": "policies are not supported"}
]
}Users and permissions are configuration, not runtime state — import never writes
Connectors.Amqp.Credentials. A users[] entry counts as applied only when the configured
store already holds that username with the same tag set, and — when the entry carries a
password_hash — that hash verifies against the configured password
(rabbit_password_hashing_sha256 and sha512 are verified; md5 and unknown algorithms are
reported by name, unverified). Anything not already matching is reported, naming the config path
to edit. See the migration recipe in
Moving topology with definitions export/import.
Reported and not applied: policies, runtime parameters, topic permissions, operator
policies, vhost limits, and an unsupported exchange type. Exchange-to-exchange bindings
(destination_type: "exchange") are applied.
Reported but still applied (a warning): a queue declared with an inert argument is still
created; the argument is named in report with applied: true. x-queue-type: "classic" and
x-queue-mode are not reported at all.
Silently accepted as RabbitMQ export noise: an empty global_parameters cluster_tags
value, internal_cluster_id, the amq.rabbitmq.log/amq.rabbitmq.trace exchanges, and a
queue's x-queue-type: "classic" / x-queue-mode arguments — every fresh RabbitMQ export
carries them, and reporting them would mean no real migration ever reaches 204.
Not implemented
A tool that assumes RabbitMQ parity needs to know the boundary before it hits it:
- The management UI is not served — this listener answers JSON only.
- Every write endpoint except
POST /api/definitions: noPUT/DELETEfor queues, exchanges, bindings, users, permissions, vhosts or policies. /api/connections,/api/channels,/api/nodes,/api/vhosts,/api/whoami,/api/health/checks/*— not served.- Pagination (
page,page_size) andcolumns=— every list always answers in full. - Rates,
message_stats, memory and node fields are not emitted. - The firehose tracer and log forwarder behind
amq.rabbitmq.traceandamq.rabbitmq.log: both exchanges exist and are listed, but nothing is ever published to them. - A known path with an unsupported HTTP method answers
405with an empty body and the measuredAllowheader, never the404an unregistered path gets.
Every field or endpoint in this list is simply absent from a reply, never emitted as a zero
or a placeholder — a tool checking for a field's presence sees it is missing rather than being
misled by a confident-looking 0.
Related
Users and permissions
The credential store this listener authenticates against, the per-vhost permission triple, and tags.
Migrating from RabbitMQ
The definitions export/import recipe and the full deviation list.
Configuration reference
Management.Enable, Management.Port, and every other Connectors.Amqp.* field.
Connections & Observability
The dashboard's own /api/amqp endpoints, metrics, and audit events — a different listener from this one.
Was this page helpful?
Error & Reason Codes
The AMQP 0-9-1 channel and connection close codes (311–541) the KubeMQ RabbitMQ connector returns — their meanings, triggers, and channel-vs-connection scope.
Migrating from RabbitMQ
Point a RabbitMQ app at KubeMQ by changing only the AMQP 0-9-1 connection string — users, transactions, DLX, the management API, and every deviation.