BROKABROKA
Sign inDownload CommunityRequest a demo
GuideGovernance

Operating every broker with one permission model

A mixed messaging estate does not need an access model per broker. It needs one model that resolves cleanly onto each broker's own enforcement — and a habit of granting rights per environment rather than per person.

12 min read

Estates rarely start mixed. A team runs Kafka, another picks RabbitMQ for a routing problem, Redis arrives with a cache and stays for Streams, and an older Artemis deployment — Apache Artemis, formerly ActiveMQ Artemis — keeps doing exactly what it was built for. Each arrives with its own console, its own notion of a user, and its own answer to "who can purge this".

The result is not usually a security incident. It is slower access reviews, inconsistent production safety, and a longer path from alert to root cause. Consolidating the operating model — not the brokers — is what shortens all three.

1 — Map teams before roles

Start from the teams that already exist operationally, not from the brokers. A team is the unit that owns resources, gets paged, and shows up in an access review. Once teams are right, roles are a short list.

Team Everywhere Development Staging Production
Payments platform Viewer Operator Operator —
Checkout services Viewer Operator — —
Messaging administrators Admin — — —
Security review Auditor — — —

Four teams, three environments, and no row that needed a person's name in it. That is the property to aim for: a grant that outlives the person who needed it is a grant nobody will remember to remove.

The first column is not decoration. A role assigned to one environment reaches the connections inside it and nothing else: the dashboard, alerts, applications and the audit trail, and every administrative permission, come only from an assignment made everywhere — and a role that administers the installation, such as Admin, cannot be assigned any narrower. So every team starts from a base role everywhere, and operating rights are added per environment on top of it; a dash means the base role is all the team has there.

One account's Roles tab: Operator assigned with the scope environment: Staging, Viewer assigned Global, and a row to assign another role with the scope Global (everywhere) preselected.
The table above for one person: a base role everywhere and operating rights in one environment. Assigned to a team instead, the same two rows reach everyone in it.

2 — Make the environment carry the policy

A team with operate rights in staging should not silently gain them in production because a connection was added to the wrong place. Put the safety decision on the environment, where it is visible and reviewable, and let roles express capability rather than exception.

In practice: mark production read-only first. No role or grant overrides that policy, so a write there is a change to the environment — deliberate, and audited like any other. Teams keep full browsing and inspection; the operations that change state are the ones that need a conversation.

Where production has to stay writable, make it guarded instead. A destructive operation — a delete, a purge, an offset reset — asks for a reason in every environment; a guarded environment asks for one on every write, and the reason is stored on that write's audit entry. It is not an approval step: nobody else signs off, but nobody writes there without saying why.

The Edit environment sheet for Production: its colour, the write policy set to Guarded — every write asks for a reason, with the line that it applies to every connection in the environment whatever the operator's permissions, the default classification Internal, and Allow insecure TLS left off.
The environment is the object the policy hangs on, so it is a first-class thing to manage rather than a label on a connection.

3 — Respect what each broker enforces natively

A unified model sits above broker-native access control; it does not replace it. Past the environment's policy, two checks apply to every write: the console's scoped permission, and whatever the broker itself allows the connection's credentials to do.

Broker What it still enforces underneath
Kafka Cluster ACLs on the connection's principal — keep an operator principal separate from application principals
Redis ACL users: command, key and channel rules; deliberately withhold destructive commands from the connection used for browsing
RabbitMQ Per-vhost configure, write and read permissions, and topic permissions on routing keys — a vhost boundary is often the cleanest mapping to an environment
Artemis Address-based authorization: security settings over address expressions (send, consume, createDurableQueue). Treat dead-letter addresses and their queues as their own sensitive scope
Memcached Nothing: the text protocol has no authentication, so the network boundary and the console's own permission are the only controls

Each of those native layers is visible from the console on its own screen — Kafka's Service Accounts, Redis's ACL users, RabbitMQ's and Artemis's Users & Permissions — read from the broker and written back to it, never copied into BROKA's model. Changing one is a write like any other: it takes the right to change that connection, stops at a read-only environment, and is audited. Reading them is recorded too (Commercial), because who may do what on a broker is security configuration.

RabbitMQ's Users & permissions: appuser limited to ^orders patterns in the broka.dev vhost with a connection cap of 100, broka with the administrator tag and .* in every vhost, capture-denied showing denies all for configure, write and read, and observer with a monitoring tag and no permissions; below, an empty Topic permissions card and Authentication attempts by protocol.
The broker's own accounts, as the broker holds them. An administrator that may touch everything beside an application confined to one name prefix is the separation the table asks for.

A person can be permitted by the console and refused by the broker, and the error they see is the broker's. That is the system working, not a misconfiguration — but only if somebody told them it would happen.

4 — One audit record, or none of this holds

If each broker keeps its own record, an access review becomes one export per broker and a spreadsheet. One trail — actor, environment, broker, resource, outcome — is what turns a permission model into something you can actually attest to.

actor      deniz@northwind-bank.example
env        production        policy: read-only
broker     rabbitmq          cluster: rmq-core-01
resource   queue q.pay.us
action     purge
outcome    blocked — write refused by read-only environment policy

Note what that entry records: an action that did not happen. A trail that only holds successes cannot answer the question an access review actually asks, which is what people tried to do.

The audit log: each entry's action, target, actor, environment, result and time, reads marked as reads beside the rest.
One trail across every broker. In Commercial, privileged reads are recorded too by default, which is what makes “who looked at this” answerable.

The trail answers what people did. The other half of a review — what they can do now — is Operations ▸ Access Review (Commercial): every account, resolved through its own roles and grants and its teams', with what conferred each permission, or everyone who holds one permission. It is gated on the audit permission rather than on managing users, so the reviewer can see access without being able to change it, and reading it is itself recorded.

Access review, Accounts tab: each account with its roles, the administrative permissions it holds — alerts.manage, applications.manage and connections.manage on the operators, none on the viewers — its permission count and its last sign-in, several marked never signed in.
The administrative column lifts the permissions worth questioning out of the total; the screen itself never changes access.

Where teams get this wrong

  • Roles per person. Grants outlive the reason they were made. Grant to teams; membership is the reversible part.
  • One shared administrative credential per broker. The audit trail can then only say "someone with the key".
  • Production defined by naming convention. If production is a prefix rather than an environment, nothing enforces it.
  • Read-only meaning read-nothing. Browsing and inspection are how incidents get diagnosed; restrict writes, not visibility.

Try it yourself

The permission-model lab starts a Kafka broker with ACLs enforced and a RabbitMQ broker with three differently scoped users, and lists the BROKA settings that complete the model.