Applies to: JBoss 4.0.5 GA

As I am working on a rather complex application with a lot of dependancy bounded MBeans I found it necessary to have a small application, in a different JVM, invoke a MBean method for administrative purposes. Even if this sounded easy at the begining it seemed that I had to face 2 problems:

  • JBoss JMX implementation
  • JAAS access to the secured console

Since I both googled and searched JBoss forums without much help I decided, upon succeding, to write this article as it might help someone futher.

The ideea was to get access to a MBean service with the name:

ro.nit.test:service=Test

and to be able to get it’s “Message” attribute and also invoke a remove method called: “printMessage”. The jmx-console was protected with admin/simple

The working code is:

AppCallbackHandler handler = new AppCallbackHandler("admin", "simple".toCharArray());
LoginContext lc = new LoginContext("TestClient", handler);
System.out.println("Created LoginContext");lc.login();

Hashtable env = new Hashtable();
String factory = "org.jnp.interfaces.NamingContextFactory";
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
String url1 = "jnp://localhost:1099";env.put(Context.PROVIDER_URL, url1);
env.put(Context.SECURITY_CREDENTIALS, "simple");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_PROTOCOL, "testLoginInitialContext");
Context ctx = new InitialContext(env);
MBeanServerConnection mconn = (MBeanServerConnection) ctx.lookup("jmx/invoker/RMIAdaptor");
ObjectName name = new ObjectName("ro.nit.test:service=Test");
Object val = mconn.getAttribute(name, "Message");
System.out.println(name + "\n\tmessage=" + val);
mconn.invoke(name, "printMessage", null, null);

This makes use of the following CallbackHandler implementation:

static class AppCallbackHandler implements CallbackHandler {
private String username;
private char[] password;

public AppCallbackHandler(String username, char[] password) {
	this.username = username;
	this.password = password;
}

public void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException {
	for (int i = 0; i < callbacks.length; i++) {
		if (callbacks[i] instanceof NameCallback) {
			NameCallback nc = (NameCallback) callbacks[i];
			nc.setName(username);
		} else if (callbacks[i] instanceof PasswordCallback) {
			PasswordCallback pc = (PasswordCallback) callbacks[i];
			pc.setPassword(password);
		} else {
			throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
		}
	}
}
}

The “auth.conf” file required by JAAS:

other {   
   // jBoss LoginModule   org.jboss.security.ClientLoginModule  required   ;
   // Put your login modules that need jBoss here};

The JVM parameters:

-Djava.security.auth.login.config=file:${path to file}/auth.conf

Links with helped me found the solution:

Some errors which I got on the way:

  • Exception in thread “main” java.lang.SecurityException: Failed to authenticate principal=null, securityDomain=jmx-console

The original code (according to JSR160):

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8080/<span class="highlightedSearchTerm">jmx-console</span>");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName stdMBeanName = new ObjectName("ro.nit.test:service=Test");
mbsc.setAttribute(stdMBeanName, new Attribute("Message", "New message set from remote"));
// TODO, will not work with JBOSS since it does not implement the
// JMX properly
// http://www.jboss.com/index.html?module=bb&op=viewtopic&t=95530&view=previous

Comments:

Buttigieg Luc -

Hi, following your advices and some other from the resources that you are explaining, I succeeded to get a remote connection with a secured JBoss with the following code:

Hashtable env = new Hashtable();
String factory = “org.jboss.security.jndi.JndiLoginInitialContextFactory”;
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
String url = “jnp://localhost:1099”;
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_CREDENTIALS, “simple”);
env.put(Context.SECURITY_PRINCIPAL, “admin”);
Context ctx = new InitialContext(env);

Thanks,
Luc


Sid -

thanks for this post. it has been extremely helpful!


r -

Saved me a bunch of time


Len -

Glad I could help.


nicolae -

Thanks for the content. It was really helpful


Torsten -

Thanks from me too - helped me as well!


Pat -

Did you run this as a Standalone client or from within a Jboss server ? I can run something similar from a standalone client but it failes with a principal=null, when I run the *same* class from within a servlet. I think the JBoss server expects security credentials passed in a different way ? One more thing : You auth.conf has *both* the lines commented out. Is that how you wanted ? thanks Pat


len -

Hello Pat, I think it’s possible things have changed a lot since I wrote this article. Surely they don’t work in JBoss 5. Unfortunately with each new jboss you have to retest and re-find many things. I wish you luck. Len