fix(activemq): add in-VM user credentials to simpleAuthenticationPlugin + ConnectionFactory - #213
Merged
Merged
Conversation
After PR #208/#209 restored the xmlns on <broker> (so the XSD loads), the post-T2.12 default DocumentBuilderFactory keeps validating and catches the next layer of T2.2 element-name bugs in the same file: SAXParseException; lineNumber: 61; columnNumber: 68; cvc-complex-type.2.4.a: Invalid content was found starting with element '{"http://activemq.apache.org/schema/core":constantPendingMessageLimit}'. One of '{"http://activemq.apache.org/schema/core":fileQueueCursor, "http://activemq.apache.org/schema/core":storeCursor, "http://activemq.apache.org/schema/core":vmQueueCursor, WC[##other:"http://activemq.apache.org/schema/core"]}' is expected. The T2.2 PR mixed up two superficially similar ActiveMQ policy mechanisms that do very different things: T2.2 wrote XSD expects What it controls --------------- ---------------------- ------------------- <pendingQueuePolicy> <pendingMessageLimitStrategy> (parent) cap on count per consumer <constantPending- <constantPending- (child) constant MessageLimit MessageLimitStrategy cap with 'limit' value="1000"/> limit="1000"/> attribute <pendingQueuePolicy> selects the queue cursor (fileQueueCursor / storeCursor / vmQueueCursor) -- i.e., how pending messages are *stored*, not how many are kept. The XSD's <xs:any namespace='##other'/> wildcard on that element does NOT allow <constantPendingMessageLimit> because the element is in the same ActiveMQ namespace, not a different one. Hence "Invalid content was found starting with element constantPendingMessageLimit." Fix: replace the wrong parent/child pair with the correct XSD-valid <pendingMessageLimitStrategy>/<constantPendingMessageLimitStrategy> pair, and use the `limit` attribute (not `value`). The "cap pending message count per queue" intent of the original T2.2 block is preserved. This PR also pulls in the #208 fix (xmlns on <broker> + the explanatory comment). The #208 PR (#209) is still open and is superseded by this one; it can be closed without merging. Refs #208, #210 > Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.
…in + ConnectionFactory The T2.2 ActiveMQ hardening PR (#166/#167) configured `<simpleAuthenticationPlugin anonymousAccessAllowed="false"/>` but did not add any users and did not update the in-VM ActiveMQConnectionFactory in perc-mq.xml / ear/WEB-INF/jetty-env.xml to provide credentials. The in-VM transport (vm://localhost) sends anonymous (no user / no password) connections by default, so every JMS listener (PERCUSSION.EMAIL, PERCUSSION.PUBLISHING, PERCUSSION.NOTIFICATIONS) gets `User name [null] or password is invalid` and retries in a 5-second FixedBackOff loop (currentAttempts climbs to 30+ within a minute). Fix has three parts: 1. activemq.xml: add a single 'rhythmyx' user to the simpleAuthenticationPlugin via the userPasswords and userGroups attributes. userGroups 'users,admins' grants both consume/produce on queues/topics and admin operations; the default ActiveMQ SimpleAuthorizationMap is permissive (no <simpleAuthorizationMap> is required to grant access to PERCUSSION.* queues). anonymousAccessAllowed stays 'false' so the security posture is preserved for any future network listener. 2. perc-mq.xml: configure the Jetty-bound ActiveMQConnectionFactory (java:/ConnectionFactory) with setUserName / setPassword via Jetty's <Property> indirection. Operators can override the default at install time via -Dactivemq.username=... / -Dactivemq.password=... 3. ear/WEB-INF/jetty-env.xml: same change for the webapp-scoped ActiveMQConnectionFactory (jms/ConnectionFactory). Default credentials are 'rhythmyx' / 'rhythmyx' (placeholder, not a secret). Operators opening a network listener (adding a <transportConnector>) MUST change the password and add a per-listener user. The comment in activemq.xml points at this requirement. This PR is built on top of #211 (the activemq.xml XSD-validity fixes); once both merge, the broker should start cleanly, the in-VM connection should authenticate, and the JMS listeners should reach steady state without retries. Refs #212 > Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.
natechadwick
approved these changes
Sep 8, 2026
This was referenced Sep 8, 2026
natechadwick
pushed a commit
that referenced
this pull request
Sep 8, 2026
…ies about String-typed attributes) (#215) The activemq.xsd advertises userPasswords and userGroups as xs:string attributes on <simpleAuthenticationPlugin>, but the actual org.apache.activemq.security.SimpleAuthenticationPlugin class in 5.16.8 has setters that take Map<String,...>, not String: public void setUserPasswords(java.util.Map<java.lang.String, java.lang.String>); public void setUserGroups(java.util.Map<java.lang.String, java.util.Set<java.security.Principal>>); There is no custom property editor registered, so Spring's BeanWrapper rejects the activemq.xml bean init with: ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'java.util.Map' for property 'userGroups': no matching editors or conversion strategy found PR #213 used the attribute form because that's what the XSD implied; that form is unusable. The correct XBean syntax is the <users> / <authenticationUser> child-element pattern (the <authenticationUser> helper class is in the same activemq-spring-5.16.8.jar, has a 3-arg String constructor AuthenticationUser(String username, String password, String groups), and is declared in the same activemq.xsd as a child of the plugin's <users> element): <simpleAuthenticationPlugin anonymousAccessAllowed="false"> <users> <authenticationUser username="rhythmyx" password="rhythmyx" groups="users,admins"/> </users> </simpleAuthenticationPlugin> The connection-factory changes from PR #213 (perc-mq.xml and ear/WEB-INF/jetty-env.xml) are unchanged; the broker just needs the correct user representation. Refs #214 > Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds credentials to the in-VM
ActiveMQConnectionFactory(in bothperc-mq.xmlandear/WEB-INF/jetty-env.xml) and a matching user to thesimpleAuthenticationPlugininactivemq.xml, so the in-VM JMS connection can authenticate against the T2.2-hardened broker. Without this, every JMS listener getsUser name [null] or password is invalidand retries in a 5-second loop.Why this is needed
The T2.2 PR (#166/#167) set
<simpleAuthenticationPlugin anonymousAccessAllowed="false"/>but did not add any users and did not update the in-VMActiveMQConnectionFactoryconfigurations. The in-VM transport (vm://localhost) sends anonymous (no creds) connections by default, so the broker rejects every connection attempt:currentAttempts=37after ~3 minutes is what the user is seeing.Diff
activemq.xml:perc-mq.xmlandear/WEB-INF/jetty-env.xml:<New class="org.apache.activemq.ActiveMQConnectionFactory"> <Arg>vm://localhost?brokerConfig=xbean:activemq.xml</Arg> + <Set name="userName"><Property name="activemq.username" default="rhythmyx"/></Set> + <Set name="password"><Property name="activemq.password" default="rhythmyx"/></Set> </New>Security posture
The T2.2 hardening intent ("auth in place so a future network listener inherits the secure defaults") is preserved:
anonymousAccessAllowed="false"— anonymous connections are still rejected.SimpleAuthorizationMap(no explicit<simpleAuthorizationMap>) allows therhythmyxuser inusers,adminsgroups to read/write/admin on all destinations. This is the same effective policy as before the hardening for the in-VM case.rhythmyx) is a placeholder. Operators opening a network listener MUST change it (and add a per-listener user) before adding any<transportConnector>. The comment inactivemq.xmlpoints at this requirement.userNameandpasswordfrom system properties (activemq.username,activemq.password) via Jetty's<Property>indirection withrhythmyxdefaults — operators can override at install time without rebuilding, e.g. via-Dactivemq.username=...instart.ini.Depends on #211
This branch is built on top of
bugfix/210-activemq-pending-message-limit-strategy(PR #211), which fixes the activemq.xml XSD validity issues. Without #211, the broker can't even start, so this auth fix is moot. After both PRs merge, the in-VM connection should work end-to-end.Verification
python3 -c "import xml.etree.ElementTree as ET; ET.parse('activemq.xml')"— well-formed.xmllint --schema activemq.xsd activemq.xml --noout— exits 0.grep "User name" jetty/base/logs/server.log | wc -l→ 0currentAttemptscounter on the JMS listener retry messages stops climbingPERCUSSION.EMAIL,PERCUSSION.PUBLISHING,PERCUSSION.NOTIFICATIONSall reach steady state without retryRefs #212