All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bagri.server.hazelcast.security.BagriJAASInvocationHandler Maven / Gradle / Ivy

The newest version!
package com.bagri.server.hazelcast.security;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXPrincipal;
import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bagri.core.system.Permission;
import com.bagri.server.hazelcast.management.UserManagement;
import com.bagri.server.hazelcast.management.UserManager;
import com.bagri.support.security.LocalSubject;
import com.bagri.support.util.JMXUtils;

public class BagriJAASInvocationHandler implements InvocationHandler {

    private static final transient Logger logger = LoggerFactory.getLogger(BagriJAASInvocationHandler.class);
	
	private MBeanServer mbs;
	private UserManagement autzManager;
	
	private BagriJAASInvocationHandler(UserManagement autzManager) {
		this.autzManager = autzManager;
	}
	
	public static MBeanServerForwarder newProxyInstance(UserManagement autzManager) {

		Object proxy = Proxy.newProxyInstance(
				MBeanServerForwarder.class.getClassLoader(), 
				new Class[] {MBeanServerForwarder.class}, 
				new BagriJAASInvocationHandler(autzManager));

		return MBeanServerForwarder.class.cast(proxy);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		logger.trace("invoke.enter; method: {}; args: {}", method.getName(), args); 

		final String methodName = method.getName();

		if (methodName.equals("getMBeanServer")) {
			return mbs;
		}

		if (methodName.equals("setMBeanServer")) {
			if (args[0] == null) {
				throw new IllegalArgumentException("Null MBeanServer");
			}
			if (mbs != null) {
				throw new IllegalArgumentException("MBeanServer already initialized");
			}
			mbs = (MBeanServer) args[0];
			return null;
		}

		if (args == null || args.length == 0 || !(args[0] instanceof ObjectName)) {
			// some MBeanServer method
			return method.invoke(mbs, args);
		}
		
		// Retrieve Subject from current AccessControlContext
		AccessControlContext acc = AccessController.getContext();
		Subject subject = Subject.getSubject(acc);

		logger.trace("invoke; got Subject: {}", subject); 
		
		// Allow operations performed locally on behalf of the connector server
		// itself
		if (subject == null) {
			return method.invoke(mbs, args);
		} else {
			//
			LocalSubject.setSubject(subject);
		}

		// Restrict access to "createMBean" and "unregisterMBean" to any user
		//if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) {
		//	throw new SecurityException("Access denied");
		//}
		
		// Retrieve JMXPrincipal from Subject
		Set principals = subject.getPrincipals(JMXPrincipal.class);
		if (principals == null || principals.isEmpty()) {
			throw new SecurityException("No principal found. Access denied");
		}
		Principal principal = principals.iterator().next();
		String identity = principal.getName();
		ObjectName oName = (ObjectName) args[0];
		
		if (checkPermissions(identity, methodName, oName)) {
			return method.invoke(mbs, args);
		}

		throw new SecurityException("Access denied to resource: " + oName.toString());
	}
	
	public boolean checkPermissions(String identity, String methodName, ObjectName target) {

		logger.trace("checkPermissions.enter; identity: {}; method: {}; target: {}", identity, methodName, target); 
		
		if (!JMXUtils.domain.equals(target.getDomain())) {
			// grant access to other domains
			logger.trace("checkPermissions.exit; returning: true"); 
			return true;
		}
		
		UserManager uMgr = (UserManager) autzManager.getEntityManager(identity);
		if (uMgr == null) {
			// unknown user, shouldn't be this
			logger.trace("checkPermissions.exit; returning: false"); 
			return false;
		}
		
		//Map xPerms = uMgr.getAllPermissions();
		Map xPerms = uMgr.getFlatPermissions();
		Permission xPerm = xPerms.get(target.toString());
		if (xPerm == null) {
			//no permissions granted to this resource
			logger.trace("checkPermissions.exit; returning: false"); 
			return false;
		}

		if ((methodName.startsWith("getAttribute") || methodName.equals("getMBeanInfo") 
				|| methodName.equals("isInstanceOf") || methodName.equals("isRegistered")
				|| methodName.equals("queryMBeans") || methodName.equals("queryNames"))
				&& xPerm.hasPermission(Permission.Value.read)) {
			// granted read access
			logger.trace("checkPermissions.exit; returning: true"); 
			return true;
		}

		if (methodName.startsWith("setAttribute") && xPerm.hasPermission(Permission.Value.modify)) {
			// granted write access
			logger.trace("checkPermissions.exit; returning: true"); 
			return true;
		}

		if (methodName.equals("invoke") && xPerm.hasPermission(Permission.Value.execute)) {
			// granted execute access
			logger.trace("checkPermissions.exit; returning: true"); 
			return true;
		}

		logger.trace("checkPermissions.exit; returning: false"); 
		return false;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy