Accessing JMX with jconsole over SSL on EAP 7.0

Latest response

I am trying to configure secure JMX access similar to the following knowledge base article which applies to EAP 6.0

https://access.redhat.com/solutions/632773

EAP 7.0 has changed the default ports that are accessed.

I was successful in a standalone mode. However I have been unable to figure out how to get it work for domain mode.

In standalone I connected using jconsole using the service url - service:jmx:remote+https::

I would assume in domain mode I should be able connect to a similar service url such as service:jmx:remote+https::

where https port is the server https port 8443

David Gilbert's picture

Responses

Hi David,

I'm actually writing a procedure for a new guide that includes connections to remote EAP 7.0 using JConsole (albeit without SSL).

If you are using the Application Realm, you will also need to create a user in the application realm to use for authentication.

The JMX service URL for a managed domain is different for EAP 7.0 compared to EAP 6. Try using service:jmx:remote://IP_ADDRESS:PORT. For non-SSL, the port is 9999 for a managed domain host controller when setting the management endpoint to false.

Hi Lucas,

Unfortunately SSL connections is what I need to setup.

FYI I am connecting with an application user.

I believe port 9999 in non-ssl mode only works if remote protocol is used. However this connects to the domain controller. I care more connecting to the servers as I need JMX access to the servers.

her is what I done so far which does work in ssl standalone mode. However it is the ssl domain mode that is giving me problems.

This is being done on my dev setup so exact production quality practices is not an issue right now.

In standalone mode.

1) Created keystore

keytool -genkey -alias jboss -keyalg RSA -keystore eap7console.jks -storepass changeit

2) Added to standalone/configuration/standalone.xml, the ssl config to ManagementRealm

<management>
    <security-realms>
        <security-realm name="ManagementRealm">
            <server-identities>
                <ssl>
                    <keystore path="eap7console.jks" relative-to="jboss.server.config.dir" keystore-password="changeit" alias="jboss"/>
                </ssl>
            </server-identities>
            <authentication>
                <local default-user="$local" skip-group-loading="true"/>
                <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
            </authentication>
            <authorization map-groups-to-roles="false">
                <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
            </authorization>
        </security-realm>

...
</management>

3) Set management-https binding on Management interface

<management-interfaces>

        <http-interface security-realm="ManagementRealm" http-upgrade-enabled="true">
            <socket-binding https="management-https"/>
        </http-interface>
    </management-interfaces>

4) Modify the jconsole.sh script in $JBOSS_HOME/bin directory. For simplicity I created a copy of jconsole.sh script for ssl connection. I called my copy jconsole_ssl.sh. Within the new jconsole_ssl.sh script, I modified the startup parameters to include the truststore and password.

$JAVA_HOME/bin/jconsole -J-Djava.class.path="$CLASSPATH" -J-Djavax.net.ssl.trustStorePassword=changeit -J-Djavax.net.ssl.trustStore=standalone/configuration/eap7console.jks -J-Djavax.net.debug=ssl "$@"

4) When jconsole starts up, I selected Remote Process and entered the following for the service url:

service:jmx:remote+https://:9993

The username and password for the management user created through the add-user.sh script

port 9993 is the port defined in the management-https binding.

5) The jconsole output window appears to show ssl connection succeeded based on the debug putput because I specified J-Djavax.net.debug=ssl on startup

===============================================================================

However domain mode is totally different problem.

1) In the domain/configuration/domain.xml file

I enabled the support of management of the server. Just for completeness I enabled it on all profiles even though my server is using full profile.

        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
            <expose-resolved-model/>
            <expose-expression-model/>
            <remoting-connector use-management-endpoint="false"/>
        </subsystem>

2) In the domain/configuration/host.xml file

I add ssl config to the ApplicationRealm since that is how the server are accessed in domain mode using jmx management.

3) Modify the jconsole.sh script in $JBOSS_HOME/bin directory. For simplicity I created a copy of jconsole.sh script for ssl connection. I called my copy jconsole_ssl_domain.sh. Within the new jconsole_ssl.sh script, I modified the startup parameters to include the truststore and password.

$JAVA_HOME/bin/jconsole -J-Djava.class.path="$CLASSPATH" -J-Djavax.net.ssl.trustStorePassword=changeit -J-Djavax.net.ssl.trustStore=domain/configuration/eap7console.jks -J-Djavax.net.debug=ssl "$@"

4) Started jconsole script jconsole_ssl_domain.sh

5) This is what I tried in the jconsole dialog:

  • Select Remote Process
  • enter service url - service:jmx:remote+https://:8443
  • the user name and password is the application user created through the add-user.sh script

I am using the https port of the server

The connection fails.

=============================================

If I connect in non-ssl mode, I have no issues connecting to the following service url in jconsole:

service:jmx:remote+http://:8080

application username and password

Currently I have been running my tests on wildfly 10.0.0 final. I will try switching back to EAP 7.0. In theory it should be identical in terms of setup. I need to work in both wildfly and EAP versions.

Hi David, I've just tested it myself, and I think I have it working. I'll try and quickly detail the process I used below.

On the host:

  • Create the keystore on the host, eg. and export the certificate.
keytool -genkey -alias jboss -keyalg RSA -keystore eap7console.jks -storepass changeit
keytool -exportcert  -keystore eap7console.jks -alias jboss -keypass changeit -storepass changeit -file jboss.cer
  • Create a new user in the ApplicationRealm that you will use to connect to the JBoss EAP servers for remote monitoring.

  • Set the remoting management endpoint to false:

/profile=full/subsystem=jmx/remoting-connector=jmx:add(use-management-endpoint=false)
  • Add the remoting port to the socket binding group.
/socket-binding-group=full-sockets/socket-binding=remoting:add(port=4447)
  • Set the remoting subsystem to use the ApplicationRealm:
/profile=full/subsystem=remoting/connector=remoting-connector:add(socket-binding=remoting,security-realm=ApplicationRealm)
  • Alter the security-realm to add SSL.
/host=master/core-service=management/security-realm=ApplicationRealm/server-identity=ssl:add(protocol=TLSv1,keystore-path=eap7console.jks,keystore-relative-to=jboss.domain.config.dir,keystore-password=changeit,alias=jboss)
  • Start the host and bind to the IP address. You shouldn't see any errors on startup.
domain.sh -b 192.168.1.230
  • On your client, import the certificate from the host to the client's truststore. e.g.
keytool -importcert -keystore clientkeystore.jks -storepass changeit -alias jboss -trustcacerts -file jboss.cer
  • Start jconsole on your client (it's best to use the wrapper script in an EAP installation), pointing to the client's truststore:
./jconsole.sh -J-Djavax.net.ssl.trustStorePassword=changeit -J-Djavax.net.ssl.trustStore=/path/to/clientkeystore.jks
  • Use the following URL for the remote process (it doesn't need '+https' for SSL to work), and use the username and password of the ApplicationRealm user you created earlier:
service:jmx:remote://HOST_IP_ADDRESS:4447

port 4447 corresponds to a server running on the host with a 0 port offset. To connect to other servers, add their port offset value to 4447.

I hope this helps :)

Thanks Lucas. It seems that this is best solution so far. I had posted to the wildfly user forum with the same question. It appears your answer is similar to the response given there also.

https://developer.jboss.org/message/967328

Even though this works I am questioning if this is the proper way to set this up. From EAP 6.x to EAP 7.0 the remoting connector at port 4447 was removed and now you can access the servers at the app server port i.e. 8080. It seems odd to me that in a non-SSL setup that you can access the server using JMX with a service url of 'service:jmx:remote+http://: where app server port is the typically port the application server is running on i.e 8080. Using the above method, a new port has to be created which does not to be guaranteed it will always exist. This approach is basically reverted to the EAP 6.0 config by adding a the remoting connector at port 4447.

My issue is that my application needs a consistent and known JMX protocol and port to connect to. I need the service URL in order to connect to each server to gather JMX metrics.

In non-ssl mode I know that I can use the 'remote+http' jmx service protocol and the port will be the HTTP application server port i.e. 8080. However with the above procedure for SSL it does not seem like I can rely on that the port is going to exist. I can assume there is going to be remoting socket binding but that is not going to work for me.

I still feel that has to be a way to use something like 'remote+https' and connect to the HTTPS application server port.

Not sure if solved my own problem. Here is what I did that seems to work.

In domain.xml file

Obviously I did the basics to enable JMX subsystem with .

      <subsystem xmlns="urn:jboss:domain:jmx:1.3">
            <expose-resolved-model/>
            <expose-expression-model/>
            <remoting-connector use-management-endpoint="false"/>
        </subsystem>

This is the part below is what seemed to get things to work as expected.

NOTE: I modified the following on all profiles that were in use.

I changed the http-connector on remoting subsystem. I changed the name to 'https-remoting-connector' and set connector-ref to 'default-https'

 <subsystem xmlns="urn:jboss:domain:remoting:3.0">
         <http-connector name="https-remoting-connector" connector-ref="default-https" security-realm="ApplicationRealm"/>
 </subsystem>

I also changed the ejb subsystem remote-connector to use https-remoting-connector.

 <subsystem xmlns="urn:jboss:domain:ejb3:4.0">
          <remote connector-ref="https-remoting-connector" thread-pool-name="default"/>
</subsystem>

In host.xml file

I added SSL keystore to the ApplicationRealm

         <security-realm name="ApplicationRealm">
            <server-identities>
                <ssl protocol="TLSv1">
                    <keystore path="eap7console.jks" relative-to="jboss.domain.config.dir" keystore-password="changeit" alias="jboss"/>
                 </ssl>
            </server-identities>
            <authentication>
                <properties path="application-users.properties" relative-to="jboss.domain.config.dir"/>
            </authentication>
            <authorization>
                <properties path="application-roles.properties" relative-to="jboss.domain.config.dir"/>
            </authorization>
        </security-realm>

Within my modified jconsole.sh script (I found it easier to create a copy of the script so I would have to keep specified command line args) which I modified to specify the following startup parameters.

$JAVA_HOME/bin/jconsole -J-Djava.class.path="$CLASSPATH" -J-Djavax.net.ssl.trustStorePassword=changeit -J-Djavax.net.ssl.trustStore=domain/configuration/eap7console.jks -J-Djavax.net.debug=ssl "$@"

In the Jconsole dialog

  • Select Remote Process
  • enter the following service url - service:jmx:remote+https://:8443

  • the user name and password is the application user created that is part of the ApplicationRealm

Others servers are accessible at https port + port offset

This solution seems to work for me. I have no idea if this is proper solution. If anyone with more experience or knowledge in this area can help or confirm this is correct approach, then feel free to chime in. Right now I am going to go with this solution.

Looks like I forgot one important part that is needed.

 <subsystem xmlns="urn:jboss:domain:undertow:3.1">
     <https-listener name="default-https" socket-binding="https" security-realm="ApplicationRealm"/>
</subsystem>

This is tied in the http-connector on the remoting subsystem

I also found this article at http://middlewaremagic.com/jboss/?p=2783 after I did my implementation. Even though the article is about EJB SSL config, some of the info still applies. See section on 'Configuring Wildfly 10 to use SSL'. This basically seems to be very similar to my steps. I probably could have create a separate security realm. I may try that out later today. The article also uses the CLI commands which is better than my manually modifying the domain.xml and host.xml directly.

Hi David,

I'm glad you have it working how you like it. I'm definitely no expert in this area, so I can't confirm whether this is a 'correct' approach or not.

If you would like a more definitive answer and advice, I would suggest opening a support case so our support engineers can have a close look.

Was this helpful?

We appreciate your feedback. Leave a comment if you would like to provide more detail.
It looks like we have some work to do. Leave a comment to let us know how we could improve.
Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.