participate


Remote Method Invocation (RMI) - JMX-RMI-SSL
<<   Back to Forum  |   Give us Feedback
This topic has 12 replies on 1 page.
tgil
Posts:9
Registered: 9/8/97
JMX-RMI-SSL   
Jan 30, 2006 4:12 PM

 
I am trying to run a JMX application secured by SSL and passwords and accessed by jconsole. According to documentation it is achieved by setting system properties. OK I got it to work designeating an SSL port and configuring certificate stores on both application and jconsole client.

Authentication and discovery probably are using my SSL port but there are additional connections that are active later on using different ports. I suppose they are JMX-RMI connections - but I dont know if they are using SSL. Additionally I cannot use arbitrarily assigned ports because of firewalling. I would expect that RMI should work over the existing SSL conection.

I dont want to (can not) program RMI directly but would prefer to declare it via appropriate JMX configuration parameters. Also I want to use the jconsole as JMX client and not code up my own.

Any tips? ideas? thanks

Thomas
 
lmalvent
Posts:168
Registered: 2/2/98
Re: JMX-RMI-SSL   
Feb 2, 2006 7:36 AM (reply 1 of 12)  (In reply to original post )

 
Hi Thomas,

Unfortunately you won't be able to export the JVM's RMIServer and RMIConnection
remote objects on a given port.

"com.sun.management.jmxremote.port" in the management.properties file applies to
the port where the RMIRegistry will be reachable. Moreover, the JVM's agent cannot
be configured with custom RMI socket factories. Through the management.properties
file you can just configure the standard SSL RMI socket factories but you cannot supply
a port for the RMIServer and RMIConnection remote objects to be exported.

However, you could create your own RMIConnectorServer supplying the platform
MBeanServer as input by calling the ManagementFactory.getPlatformMBeanServer()
static method and tell the server in which port remote objects should be exported. In
order to do this you don't need to supply custom RMI socket factories (and still use the
standard SSL RMI socket factories) but just use the following JMXServiceURL:

JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi://localhost:3000/jndi/rmi://localhost:9000/server");

which tells the RMIConnectorServer to bind to the RMIRegistry running on port 9000
and to export the RMIServer and RMIConnection remote objects on port 3000.

The following server's code snippet allows to mimic the functionality implemented by
the out-of-the-box management agent:

...

// Start rmi registry
//
System.out.println("Create the RMI registry on port 9000");
java.rmi.registry.LocateRegistry.createRegistry(9000);

// Instantiate the MBean server
//
System.out.println("Get the platform's MBean server");
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

// Environment map
//
System.out.println("Initialize the environment map");
HashMap env = new HashMap();

// Provide SSL-based RMI socket factories.
//
SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
csf);
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
ssf);

// Provide the password file used by the connector server to
// perform user authentication. The password file is a properties
// based text file specifying username/password pairs. This
// properties based password authenticator has been implemented
// using the JMXAuthenticator interface and is passed to the
// connector through the "jmx.remote.authenticator" property
// in the map.
//
// This property is implementation-dependent and might not be
// supported by all implementations of the JMX Remote API.
//
env.put("jmx.remote.x.password.file", "password.properties");

// Provide the access level file used by the connector server to
// perform user authorization. The access level file is a properties
// based text file specifying username/access level pairs where
// access level is either "readonly" or "readwrite" access to the
// MBeanServer operations. This properties based access control
// checker has been implemented using the MBeanServerForwarder
// interface which wraps the real MBean server inside an access
// controller MBean server which performs the access control checks
// before forwarding the requests to the real MBean server.
//
// This property is implementation-dependent and might not be
// supported by all implementations of the JMX Remote API.
//
env.put("jmx.remote.x.access.file", "access.properties");

// Create an RMI connector server
//
System.out.println("Create an RMI connector server");
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi://localhost:3000/jndi/rmi://localhost:9000/server");
JMXConnectorServer cs =
JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);

// Start the RMI connector server
//
System.out.println("Start the RMI connector server");
cs.start();
...

Concerning the SSL interactions between the client (JConsole) and the server, all the
remote method invocations over the RMIServer and RMIConnection remote objects
are performed through SSL. Only the retrieval of the stubs from the RMIRegistry is not
performed through SSL but through a plain socket. In the out-of-the-box management
agent you cannot use SSL-protected RMI registries. This limitation has been fixed in
the out-of-the-box management agent that ships with Java SE 6 (Mustang) by means
of a new property "com.sun.management.jmxremote.registry.ssl=true" in the
management.properties file. Mustang's JConsole has also been updated to
be able to fetch the RMIServer stubs from an SSL-protected RMIRegistry.

Regards,
Luis-Miguel ALVENTOSA
JMX - Java SE development team
Sun Microsystems, Inc.
 
tgil
Posts:9
Registered: 9/8/97
Re: JMX-RMI-SSL   
Feb 2, 2006 5:43 PM (reply 2 of 12)  (In reply to #1 )

 
Thanks for this extensive answer whcih should become part of the user guide. I started securing the JMX server without much experience with RMI.

I got pretty close to the desired behavior using code like this:

JMXConnectorServer jmxc = null;
RMIServerImpl rmis = new RMIJRMPServerImpl( 5101, csf, ssf, env );
jmxc = new RMIConnectorServer( serviceURL, env, rmis, null );


where the jmxc is registered into my MBeanServer. Your demonstration of the use of the URL specifying ports is very helpful. Also I learned how to run rmiregistry in the same JVM.

Thomas
 
tgil
Posts:9
Registered: 9/8/97
Re: JMX-RMI-SSL   
Feb 17, 2006 11:53 AM (reply 3 of 12)  (In reply to #1 )

 
Thanks again - I got my project going thanks to your help and pretty much using your example code.

It might be helpful to add what system props should be defined. It seems it is necessary to have and what not to have:

#turn this off - wrapper.java.additional.1=-Dcom.sun.management.jmxremote.port=5100
wrapper.java.additional.1=-Dcom.sun.management.jmxremote
wrapper.java.additional.2=-Dcom.sun.management.jmxremote.authenticate=true
wrapper.java.additional.3=-Dcom.sun.management.jmxremote.ssl=true
wrapper.java.additional.4=-Dcom.sun.management.jmxremote.ssl.need.client.auth=false
 
Maybe some of them are defaults but I have them set up for clarity. The jmxremote.port should not be set because otherwise JMX sets up another connector.

What is also needed are the standard SSL keystore parameters:

wrapper.java.additional.5=-Djavax.net.ssl.keyStore=....
wrapper.java.additional.6=-Djavax.net.ssl.keyStorePassword=.....


btw - "wrapper" is open source project that enables running Java as Windows service

-Thomas
 
zzr994
Posts:3
Registered: 7/19/06
Re: JMX-RMI-SSL   
Jul 19, 2006 8:49 AM (reply 4 of 12)  (In reply to #3 )

 
Hi,

I tried the same example, but it did not work for me. I used the code snippet given above and also the properies. When I invoke the jconsole and click on the local TAB, I do not see the process ID of the agent. I do see the agent PID when I am using out-of-the-box agent. I also clicked on remote TAB to see if I can connect using the username and password.

I am using jdk1.5.0_06 for both agent and jconsole

My main goal is to make the agent work when a firewall is involved and the stubs to be exported to a known port.

Any information will be useful.

Thanks.

Lester...
 
zzr994
Posts:3
Registered: 7/19/06
Re: JMX-RMI-SSL   
Jul 19, 2006 9:27 AM (reply 5 of 12)  (In reply to #4 )

 
This is how I am invoking my application.

"C:\Program Files\Java\jdk1.5.0_06\bin\java"
-Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password \ -Dcom.sun.management.jmxremote.authenticate=true \
-Dcom.sun.management.jmxremote.ssl=true \
-Dcom.sun.management.jmxremote.ssl.need.client.auth=false myApp

I tried jconsole from the same machine that the agent is running on.
 
zzr994
Posts:3
Registered: 7/19/06
Re: JMX-RMI-SSL   
Jul 19, 2006 9:36 AM (reply 6 of 12)  (In reply to #5 )

 
I got it working by commenting the following lines in my code:
//env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
//env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);

Thanks for the above posts that helped me in resolving the problem.
 
ousies
Posts:6
Registered: 17/06/03
Re: JMX-RMI-SSL   
Sep 28, 2006 10:54 AM (reply 7 of 12)  (In reply to #6 )

 
Does the above fix mean that I still have to open an additional [known] port on the firewall, or can I make use of SSH tunneling and then connect jconsole to the tunneled port on my localhost without getting involved with security issues and opening additional ports on the corporate firewall?

Thank you.
 
lmalvent
Posts:168
Registered: 2/2/98
Re: JMX-RMI-SSL   
Sep 29, 2006 1:52 AM (reply 8 of 12)  (In reply to #7 )

 
For more detailed info on JMX over an SSH Tunnel have a look at:

http://forum.java.sun.com/thread.jspa?forumID=4&threadID=565139
 
ousies
Posts:6
Registered: 17/06/03
Re: JMX-RMI-SSL   
Sep 29, 2006 3:25 AM (reply 9 of 12)  (In reply to #7 )

 
I got this to work without additional ports to be openened on the firewall. This is what I did:

I added the code snippet mentioned above in a static initializer in the class with the main method, with the following applications VM args:
-Drmi.remote.objects.port=3000 \
-Drmi.connector.server.port=9000 \
-Djavax.net.ssl.keyStore=keystore \
-Djavax.net.ssl.keyStorePassword=password \
-Djava.rmi.server.hostname=localhost \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.ssl=true \
-Dcom.sun.management.jmxremote.authenticate=true \
-Dcom.sun.management.jmxremote.ssl.need.client.auth=false

As you can see I made the 3000 and 9000 port numbers configurable, but in the end realized that it is not necessary, because when I use other ports, my application can't start (Connection refused exceptions).

Also note that I had to add this VM arg:
-Djava.rmi.server.hostname=localhost \
as I need to force the data port (which is in fact tunnelled to a local port on my localhost) to be looked up on localhost. If I don't add this, the JDK automatically resolves the RMI server's host name to be the internal IP of the behind-the-firewall-remote-machine.

I also noticed that the tunnelled ports on my localhost have to match the 3000 and 9000 of the remote application, otherwise it doesn't work.

Here is my ssh tunnelling command:
ssh -C -L 3000:localhost:3000 -L 9000:localhost:9000 user@remote-server.com

When opening JConsole, I go to the Advanced tab, and complete following information:
JMX URL:  service:jmx:rmi://localhost:3000/jndi/rmi://localhost:9000/server
User Name:  username configured in password.properties
Password:  password configured in password.properties

Also just make sure that you have configured the access levels (readonly, readwrite) correctly for the users in password.properties.

Thanks,
Gerrit
 
lmalvent
Posts:168
Registered: 2/2/98
Re: JMX-RMI-SSL   
Sep 29, 2006 4:36 AM (reply 10 of 12)  (In reply to #9 )

 
The -Dcom.sun.management.jmxremote* system properties are not needed as you are starting your own RMI connector server and not the RMI connector server used by the out-of-the-box management agent.

Regards,
Luis
 
ousies
Posts:6
Registered: 17/06/03
Re: JMX-RMI-SSL   
Sep 29, 2006 5:11 AM (reply 11 of 12)  (In reply to #10 )

 
Thank you for this pointer Luis. I removed them and all still working as it should.

Gerrit
 
ousies
Posts:6
Registered: 17/06/03
Re: JMX-RMI-SSL   
Sep 29, 2006 8:14 AM (reply 12 of 12)  (In reply to #11 )

 
OK I lied. I still have issues. Here is a picture indicating that essentially I'm trying to tunnel from my machine to machine_b, via machine_a.

                                         |-LAN--------------------------------|
|------------| VPN |-----------| VPN con |  |------------|     |-----------|  |
| my machine |-----| machine_a |---------|--| VPN server |-----| machine_b |  | 
|------------|     |-----------|         |  |------------|     |-----------|  |
                                         |------------------------------------|


When I tunnel like this:
ssh -vvv -C -L 3000:machine_b.vpn.ip:3000 -L 9000:machine_b.vpn.ip:9000 user@machine_a.vpn.ip
then I get "Connection failed" in JConsole. On the tunnel screen I get:
channel 3: open failed: connect failed: Connection timed out
I'm still using the same JMX URL:
service:jmx:rmi://localhost:3000/jndi/rmi://localhost:9000/server

Anyone have any advice about this?

Thanks in advance,
Gerrit
 
This topic has 12 replies on 1 page.
Back to Forum
 
Read the Developer Forums Code of Conduct

Click to email this message Email this Topic

Edit this Topic
  
 
 
Forums Statistics

About Sun forums
  • Sun Forums is a large collection of user generated discussions. It is here to help you ask questions, find answers, and participate in discussions.

    Check out our guide on Getting started with Sun Forums for a full walkthrough of how to best leverage the benefits of this community.

Powered by Jive Forums