[Bug] Broker container never initializes the AuthConfig identity fields, so ACL 2.0 data goes to a relative "null" path and cluster-scoped admin requests become Cluster:null

Aperta
#11,408 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@iloveeyjafjalla ci sta già lavorando.

Dal 13/10/2026.

  • #11409 di @iloveeyjafjalla — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
java

Direzione di ricerca

Compare the three identity-field assignments in broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java (around lines 241-243) with the two container entry points, BrokerContainerStartup.java (createAndInitializeBroker) and BrokerContainerProcessor.java (the addBroker path). Check auth/src/main/java/org/apache/rocketmq/auth/config/AuthConfig.java for the fields that stay null. Done means a broker started through the container reports the same configName, clusterName and authConfigPath as standalone, with a regression test. Pull request #11409 is already open against this issue, so check with the author before duplicating the work.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Before Creating the Bug Report
  • I found a bug, not just asking a question, which should be created in GitHub Discussions.
  • I have searched the GitHub Issues and GitHub Discussions of this repository and believe that this is not a duplicate.
  • I have confirmed that this bug belongs to the current repository, not other repositories of RocketMQ.
Runtime platform environment

OS: any (broker container mode, started with mqbrokercontainer, with ACL 2.0 enabled on the inner brokers)

RocketMQ version

branch: develop
Git commit id: a7edeecfb

JDK Version

Compiler: Temurin 1.8.0_504 (target 1.8, same as CI)

Describe the Bug

A standalone broker derives the three identity fields of AuthConfig from the broker configuration it just loaded (broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java:241-243):

authConfig.setConfigName(brokerConfig.getBrokerName());
authConfig.setClusterName(brokerConfig.getBrokerClusterName());
authConfig.setAuthConfigPath(messageStoreConfig.getStorePathRootDir() + File.separator + "config");

The proxy does the same for the first two (proxy/src/main/java/org/apache/rocketmq/proxy/config/Configuration.java:50-51). The two places that start a broker inside a broker container never do it: they build the AuthConfig from the per-broker properties and stop there.

  • container/src/main/java/org/apache/rocketmq/container/BrokerContainerStartup.java:134-140 (createAndInitializeBroker)
  • container/src/main/java/org/apache/rocketmq/container/BrokerContainerProcessor.java:120-123 (the mqadmin addBroker RPC path)

AuthConfig.configName, AuthConfig.clusterName and AuthConfig.authConfigPath have no defaults (auth/src/main/java/org/apache/rocketmq/auth/config/AuthConfig.java:26-30), so all three stay null. That shows up in three concrete ways:

  1. The ACL 2.0 user/ACL database is created at a relative path. LocalAuthenticationMetadataProvider.initialize and LocalAuthorizationMetadataProvider.initialize open RocksDB at authConfig.getAuthConfigPath() + File.separator + "users" / "acls". With a null path this is the literal relative path null/users / null/acls, created under the process working directory, instead of <storePathRootDir>/config/users next to the broker's store. Restarting the container from a different working directory silently comes up with an empty user/ACL store.
  2. Cluster-scoped admin requests are authorized as Cluster:null. DefaultAuthorizationContextBuilder builds those resources from authConfig.getClusterName() (auth/.../DefaultAuthorizationContextBuilder.java:465, 553, 579, 672) for UPDATE_AND_CREATE_TOPIC_LIST, GET_ALL_TOPIC_CONFIG, DELETE_TOPIC_IN_BROKER_LIST and DELETE_SUBSCRIPTION_GROUP_LIST. With a null cluster name the resource key is Cluster:null, so a policy that grants a concrete cluster (Cluster:<clusterName>, Resource.isMatch compares the names literally) never matches: cluster-wide mqadmin updateTopic -c ... / deleteTopic -c ... are rejected with NO_PERMISSION on brokers started by a container.
  3. All inner brokers share one set of auth singletons. AuthenticationFactory/AuthorizationFactory cache providers/evaluators in a static map keyed by PROVIDER_/METADATA_PROVIDER_/EVALUATOR_ + config.getConfigName() (AuthenticationFactory.java:51, :78, :95; AuthorizationFactory.java:52, :80, :97). With a null name every broker started by the container uses the ..._null entry, so the second and later brokers reuse the instances created for the first one — including a metadata provider configured for only one of them — instead of each broker owning its own; AuthenticationMetadataManagerImpl.shutdown() of one broker also closes that shared provider for the others.

The standalone broker is not affected because it always fills the three fields before the BrokerController is constructed.

Steps to Reproduce
  1. Prepare two per-broker configuration files that enable ACL 2.0 (as the ACL 2.0 setup requires): authenticationEnabled=true, authenticationMetadataProvider=org.apache.rocketmq.auth.authentication.provider.LocalAuthenticationMetadataProvider, authorizationEnabled=true, authorizationMetadataProvider=org.apache.rocketmq.auth.authorization.provider.LocalAuthorizationMetadataProvider, plus brokerName, brokerClusterName and storePathRootDir.
  2. Start a container with those brokers: mqbrokercontainer -c <container.conf> (or start the container and add a broker with mqadmin addBroker -b <broker.conf>).
  3. Observe that the user/ACL data is created under <cwd>/null/users and <cwd>/null/acls instead of <storePathRootDir>/config/users and .../acls, that getAuthConfig().getClusterName() is null, and that a Cluster:<clusterName> grant does not authorize mqadmin updateTopic -c <cluster>.
  4. At the unit level the same state is reproduced deterministically by starting a broker through the container and checking the AuthConfig the container put on it: createAndInitializeBroker(...) → brokerContainer.addBroker(...) → innerBrokerController.getAuthConfig(), i.e. the three fields must equal the values BrokerStartup would have set.
What Did You Expect to See?

A broker started by the container behaves like the same broker started by mqbroker: configName = brokerName, clusterName = brokerClusterName, authConfigPath = <storePathRootDir>/config, so ACL data lives next to the broker store, cluster-scoped authorization sees the real cluster name, and each broker owns its own auth provider/evaluator instances.

What Did You See Instead?

All three fields stay null (and are silently accepted), so the auth database is written to a working-directory-relative null/ directory, cluster-scoped policies are evaluated against Cluster:null, and the inner brokers collapse onto shared *_null factory entries. Nothing in the shipped configurations or documentation asks a container user to set these fields by hand (grep -r authConfigPath distribution/ docs/ finds nothing), so there is no way to avoid it other than knowing the setter-derived key names that MixAll.properties2Object accepts.

Additional Context

Minimal fix: mirror BrokerStartup.java:241-243 in both container entry points (a shared helper so the two paths cannot drift apart again). Scope note: a master and a slave that share one brokerName inside a single container still share the per-name factory entries, which matches the standalone semantics where each of them is its own JVM; the fix deliberately keeps that parity instead of inventing a different key.

I will open a PR with the change plus a regression test that starts a broker through the container and asserts the three fields against the values the standalone startup would have derived (red before the change, green after).

Lingua principale
Java
Stelle
22.7k
Fork
12k
Merge medio
3g 18h
PR unite (30g)
17

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/rocketmq

Tutte le issue di apache/rocketmq

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.