Tomcat JMX connection - Authentication failed

10,709

Remote access

Remote access means access from another machine, to access locally via another VM you don't have to setup JMX[note 1]. You can try this by starting an java application wthout JMX, and then start VisualVM on the same machine. The started app should appear under "Local" (in VisualVM).

As the exception states: Authentication failed! Credentials required did you supply the username and password? ;) I guess you did...

Possible solution

If you did, then you should try to remove $CATALINA_BASE from CATALINA_OPTS and enter a hardcoded value, just to see if this is the root problem.

example:

CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070 -Dcom.sun.management.jmxremote.password.file=/opt/tomcat6/conf/jmxremote.password -Dcom.sun.management.jmxremote.ssl=false"

If it works, than try like this:

CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070
-Dcom.sun.management.jmxremote.password.file=`echo $CATALINA_BASE`/conf/jmxremote.password
-Dcom.sun.management.jmxremote.ssl=false"

[note 1]: Here says: "Under previous releases of the Java SE platform, to allow the JMX client access to a local Java VM, you had to set the following system property (com.sun.management.jmxremote) when you started the Java VM or Java application. Setting this property registered the Java VM platform's MBeans and published the Remote Method Invocation (RMI) connector via a private interface to allow JMX client applications to monitor a local Java platform, that is, a Java VM running on the same machine as the JMX client. In the Java SE 6 platform, it is no longer necessary to set this system property. Any application that is started on the Java SE 6 platform will support the Attach API, and so will automatically be made available for local monitoring and management when needed."

Share:
10,709
ziggy
Author by

ziggy

Updated on June 15, 2022

Comments

  • ziggy
    ziggy almost 2 years

    I am having some problems setting up Tomcat for JMX. I added the following properties to

      CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070      -Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/jmxremote.password      -Dcom.sun
        .management.jmxremote.ssl=false"
    

    And have added the jmxremote.password file in to the conf directory. I wrote a client tool that connects to the JMX server running on port 18070. When i run the client program i get the following error.

        Exception in thread "main" java.lang.SecurityException: Authentication failed! Credentials required
           at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticationFailure(JMXPluggableAuthenticator.java:193)
           at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticate(JMXPluggableAuthenticator.java:145)
           at sun.management.jmxremote.ConnectorBootstrap$AccessFileCheckerAuthenticator.authenticate(ConnectorBootstrap.java:185)
           at javax.management.remote.rmi.RMIServerImpl.doNewClient(RMIServerImpl.java:213)
           at javax.management.remote.rmi.RMIServerImpl.newClient(RMIServerImpl.java:180)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:597)
           at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
           at sun.rmi.transport.Transport$1.run(Transport.java:159)
           at java.security.AccessController.doPrivileged(Native Method)
           at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
           at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
           at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
           at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
           at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
           at java.lang.Thread.run(Thread.java:619)
           at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
           at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
           at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
           at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
           at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2312)
           at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:277)
           at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
           at com.bt.c21sc.c21tkprobe.accessors.C21TkProbeJmxDAO.connect(Unknown Source)
           at com.bt.c21sc.c21tkprobe.service.C21TkProbeBD.execute(Unknown Source)
           at com.bt.c21sc.c21tkprobe.C21AppserverProbe.main(Unknown Source)
    

    If i change the CATALINA_OPTS properties to

    CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070 -Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/jmxremote.password -Dcom.sun
    .management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
    

    Then it works fine. I think what i am confused of is what is classed as remote access. I am running the client program away from the Tomcat instance but both Tomcat and the client tool are on the same machine (i.e. different virtual machines but same environemnt). I thought i had to configure the remote authentication if i access the JMX server remotely from a different machine.

    By remote access do they mean accessing the JMX server from any VM either locally or remotely?

    Edit

    Thanks. I found out that the problem was that even though i was supplying the username and password in the jmxremort.password and jmxremote.access files i still had to supply the username and password from the client.

    You are right that i dont have to supply the user credentials if run locally. I have proved this as i can access the Tomcat's JVM via Jconsole.

    I am accessing it programmatically so i have to supply a URL which is shown below service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi

    I then get the jmx server as shown below.

    url = new JMXServiceURL(urlString);         
    Hashtable<String, String[]> env = new Hashtable<String, String[]>();
    String[] credentials = new String[] {user,pass};
    env.put(JMXConnector.CREDENTIALS, credentials);         
    jmxc = JMXConnectorFactory.connect(url,env); 
    mbsc = jmxc.getMBeanServerConnection(); 
    

    If i am accessing this locally how would i go about this? I know that it dont work locally without the user credentials as that is how i found out that i need to provide. if Jconsole or visualvm can connect to it then there must be a different approach that allows retrieving the Tomcat jmx server without having to supply the port number.

    The URL includes a port number. If im accessing the JMX server programmatically, how would i access it without having to specify the port number?

    By the way i am using Tomcat 5.5 and JDK 1.6

    Thanks