RabbitMQ ships with defaults built for a developer laptop: a guest user with a well-known password, an ANONYMOUS login mechanism, plaintext listeners and a management UI that stores credentials in the browser. In production the broker carries orders, payments, telemetry and job instructions, and every application that connects to it is a non-human identity with a password, certificate or token. This guide sets out how RabbitMQ authenticates and authorises clients, how to design users, virtual hosts and permissions, how to lock down the management plugin, and which settings belong in a production baseline. It is for platform and security engineers running self-managed RabbitMQ 4.x clusters.
Key takeaways
- Delete
guestand remove ANONYMOUS. The default user has the passwordguest, and the ANONYMOUS mechanism, enabled by default, lets unauthenticated clients act as the configured anonymous user. - One user per application, one vhost per tenant or environment. RabbitMQ's own deployment guidelines recommend both, because they make permissions, correlation and rotation workable.
- Permissions are three regular expressions per vhost. Configure, write and read patterns decide everything a client can do;
.*everywhere is the most common over-grant. - Management tags are privileged roles.
administratorcan create users, vhosts and permissions; give automation themonitoringtag with empty permissions, not admin. - TLS is opt-in, and so is encryption at rest. Disable plaintext listeners with
listeners.tcp = none, verify peers, protect the Erlang cookie, and encrypt the disk or the payloads because the broker does not.
How identity and access work in RabbitMQ
Every connection presents a password, JWT or X.509 certificate and names a virtual host. RabbitMQ authenticates the user, checks that the user has some permission in that vhost, then checks each operation against the user's permissions on the named exchange or queue. Authentication and authorisation are pluggable backends.
| Backend or mechanism | What it provides | When to use it | Watch out for |
|---|---|---|---|
| Internal database with PLAIN / AMQPLAIN | Users, salted password hashes (SHA-256 by default), permissions and tags stored in the broker | Small clusters, application users seeded from definitions | Passwords sent in the clear unless TLS is enforced; rotation is manual |
EXTERNAL with rabbitmq_auth_mechanism_ssl | Identity taken from the client certificate; any password is ignored | Fleets of similar clients, IoT, environments with an internal PKI | Certificate lifecycle and revocation become the access control |
| OAuth 2.0 (JWT) | Authorisation from token scopes such as rabbitmq.read:*/* and rabbitmq.tag:administrator, validated against auth_oauth2.resource_server_id | Management UI single sign-on; applications that already obtain tokens from an identity provider | Scope design; long token lifetimes; aliases that grant more than intended |
| LDAP | Authentication and authorisation from a directory | Human operators and organisations that manage service accounts in a directory | Directory availability; use the cache backend to reduce load |
| HTTP backend | Delegates decisions to an HTTP service you run | Custom policy | That service becomes part of the broker's trust boundary |
| ANONYMOUS | Unauthenticated clients act as anonymous_login_user (default guest) | Never in production | Enabled by default; remove it |
Defaults to remove on day one
- The
guestuser: a blank node creates the vhost/and userguestwith passwordguestand full access to/. By defaultguestmay only connect over the loopback interface, controlled byloopback_users. The access control guide strongly advises against settingloopback_users = none; delete the user instead. Importing definitions on first boot preventsguestbeing created at all. - The ANONYMOUS mechanism: list only the mechanisms you use, for example
auth_mechanisms.1 = PLAINandauth_mechanisms.2 = AMQPLAIN(or EXTERNAL), and setanonymous_login_user = none, as the production checklist shows. - Weak hashing for new users: the default module is
rabbit_password_hashing_sha256;rabbit_password_hashing_sha512is available andrabbit_password_hashing_md5exists only for backwards compatibility. A changed algorithm applies to newly created users, so re-create or reset existing ones.
Users, vhosts and permissions
Virtual hosts are the tenancy boundary: the same exchange or queue name refers to a different resource in each vhost, and a user with no permission in a vhost cannot connect to it. RabbitMQ's deployment guidelines say the default vhost is fine for a cluster dedicated to one system, and recommend a separate vhost per tenant and environment, such as project1_production and project1_development, in multi-tenant clusters.
Inside a vhost, a user's permissions are a triple of regular expressions matched against resource names:
| Permission | Covers | Examples of operations (AMQP 0-9-1) | Least-privilege pattern |
|---|---|---|---|
| configure | Creating, deleting or changing resources | exchange.declare, queue.declare, queue.delete | Only the queues the app owns, for example ^orders-svc\..*; ^$ for apps whose topology is pre-declared |
| write | Injecting messages, and the destination side of bindings | basic.publish (exchange), queue.bind (queue) | Only the exchanges it publishes to |
| read | Retrieving messages, and the source side of bindings | basic.consume, basic.get, queue.purge (queue) | Only the queues it consumes from |
- Deny with an empty pattern:
'^$'or''matches nothing and blocks that operation type entirely. - Server-named queues: server-generated names start
amq.genand the default exchange is checked asamq.default, so a consumer that uses exclusive server-named queues can be limited to'^(amq\.gen.*|amq\.default)$'. - Per-user prefixes: the internal backend expands
{username}and{vhost}(and{client_id}for MQTT) in patterns, so^{username}-.*gives each identity its own namespace. - Topic authorisation is opt-in: with the default backend, publishing to a topic exchange is always authorised if no topic permissions exist. Define topic permissions where routing keys carry meaning, especially for MQTT and STOMP clients. See the MQTT Security Guide.
- Changes are not instant: RabbitMQ may cache access control results per connection or channel, so a narrowed permission may only apply when the client reconnects.
Decision guidance: one user per application is the baseline the deployment guidelines recommend. For many instances of the same application, the guidelines describe a trade-off between per-instance credentials (better security) and shared credentials (simpler provisioning). Fleets of similar clients with fixed addresses are where X.509 or source IP range authorisation fit best; applications that already obtain tokens from an identity provider are where OAuth 2.0 fits.
Admin roles and privileged access
Management UI and HTTP API access is controlled by user tags, separately from resource permissions. New users have no tags.
| Tag | Adds | Who should hold it |
|---|---|---|
| (none) | No management plugin access | Every application user |
management | List the vhosts the user can reach; view queues, exchanges and bindings there; view and close own connections | Developers needing visibility in their own vhost |
policymaker | Management plus create and delete policies and parameters in reachable vhosts | Platform owners of a vhost |
monitoring | Management plus all vhosts, other users' connections and channels, node-level data and global statistics | Monitoring tools and on-call engineers |
administrator | Policymaker and monitoring plus create and delete vhosts, users and permissions, and close other users' connections | A small set of named operators and the deployment pipeline |
- Admin is still bound by resource permissions: the management guide notes that the
administratorormonitoringtag does not on its own grant access to exchanges, queues and bindings. But an administrator can grant themselves any permission, so treat the tag as full control of the cluster. - Monitoring identities: the documented pattern is a user tagged
monitoringwith empty configure, write and read permissions. That lets a collector list everything without publishing, consuming or deleting. - Erlang cookie and CLI access: nodes and CLI tools such as
rabbitmqctlauthenticate to each other with a shared secret, the Erlang cookie, held in a file. Anyone with the cookie and network access to the distribution port can administer the node. The production checklist says to restrict the file to the OS users that run RabbitMQ and the CLI, to generate it securely at deployment rather than copying a runtime-generated value, and to restrict access to the inter-node and CLI ports. - Single sign-on for humans: with OAuth 2.0 enabled for the management UI,
management.oauth_disable_basic_authdefaults to true, so only OAuth logins are accepted in the UI. Map identity provider groups torabbitmq.tag:scopes and keep administrator scopes for a small group. See the OAuth Scope Design Guide.
Integrations, API tokens and service accounts
Applications, shovels, federation links, exporters and deployment pipelines all hold broker credentials. Treat each as a service account with an owner, a scope and a rotation plan. See the Service Account Security Guide.
- Seed with definitions, not ad hoc commands: the deployment guidelines recommend importing vhosts, users, permissions and topology from a definitions file. Exported definitions contain password hashes and the hashing function, and the documentation says to treat user records as sensitive. Store definition files like secrets, and prefer pre-hashed passwords to plaintext values in them.
- Keep secrets out of plaintext configuration: values prefixed with
encrypted:inrabbitmq.confare decrypted at start-up;rabbitmqctl encrypt_conf_valueproduces them. Use this for LDAP bind passwords, the management credentials secret and similar values, and keep the passphrase in your secrets manager. - Federation and shovel URIs: these usually carry remote broker credentials; give them dedicated, narrowly scoped users and TLS (
amqps://) URIs. - Connection strings in application code: AMQP URIs with embedded passwords leak through repositories, CI logs and container images. Inject them at runtime from a secrets manager. See the Secrets Management Guide.
- Rotation: the access control guide describes routine rotation as changing the password (CLI or
PUT /api/users/{user}), closing existing connections withrabbitmqctl close_all_user_connections, and making sure applications reconnect with the new value. For a suspected leak it recommends deleting the user, which closes all its connections, then re-creating it with a new generated password and re-granting permissions. Clearing permissions alone does not close open connections. - Token-based clients: with OAuth 2.0, keep token lifetimes short, scope tokens to the vhost and resource (
rabbitmq.write:orders/orders-exchangestyle) and useauth_oauth2.scope_aliasescarefully, since one alias can expand into administrator scopes. See the JWT Security Guide.
TLS and network exposure
RabbitMQ listens on several ports, and the deployment guidelines split them into client ports, which applications must reach, and everything else, which should be limited to RabbitMQ nodes and CLI hosts.
| Port | Use | Exposure |
|---|---|---|
| 5672 / 5671 | AMQP 0-9-1 and AMQP 1.0, plain / TLS | Application networks only; prefer 5671 with listeners.tcp = none |
| 5552 / 5551 | Stream protocol, plain / TLS | Application networks if streams are used |
| 15672 / 15671 | Management UI, HTTP API and rabbitmqadmin, plain / TLS | Operator and monitoring networks only, never the internet |
| 1883 / 8883, 61613 / 61614 | MQTT and STOMP, plain / TLS (when plugins enabled) | Only if those plugins are needed |
| 15692 / 15691 | Prometheus metrics, plain / TLS | Monitoring network |
| 4369, 25672, 35672-35682 | epmd, inter-node and CLI distribution | Cluster nodes and CLI hosts only |
| 6000-6500 | Stream replication | Cluster nodes only |
- TLS-only listeners: set
listeners.tcp = noneandlisteners.ssl.default = 5671withssl_options.cacertfile,certfileandkeyfile. - Verify peers:
ssl_options.verify = verify_peerwithssl_options.fail_if_no_peer_cert = truerejects clients without a trusted certificate, which is also the basis for EXTERNAL authentication. See the mTLS Guide. - Test the result: check versions and cipher suites with a tool such as testssl.sh, as the deployment guidelines suggest.
- Inter-node TLS: recommended by the production checklist; it also means CLI tools must be configured for TLS.
- Management UI headers: set
management.hsts.policy(for examplemax-age=31536000; includeSubDomains) and review the CSP and CORS settings the management guide documents. - Browser-stored credentials: by default the management UI stores Basic credentials Base64-encoded in the browser's
localStorage, readable by anyone with developer tools or an XSS flaw. Setmanagement.credentials_encryption_secret(identical on every node) or move the UI to OAuth 2.0. - Data at rest: RabbitMQ does not encrypt message payloads or metadata on disk. Use volume encryption, end-to-end payload encryption by the applications, or both. See the Disk Encryption Guide.
Logging and detection
Failed authentication closes the connection and writes to the server log; for example, a remote attempt with guest is logged as "PLAIN login refused: user 'guest' can only connect via localhost". Log categories such as log.connection.level control connection logging detail. For structured audit, the rabbitmq_event_exchange plugin republishes internal events to the topic exchange amq.rabbitmq.event, with an empty body and details in message metadata.
| Event (routing key) | Why it matters | Suggested response |
|---|---|---|
user.authentication.failure | Password guessing, stale credentials after rotation, misconfigured clients | Alert on bursts per source or per user |
user.created, user.deleted | New or removed identities outside the definitions pipeline | Compare with change records |
user.tags.set | Possible grant of administrator | Alert on any change in production |
user.password.changed, user.password.cleared | Credential change or removal of password login | Confirm it matches a rotation |
permission.created, topic.permission.created | Permission widening | Review the pattern for .* |
vhost.created | New tenancy boundary or a staging area for abuse | Confirm ownership |
user.authentication.success | Logins by unexpected users or from unexpected networks | Baseline per application user |
Only trusted consumers should have read access to amq.rabbitmq.event, as the plugin documentation warns. Ship events and server logs to the SIEM; for metrics, the management guide recommends Prometheus over the management UI for production. See the SIEM Guide.
Metrics that show the controls are working:
- Users with
.*configure, write and read permissions in production vhosts (target zero outside the deployment identity). - Number of users with the
administratortag per cluster. - Share of client connections using TLS, and plaintext listeners enabled (target zero).
- Application users whose password is older than your rotation interval.
- Authentication failures per day per user, against a baseline.
- Clusters where
guestexists or ANONYMOUS is enabled (target zero).
Hardening baseline
| Area | Setting or action | Default | Baseline |
|---|---|---|---|
| Default user | Delete guest, or import definitions on first boot | guest/guest, loopback only | Absent |
| Loopback restriction | loopback_users | guest | Never none |
| SASL mechanisms | auth_mechanisms.N, anonymous_login_user | ANONYMOUS enabled | PLAIN/AMQPLAIN or EXTERNAL only; anonymous_login_user = none |
| Password hashing | password_hashing_module | rabbit_password_hashing_sha256 | SHA-256 or SHA-512, never MD5 |
| Listeners | listeners.tcp, listeners.ssl.default | Plain TCP on 5672 | listeners.tcp = none, TLS on 5671 |
| Peer verification | ssl_options.verify, fail_if_no_peer_cert | Not configured | verify_peer, true where clients have certificates |
| Management UI | TLS listener on 15671, management.hsts.policy, credential encryption or OAuth 2.0 | HTTP on 15672, Basic auth in localStorage | TLS, HSTS, OAuth 2.0 or encrypted credentials |
| Plugins | rabbitmq-plugins enabled list | Varies by package | Only plugins in use; each adds ports and code |
| Erlang cookie | Cookie file permissions and generation | Generated on first start | Generated at deployment, owner-only file, distribution ports firewalled |
| Secrets in config | encrypted: values | Plaintext | Encrypted values, passphrase in a secrets manager |
| Data at rest | Disk or payload encryption | None | Volume encryption at minimum |
Rolling it out
- Inventory: list users, tags, vhosts, permission patterns, enabled plugins, listeners and which applications connect with which user (connection names and client properties help).
- Split shared users: create one user per application with least-privilege patterns, move applications over one at a time, and watch
user.authentication.failureand permission errors in the server log. - Remove defaults: delete
guestand drop ANONYMOUS fromauth_mechanismsin a staging cluster first; roll back by restoring the previous configuration file. - Introduce TLS: enable 5671 alongside 5672, migrate clients, then set
listeners.tcp = none. Keep the plain listener configuration ready to restore during the change window. - Lock down management: move the UI to TLS and OAuth 2.0 or credential encryption, reduce
administratortags, and firewall 15672/15671. - Codify: manage users, permissions and policies through definitions in version control, with secrets injected at deploy time.
Small versus large estates: a single cluster for one system can keep the default vhost and internal users, provided guest and ANONYMOUS are gone and TLS is on. Multi-tenant or regulated clusters benefit from vhost per tenant and environment, OAuth 2.0 for humans, certificates or tokens for applications, and event exchange audit into the SIEM.
Common misconfigurations
- Re-enabling remote
guest: settingloopback_users = noneto make a quick test work, then promoting that configuration. Default accounts with known passwords are ATT&CK T1078.001. - Leaving ANONYMOUS enabled: any client that does not send credentials connects as the anonymous user.
- Shared
.*users: one user with full configure, write and read in every vhost, used by every service, so a single leaked connection string allows reading, purging and deleting all queues. - Plaintext AMQP and management: passwords and message payloads on 5672 and 15672 can be captured on the network (ATT&CK T1040, T1557).
- Management UI on the internet: 15672 reachable from anywhere, often with an
administratoruser and Basic auth. - Definitions and URIs in repositories: definition exports with password hashes, and AMQP or federation URIs with embedded passwords, committed to Git (ATT&CK T1552.001).
Framework mapping
| Control area | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 |
|---|---|---|
| Application users, rotation and default account removal | AC-2, IA-2, IA-5 | PR.AA-01 |
| Vhost and regex permissions, management tags | AC-3, AC-6 | PR.AA-05 |
| TLS listeners, peer verification, inter-node TLS | SC-8, SC-12 | PR.DS-02 |
| Port restriction and plugin minimisation | CM-7 | PR.IR-01 |
| Disk or payload encryption | SC-28 | PR.DS-01 |
| Event exchange and log monitoring | AU-2, SI-4 | DE.CM-09 |
Practitioner checklist
- Delete
guest(or import definitions on first boot) and confirmloopback_usersis notnone. - Remove ANONYMOUS from
auth_mechanismsand setanonymous_login_user = none. - Create one user per application with least-privilege configure, write and read patterns, and no management tag.
- Use a vhost per tenant and environment on shared clusters.
- Limit
administratorto named operators and the deployment pipeline; usemonitoringwith empty permissions for collectors. - Enforce TLS with
listeners.tcp = none,verify_peerandfail_if_no_peer_cert, and enable inter-node TLS. - Generate and protect the Erlang cookie and firewall ports 4369, 25672 and 35672-35682 to cluster and CLI hosts.
- Put the management UI behind TLS with OAuth 2.0 or credential encryption, HSTS, and operator-only network access.
- Store definitions and connection strings as secrets, use
encrypted:config values, and rotate application passwords on a schedule. - Enable the event exchange, restrict who can read it, and alert on authentication failures and user, tag and permission changes.
Standards and references
- RabbitMQ: Authentication, Authorisation, Access Control
- RabbitMQ: Deployment Guidelines (Production Checklist)
- RabbitMQ: Management Plugin
- RabbitMQ: TLS Support
- RabbitMQ: Networking and Port Access
- RabbitMQ: OAuth 2.0 Authentication Backend
- RabbitMQ: Event Exchange Plugin
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: Kafka Security Guide · Kafka Credentials Security Guide · MQTT Security Guide · Service Account Security Guide