Skip to content

Generate JMS admin password of the broker on first run (fixes CVE-2026-22886) - #26148

Open
OndroMih wants to merge 4 commits into
eclipse-ee4j:mainfrom
OndroMih:ondromih-2026-07-generate-openmq-admin-pass
Open

Generate JMS admin password of the broker on first run (fixes CVE-2026-22886)#26148
OndroMih wants to merge 4 commits into
eclipse-ee4j:mainfrom
OndroMih:ondromih-2026-07-generate-openmq-admin-pass

Conversation

@OndroMih

@OndroMih OndroMih commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Fixes CVE-2026-22886.

When the default JMS broker instance is created, this generates a random password for both the client and in the broker configuration to keep them in synch.

WARNING: If upgrading an existing Glassfish installation, the existing JMS broker configuration isn't changed. It's recommended to change the default JMS admin password manually, as described in the GlassFish Administration guide.

The generated password can be retrieved from the GlassFish configuration if needed: get configs.config.config-name.jms-service.jms-host.jms-host-name.admin-password

Knowing the generated password, it's possible to change the password to a custom value, as described in the guide.

Why

Currently, by default the OpenMQ broker's admin interface is protected by the default well-known password. This allows anybody to access the admin interface if they have access to the JMS port.

It's possible to disable the admin interface but it's needed for several Glassfish commands, which would be broken without access to the OpenMQ admin interface. I chose the solution to generate the password because it doesn't break anything and should be safe as the default setup.

How

The EMBEDDED and LOCAL type of the broker are initialized from the JMS resource adapter. The EMBEDDED is initialized lazily, the LOCAL is initialized immediately after GlassFish starts if it's not created yet.

The resource adapter provided by OpenMQ doesn't support providing the admin password to initialize the new broker instance with, and always uses the default admin password. That's why I extended it in the new GlassFishResourceAdapter class, which waits until the new broker instance is created in the filesystem and then modifies the admin password to a generated password and updates the admin password in the jms host in GlassFish configuration to match it.

A few more changes were required to align with this:

  • the jms-ping command, if it was executed before the JMS broker was created, failed. The reason was that it used the default admin password and its action initialized the broker and the password get generated. The jms-ping command then failed because it operated on a resource that was created with the previous default password. I modified the jms-ping command so that when it fails and the password was meanwhile updated, it recreates the temporary resource and restarts the ping action with the new generated password
  • An ant test was using hard-coded default admin password. I changed the tests to create a new test user on the JMS broker and use it instead of the admin user. This not only made the tests pass again but it's a good practice to use a test user intead of mis-using the existing admin user.

@OndroMih
OndroMih requested a review from a team July 15, 2026 19:02
@OndroMih OndroMih modified the milestones: 8.0.4, 8.0.5 Jul 15, 2026
Generates the password for both the client and in the broker configuration to keep them in synch.
@OndroMih
OndroMih force-pushed the ondromih-2026-07-generate-openmq-admin-pass branch from 8ac385a to a6e2bf7 Compare July 15, 2026 19:15
OndroMih added 3 commits July 16, 2026 18:40
If the password is generated lazily and jms-ping is the initiator of this (nothing else connected to the JMS broker before),
the jms-ping command has no way to know the generated password. it first uses the default password, fails, and retries if the password was generated and is now different from the previous (default) password.
Using admin was a hack and doesn't work anymore as admin's password is generated.
The test needs to create a new test user and use it for JMS resources.

The create-jms-user mechanism in build.xml is a copy of a similar mechanism in the varhome test
@OndroMih
OndroMih force-pushed the ondromih-2026-07-generate-openmq-admin-pass branch from e79c13f to 30e0ed5 Compare July 17, 2026 22:18
@OndroMih

Copy link
Copy Markdown
Contributor Author

@pzygielo , do you think it's worth porting this directly to the OpenMQ resource adapter?

My new GlassFishResourceAdapter doesn't use any GlassFish-specific features, it only relies on the value of the "AdminPassword" property and updated the admin password in the broker config when the broker is created. It could also accept a property toggle, e.g. "UpdateAdminPassword" and only upadte the admin password if it's true.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR mitigates CVE-2026-22886 by ensuring managed (Embedded/Local) OpenMQ brokers do not retain the well-known default admin password on first creation, and aligns docs/tests with the new behavior.

Changes:

  • Generate and persist a randomized OpenMQ admin password in GlassFish config when a managed broker is created for the first time, and synchronize the broker’s password repository accordingly.
  • Update jms-ping to handle the “lazy broker creation + password generation” timing by retrying with the updated credentials.
  • Adjust devtests and add an integration test to ensure default OpenMQ admin credentials can no longer access the admin service; update documentation to explain how to retrieve/change the generated password.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
docs/administration-guide/src/main/asciidoc/jms.adoc Documents autogenerated admin password behavior and how to retrieve/change it.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/servlet/Servlet.java Switches devtest connection factories off admin/admin to a dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/ejb/HelloStatefulEJB.java Switches devtest connection factories off admin/admin to a dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/ejb/HelloEJB.java Switches devtest connection factories off admin/admin to a dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/descriptor/web.xml Updates descriptor-defined JMS CF credentials to use the dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/descriptor/ejb-jar.xml Updates descriptor-defined JMS CF credentials to use the dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/descriptor/application.xml Updates descriptor-defined JMS CF credentials to use the dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/descriptor/application-client.xml Updates descriptor-defined JMS CF credentials to use the dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/client/Client.java Switches appclient-side JMS CF credentials to the dedicated test user.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/build.xml Ensures broker exists and creates the dedicated JMS test user during setup.
appserver/tests/appserv-tests/devtests/connector/v3/jms-connection-factory-definition/build.properties Defines dedicated JMS test user credentials for the devtest.
appserver/tests/application/src/test/java/org/glassfish/main/test/app/jms/OpenMqAdminServiceDefaultCredentialsTest.java Adds an integration test ensuring default admin credentials can’t access OpenMQ admin service.
appserver/jms/pom.xml Adds the new jmsra-ext module to the JMS build.
appserver/jms/jmsra/pom.xml Packages the extension and replaces RA class in ra.xml to use the GlassFish adapter.
appserver/jms/jmsra-ext/src/main/java/org/glassfish/main/jms/ra/GlassFishResourceAdapter.java Implements OpenMQ RA extension to synchronize the admin password repository on first broker creation.
appserver/jms/jmsra-ext/pom.xml Introduces the new extension module and its OpenMQ dependencies.
appserver/jms/jms-core/src/main/java/com/sun/enterprise/connectors/jms/system/ActiveJmsResourceAdapter.java Generates a random admin password in config on first use for managed brokers.
appserver/jms/admin/src/main/java/org/glassfish/jms/admin/cli/JMSPing.java Retries ping with regenerated credentials and includes formatting cleanups.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 741 to 744
String adminUserName = jmsHost.getAdminUserName();
String adminPassword = JmsRaUtil.getUnAliasedPwd(jmsHost.getAdminPassword());
boolean usesDefaultAdminCredentials = isDefaultAdminCredentials(adminUserName, adminPassword);
List<Property> jmsHostProps= getJmsService().getProperty();
Comment on lines +146 to +157
try {
value = pingConnectionPool(SimpleJndiName.of(tmpJMSResource + JNDINAME_APPENDER));
} catch (ResourceException e) {
if (!oldPassword.equals(defaultJmsHost.getAdminPassword())) {
// Retry in case the password was lazily autogenerated on first access.
// We need to recreate the resource with the generated password, which was meanwhile updated in
// the default JMS host config
deleteJMSResource(subReport, tmpJMSResource, context.getSubject());
createJMSResource(defaultJmsHost, subReport, tmpJMSResource, context.getSubject());
}
value = pingConnectionPool(SimpleJndiName.of(tmpJMSResource + JNDINAME_APPENDER));
}
Comment on lines 168 to 170
report.setMessage(localStrings.getLocalString("jms-ping.pingConnectionPoolException",
"An exception occured while trying to ping the JMS Host.", e.getMessage()));
"An exception occured while trying to ping the JMS Host.", e.getMessage()));
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
Comment on lines +84 to +86
boolean finished = process.waitFor(Duration.ofSeconds(30).toMillis(), java.util.concurrent.TimeUnit.MILLISECONDS);
assertTrue(finished, "imqcmd command timed out");

Comment on lines +126 to +130
<replace
file="${project.build.outputDirectory}/glassfish/lib/install/applications/jmsra/META-INF/ra.xml"
token="com.sun.messaging.jms.ra.ResourceAdapter"
value="org.glassfish.main.jms.ra.GlassFishResourceAdapter"
/>
ways:

* Read the `admin-password` attribute of the JMS host in
domain-dir``/config/domain.xml``.
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.

2 participants