Skip to content

Document least-privilege management API access for the RabbitMQ transport - #8541

Draft
andreasohlund wants to merge 1 commit into
masterfrom
rabbit-policy
Draft

andreasohlund wants to merge 1 commit into
masterfrom
rabbit-policy

Conversation

@andreasohlund

@andreasohlund andreasohlund commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Motivation

Customers with strict security requirements, such as banks whose RabbitMQ management UI is protected by SSO/LDAP, can't grant policymaker rights to every endpoint host. The current docs read as "give every endpoint policymaker, or disable the checks in extreme circumstances". There is a third option, and this PR documents it:

  1. An administrator creates a delivery-limit policy in advance that covers the endpoint queues:
    rabbitmqctl set_policy -p <vhost> <name> '<pattern>' '{"delivery-limit":100000}' --apply-to quorum_queues
  2. Endpoints then run with a management API user that only has the read-only management tag, with all broker requirement checks and delivery-limit validation still enabled.

In that setup the transport only sends GET /api/overview, GET /api/feature-flags, and GET /api/queues/{vhost}/{queue}. It never sends PUT /api/policies, because the queue's effective delivery limit already has the expected value. Without a policy created in advance, a management-only user gets a 401 when the transport tries to create its policy on RabbitMQ 4.x, and the endpoint doesn't start.

Tested with

  • NServiceBus.RabbitMQ 10.1.7 / NServiceBus 9.2.8
  • RabbitMQ 3.13.7 and 4.3.6 (management tag was enough for /api/feature-flags on both; on 3.11 it needs administrator)

Changes

  • connection-settings_management-api-configuration_rabbit_[10,): new "Minimum management API permissions" section. "Disabling broker requirement checks" now points to policies created in advance as the recommended alternative (the CAUTION is unchanged). Typo fix.
  • connection-settings_delivery-limit-validation_rabbit_[10,): the policymaker note now says it's only needed when the transport creates policies itself. New "Creating delivery limit policies in advance" section covering the rabbitmqctl example, -p <vhost>, quorum_queues, the nsb.*.delivery-limit naming rule, and the one-policy-per-queue rule. Typo fixes.
  • operations-scripting_content_rabbit_[10,11) / [11,): aligned "unlimited" wording and mentioned running queue validate-delivery-limit from a deployment pipeline.
  • servicecontrol/transports.md: ServiceControl 6.5+ runs the same checks for its own queues (error, audit, Particular.*), so those queues need a policy too.
  • reviewed: date bumped on connection-settings.md.

No snippets or pre-10 partials changed.

For reviewers on the RabbitMQ transport team: 100000 vs -1

Please check the "unlimited" wording. The docs used to say the transport requires an unlimited delivery limit. The transport actually expects 100000 (Queue.BigValueInsteadOfActuallyUnlimited, introduced in Particular/NServiceBus.RabbitMQ#1689), not -1:

  • A user policy with "delivery-limit": -1 makes validation fail on 4.x with "non-default value of '-1'" (see BrokerVerifier.ShouldOverrideDeliveryLimit). Only transport-owned nsb.*.delivery-limit policies with -1 get overwritten.
  • RabbitMQ 3.13 rejects -1 in policies outright.
  • --apply-to has to be quorum_queues (underscore); RabbitMQ 4.3 rejects quorum-queues.

The docs now state the value 100000 explicitly so that administrators who create policies by hand don't use -1.

@andreasohlund

Copy link
Copy Markdown
Member Author

Retested with the latest transport: NServiceBus.RabbitMQ 11.2.1

I reran the least-privilege scenarios with NServiceBus.RabbitMQ 11.2.1 / NServiceBus 10.2.9 against RabbitMQ 3.13.7 and 4.3.6 (Docker rabbitmq:3.13-management / rabbitmq:4.3-management).

The endpoint used a user with only the management tag and full vhost permissions for AMQP. It used quorum queues with the conventional topology, all broker requirement checks on, and delivery-limit validation on. A logging reverse proxy in front of the management API recorded every request.

Scenario RabbitMQ 3.13.7 RabbitMQ 4.3.6
A: admin pre-creates a {"delivery-limit":100000} policy (--apply-to quorum_queues) ✅ Starts, message round-trip works, reads only ✅ Starts, message round-trip works, reads only; the queue reports delivery_limit=100000
B: no pre-created policy ✅ Starts, reads only (no policy write on 3.x) ❌ PUT /api/policies/%2F/nsb.LeastPriv.B.delivery-limit → 401, endpoint doesn't start
C: admin policy with {"delivery-limit":-1} rabbitmqctl set_policy rejects it ("Validation failed"), so this ends up the same as B ❌ "The delivery limit for 'LeastPriv.C' is set to the non-default value of '-1'", endpoint doesn't start

In the scenarios that passed, the transport only called:

GET /api/overview
GET /api/feature-flags
GET /api/queues/%2F/<queue>

There was no PUT /api/policies. The one 401 on /api/overview in each run is the Basic-auth challenge before the 200, because the client uses HttpClientHandler.Credentials. It isn't a permissions problem.

The BrokerVerifier delivery-limit logic (BigValueInsteadOfActuallyUnlimited, the nsb.*.delivery-limit ownership check, and the 4.0 write gate) is unchanged between 10.x and 11.2.1. So the [10,) partials in this PR apply to 11.x as well.

Not covered by this run: the claim that RabbitMQ 3.11 needs the administrator tag for /api/feature-flags.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant