问题
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 theJMXAuthenticator
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:
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
.
来源:https://stackoverflow.com/questions/27192456/jmx-authentication-role-based-mbean-operations