JMX Authentication - Role Based MBean Operations

822 views Asked by At

I have implemented JMXAuthenticator for JMX authentication over RMI, however I am not sure how to create roles to allow for readonly/readwrite access levels. For example, in JMXAuthenticator.authenticate I have my custom authentication logic and want this to determine the access role. I have tried the following but it makes no difference when performing operations in JConsole:

@Override
public Subject authenticate(Object credentials) {
    Subject subject = new Subject();
    JMXPrincipal p;

    //...my logic
    String accessLevel = myCustomLogic();
    if (accessLevel.equals("admin")) {
        p = new JMXPrincipal("adminrole");
    } else {
        p = new JMXPrincipal("basicrole");
    }

    subject.getPrincipals().add(p);
    return subject;
}

I have then created an access file, jmxaccess.properties, containing

adminuser readwrite
basicuser readonly

and jmx.management.properties which contains com.sun.management.jmxremote.access.file=PATH TO ACCESS FILE and I run the application with -Dcom.sun.management.config.file=PATH TO jmx.management.properties.

However when I connect through JConsole and authenticate as a basicuser (read only access) I can access setters on the bean. I am connecting via the full service:jmx:rmi:... url.

So my questions are

  • Do I need to annotate/do anything to the setters in my bean to specify them as visible only to admin users?
  • Am I not building the Subject object correctly which the JMXAuthenticator returns?
  • Any other config/setup that is missing?

Thanks

Edit My MBean is just a basic POJO with private fields that have public getters and setters plus one other public method.

1

There are 1 answers

1
clicky On BEST ANSWER

Found the answer: need to implement a custom invocation handler via InvocationHandler interface. This intercepts server calls before they reach the beans. Inside the authenticate method you need to check the principals

AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
Set principals = subject.getPrincipals(JMXPrincipal.class);
if(principals != null && !principals.isEmpty()) {
    Principal principal = (Principal)principals.iterator().next();
    //your checks
}

I extended JMXPrincipal (one extension per access level) and assigned it to the Subject in the Authenticator above, then after retrieving the principal in the IH, I can check the type via instanceof and either allow the action to continue or throw a SecurityException.