You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by tu...@apache.org on 2015/08/27 14:27:20 UTC
[4/6] incubator-geode git commit: GEODE-77 : Integrated Security Code
Merge Review board url : https://reviews.apache.org/r/37209/
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/CLIOperationContext.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/CLIOperationContext.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/CLIOperationContext.java
index b0198e4..f5a101d 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/CLIOperationContext.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/CLIOperationContext.java
@@ -7,116 +7,164 @@ import java.util.Map;
import org.springframework.shell.event.ParseResult;
-import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.GemFireConfigException;
import com.gemstone.gemfire.management.cli.CommandProcessingException;
import com.gemstone.gemfire.management.internal.cli.CommandManager;
import com.gemstone.gemfire.management.internal.cli.GfshParseResult;
import com.gemstone.gemfire.management.internal.cli.GfshParser;
+import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
import com.gemstone.gemfire.management.internal.cli.parser.CommandTarget;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.*;
-
+/**
+ * It represents command being executed and all passed options and option-values.
+ * ResourceOpCode returned by CLIOperationContext is retrieved from ResourceOperation
+ * annotation on the target command
+ *
+ * @author tushark
+ * @since 9.0
+ */
public class CLIOperationContext extends ResourceOperationContext {
-
- private OperationCode code = OperationCode.RESOURCE;
- private ResourceOperationCode resourceCode = null;
- private Map<String,String> commandOptions = null;
-
- private static Map<String,ResourceOperationCode> commandToCodeMapping = new HashMap<String,ResourceOperationCode>();
- private static CommandManager commandManager = null;
- private static GfshParser parser = null;
-
- public CLIOperationContext(String commandString) throws CommandProcessingException, IllegalStateException{
- code = OperationCode.RESOURCE;
- GfshParseResult parseResult = (GfshParseResult) parseCommand(commandString);
- this.commandOptions = parseResult.getParamValueStrings();
- this.resourceCode = findResourceCode(parseResult.getCommandName()); //need to add this to ParseResult
- }
-
- private static ParseResult parseCommand(String commentLessLine) throws CommandProcessingException, IllegalStateException {
+
+ private OperationCode code = OperationCode.RESOURCE;
+ private ResourceOperationCode resourceCode = null;
+ private Map<String,String> commandOptions = null;
+
+ private static Map<String,ResourceOperationCode> commandToCodeMapping = new HashMap<String,ResourceOperationCode>();
+ private static CommandManager commandManager = null;
+ private static GfshParser parser = null;
+
+ public CLIOperationContext(String commandString) throws CommandProcessingException, IllegalStateException{
+ GfshParseResult parseResult = (GfshParseResult) parseCommand(commandString);
+ this.commandOptions = parseResult.getParamValueStrings();
+ this.resourceCode = findResourceCode(parseResult.getCommandName());
+ this.code = findOperationCode(parseResult.getCommandName());
+ }
+
+ /**
+ * This method returns OperationCode for command. Some commands perform data
+ * operations, for such commands OperationCode returned is not RESOURCE but
+ * corresponding data operation as defined in OperationCode
+ *
+ * @param commandName
+ * @return OperationCode
+ */
+ private OperationCode findOperationCode(String commandName) {
+
+ if(CliStrings.GET.equals(commandName) || CliStrings.LOCATE_ENTRY.equals(commandName))
+ return OperationCode.GET;
+
+ if(CliStrings.PUT.equals(commandName))
+ return OperationCode.PUT;
+
+ if(CliStrings.QUERY.equals(commandName))
+ return OperationCode.QUERY;
+
+ if (CliStrings.REMOVE.equals(commandName)) {
+ if (commandOptions.containsKey(CliStrings.REMOVE__ALL)
+ && "true".equals(commandOptions.get(CliStrings.REMOVE__ALL))) {
+ return OperationCode.REMOVEALL;
+ } else
+ return OperationCode.DESTROY;
+ }
+
+ if(CliStrings.CLOSE_DURABLE_CQS.equals(commandName)) {
+ return OperationCode.CLOSE_CQ;
+ }
+
+ if(CliStrings.CREATE_REGION.equals(commandName)) {
+ return OperationCode.REGION_CREATE;
+ }
+
+ if(CliStrings.DESTROY_REGION.equals(commandName)) {
+ return OperationCode.REGION_DESTROY;
+ }
+
+ if(CliStrings.EXECUTE_FUNCTION.equals(commandName)) {
+ return OperationCode.EXECUTE_FUNCTION;
+ }
+
+ //"stop cq"
+ //"removeall",
+ //"get durable cqs",
+ return OperationCode.RESOURCE;
+ }
+
+ private static ParseResult parseCommand(String commentLessLine) throws CommandProcessingException, IllegalStateException {
if (commentLessLine != null) {
return parser.parse(commentLessLine);
}
throw new IllegalStateException("Command String should not be null.");
}
-
- public static void registerCommand(CommandManager cmdManager, Method method, CommandTarget commandTarget){
- //Save command manager instance and create a local parser for parsing the commands
- if(commandManager==null){
- commandManager = cmdManager;
- parser = new GfshParser(cmdManager);
- }
-
- boolean found=false;
- Annotation ans[] = method.getDeclaredAnnotations();
- for(Annotation an : ans){
- if(an instanceof ResourceOperation) {
- cache(commandTarget.getCommandName(),(ResourceOperation)an);
- found=true;
- }
- }
- if(!found)
- cache(commandTarget.getCommandName(),null);
- }
+
+ public static void registerCommand(CommandManager cmdManager, Method method, CommandTarget commandTarget){
+ if(commandManager==null){
+ commandManager = cmdManager;
+ parser = new GfshParser(cmdManager);
+ }
+
+ boolean found=false;
+ Annotation ans[] = method.getDeclaredAnnotations();
+ for(Annotation an : ans){
+ if(an instanceof ResourceOperation) {
+ cache(commandTarget.getCommandName(),(ResourceOperation)an);
+ found=true;
+ }
+ }
+ if(!found)
+ cache(commandTarget.getCommandName(),null);
+ }
- private static void cache(String commandName, ResourceOperation op) {
- ResourceOperationCode code = null;
-
- if (op != null) {
- String opString = op.operation();
- if (opString != null)
- code = ResourceOperationCode.parse(opString);
- }
-
- if(code==null){
- if(commandName.startsWith("describe") || commandName.startsWith("list") || commandName.startsWith("status")
- || commandName.startsWith("show")){
- code = ResourceOperationCode.LIST_DS;
- }
- }
-
- //TODO : Have map according to each resources
- //TODO : How to save information for retrieving command Option map or region and serverGroup
-
- Resource targetedResource = null;
- if(op!=null){
- targetedResource = op.resource();
- } else {
- targetedResource = Resource.DISTRIBUTED_SYSTEM;
- //TODO : Add other resource and mbeans
- }
-
-
- LogService.getLogger().trace("#RegisterCommandSecurity : " + commandName + " code " + code + " op="+op);
-
- if(code!=null) {
- commandToCodeMapping.put(commandName, code);
- }
-
- }
+ private static void cache(String commandName, ResourceOperation op) {
+ ResourceOperationCode resourceOpCode = null;
+
+ if (op != null) {
+ String opString = op.operation();
+ if (opString != null)
+ resourceOpCode = ResourceOperationCode.parse(opString);
+ }
+
+ if(resourceOpCode==null){
+ if (commandName.startsWith(GETTER_DESCRIBE) || commandName.startsWith(GETTER_LIST)
+ || commandName.startsWith(GETTER_STATUS)) {
+ resourceOpCode = ResourceOperationCode.LIST_DS;
+ }
+ }
+
- public Map<String, String> getCommandOptions() {
- return commandOptions;
- }
+ if(resourceOpCode!=null) {
+ commandToCodeMapping.put(commandName, resourceOpCode);
+ } else {
+ throw new GemFireConfigException(
+ "Error while configuring authorization for gfsh commands. No opCode defined for command " + commandName);
- private static ResourceOperationCode findResourceCode(String commandName) {
- return commandToCodeMapping.get(commandName);
- }
+ }
+
+ }
+ public Map<String, String> getCommandOptions() {
+ return commandOptions;
+ }
- @Override
- public OperationCode getOperationCode() {
- return code;
- }
+ private static ResourceOperationCode findResourceCode(String commandName) {
+ return commandToCodeMapping.get(commandName);
+ }
- @Override
- public ResourceOperationCode getResourceOperationCode() {
- return resourceCode;
- }
-
-
- public String toString(){
- String str;
- str = "CLIOperationContext(resourceCode=" + resourceCode + ") options=" + commandOptions+")";
- return str;
- }
+
+ @Override
+ public OperationCode getOperationCode() {
+ return code;
+ }
+
+ @Override
+ public ResourceOperationCode getResourceOperationCode() {
+ return resourceCode;
+ }
+
+
+ public String toString(){
+ String str;
+ str = "CLIOperationContext(resourceCode=" + resourceCode + ") options=" + commandOptions+")";
+ return str;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JMXOperationContext.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JMXOperationContext.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JMXOperationContext.java
index 375cc27..49d30d6 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JMXOperationContext.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JMXOperationContext.java
@@ -9,153 +9,238 @@ import java.util.Map;
import javax.management.ObjectName;
import com.gemstone.gemfire.GemFireConfigException;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.management.AsyncEventQueueMXBean;
+import com.gemstone.gemfire.management.CacheServerMXBean;
+import com.gemstone.gemfire.management.DiskStoreMXBean;
+import com.gemstone.gemfire.management.DistributedLockServiceMXBean;
+import com.gemstone.gemfire.management.DistributedRegionMXBean;
import com.gemstone.gemfire.management.DistributedSystemMXBean;
+import com.gemstone.gemfire.management.GatewayReceiverMXBean;
+import com.gemstone.gemfire.management.GatewaySenderMXBean;
+import com.gemstone.gemfire.management.LocatorMXBean;
+import com.gemstone.gemfire.management.LockServiceMXBean;
+import com.gemstone.gemfire.management.ManagerMXBean;
+import com.gemstone.gemfire.management.MemberMXBean;
+import com.gemstone.gemfire.management.RegionMXBean;
import com.gemstone.gemfire.management.internal.MBeanJMXAdapter;
import com.gemstone.gemfire.management.internal.cli.util.ClasspathScanLoadHelper;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.*;
-
+/**
+ * It describes current JMX MBean Method call and its parameters.
+ * OpCode returned by JMXOperationContext is retrieved from ResourceOperation annotation
+ * on the target methodName
+ *
+ * @author tushark
+ * @since 9.0
+ *
+ */
public class JMXOperationContext extends ResourceOperationContext {
-
- private OperationCode code = OperationCode.RESOURCE;
- private ResourceOperationCode resourceCode = null;
-
- private static Map<String,ResourceOperationCode> cacheDSResourceOps = null;
- private static Map<String,ResourceOperationCode> cacheMemberResourceOps = null;
- private static Map<String,ResourceOperationCode> cacheRegionResourceOps = null;
- private static Map<String,ResourceOperationCode> cacheDiskStoreResourceOps = null;
-
- static {
- //cache all resource annotations
- readJMXAnnotations();
-
- }
+
+
+ private OperationCode code = OperationCode.RESOURCE;
+ private ResourceOperationCode resourceCode = null;
+ private ObjectName name;
+ private String methodName;
+
+ private static Map<Class<?>,Map<String,ResourceOperationCode>> cachedResourceOpsMapping = new HashMap<Class<?>,Map<String,ResourceOperationCode>>();
+ private static Map<String,ResourceOperationCode> distributedSystemMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> diskStoreMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> cacheServerMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> gatewayReceiverMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> gatewaySenderMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> lockServiceMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> managerMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> memberMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> regionMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> locatorMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> distributedLockServiceMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> distributedRegionMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> asyncEventQueueMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+ private static Map<String,ResourceOperationCode> accessControlMXBeanResourceOps = new HashMap<String,ResourceOperationCode>();
+
+
+ static {
+ readJMXAnnotations();
+ }
- private static void readJMXAnnotations() {
- try {
- Class[] klassList = ClasspathScanLoadHelper.getClasses("com.gemstone.gemfire.management");
- for(Class klass : klassList) {
- if(klass.getName().endsWith("MXBean")) {
- Method[] methods = klass.getMethods();
- for(Method method : methods) {
- String name = method.getName();
- //ResourceOperation op = method.getDeclaredAnnotations();(ResourceOperation.class);
- boolean found=false;
- Annotation ans[] = method.getDeclaredAnnotations();
- for(Annotation an : ans){
- if(an instanceof ResourceOperation) {
- cache(klass,name,(ResourceOperation)an);
- found=true;
- }
- }
- if(!found)
- cache(klass,name,null);
- }
- //TODO : Log all cached operations
- }
- }
- } catch (ClassNotFoundException e) {
- throw new GemFireConfigException(
- "Error while configuring authorization for jmx - ", e);
- } catch (IOException e) {
- throw new GemFireConfigException(
- "Error while configuring authorization for jmx - ", e);
- }
-
- }
-
- private static void cache(Class klass, String name, ResourceOperation op) {
- ResourceOperationCode code = null;
-
- if (op != null) {
- String opString = op.operation();
- if (opString != null)
- code = ResourceOperationCode.parse(opString);
- }
-
- if(code==null){
- if(name.startsWith("list") || name.startsWith("fetch") || name.startsWith("view")
- || name.startsWith("show")){
- code = ResourceOperationCode.LIST_DS;
- } else if (name.startsWith("get")){
- code = ResourceOperationCode.READ_DS;
- } else if (name.startsWith("is")){
- code = ResourceOperationCode.READ_DS;
- } else if (name.startsWith("set")){
- code = ResourceOperationCode.SET_DS;
- }
- }
-
- /*
- System.out.println("Klass " + klass + " mname : " + name);
- if (code != null)
- System.out.println("ResourceOperation code=" + code);
- else
- System.out.println("ResourceOperation is null");*/
-
- Resource targetedResource = null;
-
- if(op!=null){
- targetedResource = op.resource();
- } else {
- if(klass.equals(DistributedSystemMXBean.class)) {
- targetedResource = Resource.DISTRIBUTED_SYSTEM;
- }
- //TODO : Add other resource and mbeans
- }
-
- /* Comment for timebeing to avoid falling for other methods
- if(!isGetterSetter(name) && code==null){
- throw new GemFireConfigException(
- "Error while configuring authorization for jmx. No authorization defined for "
- + klass.getCanonicalName() + " method " + name);
- }*/
- if(targetedResource!=null) {
- switch (targetedResource) {
- case DISTRIBUTED_SYSTEM:
- if (code != null){
- if(cacheDSResourceOps==null)
- cacheDSResourceOps = new HashMap<String,ResourceOperationCode>();
- cacheDSResourceOps.put(name, code);
- }
- break;
- }
- }
- }
+ private static void readJMXAnnotations() {
+
+ cachedResourceOpsMapping.put(DistributedSystemMXBean.class, distributedSystemMXBeanResourceOps);
+ cachedResourceOpsMapping.put(DiskStoreMXBean.class, diskStoreMXBeanResourceOps);
+ cachedResourceOpsMapping.put(CacheServerMXBean.class, cacheServerMXBeanResourceOps);
+ cachedResourceOpsMapping.put(GatewayReceiverMXBean.class, gatewayReceiverMXBeanResourceOps);
+ cachedResourceOpsMapping.put(GatewaySenderMXBean.class, gatewaySenderMXBeanResourceOps);
+ cachedResourceOpsMapping.put(LockServiceMXBean.class, lockServiceMXBeanResourceOps);
+ cachedResourceOpsMapping.put(ManagerMXBean.class, managerMXBeanResourceOps);
+ cachedResourceOpsMapping.put(MemberMXBean.class, memberMXBeanResourceOps);
+ cachedResourceOpsMapping.put(RegionMXBean.class, regionMXBeanResourceOps);
+ cachedResourceOpsMapping.put(LocatorMXBean.class, locatorMXBeanResourceOps);
+ cachedResourceOpsMapping.put(DistributedLockServiceMXBean.class, distributedLockServiceMXBeanResourceOps);
+ cachedResourceOpsMapping.put(DistributedRegionMXBean.class, distributedRegionMXBeanResourceOps);
+ cachedResourceOpsMapping.put(AsyncEventQueueMXBean.class, asyncEventQueueMXBeanResourceOps);
+ cachedResourceOpsMapping.put(AccessControlMXBean.class, accessControlMXBeanResourceOps);
+
+ try {
+ Class<?>[] klassList = ClasspathScanLoadHelper.getClasses(MANAGEMENT_PACKAGE);
+ for(Class<?> klass : klassList) {
+ if(klass.getName().endsWith("MXBean")) {
+ Method[] methods = klass.getMethods();
+ for(Method method : methods) {
+ String name = method.getName();
+ boolean found=false;
+ Annotation ans[] = method.getDeclaredAnnotations();
+ for(Annotation an : ans){
+ if(an instanceof ResourceOperation) {
+ cache(klass,name,(ResourceOperation)an);
+ found=true;
+ }
+ }
+ if(!found)
+ cache(klass,name,null);
+ }
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ throw new GemFireConfigException(
+ "Error while configuring authorization for jmx - ", e);
+ } catch (IOException e) {
+ throw new GemFireConfigException(
+ "Error while configuring authorization for jmx - ", e);
+ }
+
+ }
+
+ private static void cache(Class<?> klass, String name, ResourceOperation op) {
+ ResourceOperationCode code = null;
+
+ if (op != null) {
+ String opString = op.operation();
+ if (opString != null)
+ code = ResourceOperationCode.parse(opString);
+ }
+
+ if(code==null && isGetterSetter(name)){
+ code = ResourceOperationCode.LIST_DS;
+ }
+
+
+ if (code == null && cachedResourceOpsMapping.keySet().contains(klass) && !isGetterSetter(name)) {
+ throw new GemFireConfigException("Error while configuring authorization for jmx. No opCode defined for "
+ + klass.getCanonicalName() + " method " + name);
+ }
+
+ final Map<String,ResourceOperationCode> resourceOpsMap = cachedResourceOpsMapping.get(klass);
+ if(resourceOpsMap==null) {
+ if (cachedResourceOpsMapping.keySet().contains(klass))
+ throw new GemFireConfigException("Unknown MBean " + klass.getCanonicalName());
+ else {
+ LogService.getLogger().warn("Unsecured mbean " + klass);
+ }
+ }
+ else {
+ resourceOpsMap.put(name, code);
+ }
+ }
- private static boolean isGetterSetter(String name) {
- if(name.startsWith("is") || name.startsWith("get") || name.startsWith("set") || name.startsWith("fetch")
- || name.startsWith("list") || name.startsWith("view") || name.startsWith("show") )
- return true;
- else return false;
- }
+ public static boolean isGetterSetter(String name) {
+ if(name.startsWith(GETTER_IS) || name.startsWith(GETTER_GET) || name.startsWith(GETTER_FETCH)
+ || name.startsWith(GETTER_LIST) || name.startsWith(GETTER_VIEW) || name.startsWith(GETTER_SHOW) || name.startsWith(GETTER_HAS))
+ return true;
+ else return false;
+ }
- public JMXOperationContext(ObjectName name , String methodName){
- code = OperationCode.RESOURCE;
- if(name.equals(MBeanJMXAdapter.getDistributedSystemName())){
- resourceCode = cacheDSResourceOps.get(methodName);
- }
- }
-
+ public JMXOperationContext(ObjectName name , String methodName){
+ code = OperationCode.RESOURCE;
+ Class<?> klass = getMbeanClass(name);
+ Map<String,ResourceOperationCode> resourceOpsMap = cachedResourceOpsMapping.get(klass);
+ resourceCode = resourceOpsMap.get(methodName);
+ this.methodName = methodName;
+ this.name = name;
+
+ //If getAttr is not found try for isAttr ie. boolean getter
+ if(resourceCode==null) {
+ if(this.methodName.startsWith(GET_PREFIX)) {
+ String methodNameBooleanGetter = GET_IS_PREFIX + this.methodName.substring(GET_PREFIX.length());
+ if(resourceOpsMap.containsKey(methodNameBooleanGetter)){
+ resourceCode = resourceOpsMap.get(methodNameBooleanGetter);
+ this.methodName = methodNameBooleanGetter;
+ }
+ }
+ }
+
+ //If resourceCode is still null most likely its wrong method name so just allow it pass
+ if(resourceCode==null) {
+ resourceCode = ResourceOperationCode.LIST_DS;
+ }
+ }
+
- @Override
- public OperationCode getOperationCode() {
- return code;
- }
+
- @Override
- public ResourceOperationCode getResourceOperationCode() {
- return resourceCode;
- }
+ private Class<?> getMbeanClass(ObjectName name) {
+ if (name.equals(MBeanJMXAdapter.getDistributedSystemName()))
+ return DistributedSystemMXBean.class;
+ else {
+ String service = name.getKeyProperty(MBEAN_KEY_SERVICE);
+ String mbeanType = name.getKeyProperty(MBEAN_KEY_TYPE);
- public static Map<String, ResourceOperationCode> getCacheDSResourceOps() {
- return cacheDSResourceOps;
- }
+ if (MBEAN_TYPE_DISTRIBUTED.equals(mbeanType)) {
+ if (MBEAN_SERVICE_SYSTEM.equals(service)) {
+ return DistributedSystemMXBean.class;
+ } else if (MBEAN_SERVICE_REGION.equals(service)) {
+ return DistributedRegionMXBean.class;
+ } else if (MBEAN_SERVICE_LOCKSERVICE.equals(service)) {
+ return DistributedLockServiceMXBean.class;
+ } else {
+ throw new RuntimeException("Unknown mbean type " + name);
+ }
+ } else if (MBEAN_TYPE_MEMBER.equals(mbeanType)) {
+ if (service == null) {
+ return MemberMXBean.class;
+ } else {
+ if (MBEAN_SERVICE_MANAGER.equals(service)) {
+ return ManagerMXBean.class;
+ } else if (MBEAN_SERVICE_CACHESERVER.equals(service)) {
+ return CacheServerMXBean.class;
+ } else if (MBEAN_SERVICE_REGION.equals(service)) {
+ return RegionMXBean.class;
+ } else if (MBEAN_SERVICE_LOCKSERVICE.equals(service)) {
+ return LockServiceMXBean.class;
+ } else if (MBEAN_SERVICE_DISKSTORE.equals(service)) {
+ return DiskStoreMXBean.class;
+ } else if (MBEAN_SERVICE_GATEWAY_RECEIVER.equals(service)) {
+ return GatewayReceiverMXBean.class;
+ } else if (MBEAN_SERVICE_GATEWAY_SENDER.equals(service)) {
+ return GatewaySenderMXBean.class;
+ } else if (MBEAN_SERVICE_ASYNCEVENTQUEUE.equals(service)) {
+ return AsyncEventQueueMXBean.class;
+ } else if (MBEAN_SERVICE_LOCATOR.equals(service)) {
+ return LocatorMXBean.class;
+ } else {
+ throw new RuntimeException("Unknown mbean type " + name);
+ }
+ }
+ } else {
+ throw new RuntimeException("Unknown mbean type " + name);
+ }
+ }
+ }
- public static void setCacheDSResourceOps(
- Map<String, ResourceOperationCode> cacheDSResourceOps) {
- JMXOperationContext.cacheDSResourceOps = cacheDSResourceOps;
- }
-
-
+ @Override
+ public OperationCode getOperationCode() {
+ return code;
+ }
+
+ @Override
+ public ResourceOperationCode getResourceOperationCode() {
+ return resourceCode;
+ }
+
+ public String toString(){
+ return "JMXOpCtx(on="+name+",method="+methodName+")";
+ }
}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JSONAuthorization.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JSONAuthorization.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JSONAuthorization.java
index d85ce65..5455818 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JSONAuthorization.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/JSONAuthorization.java
@@ -272,8 +272,8 @@ public class JSONAuthorization implements AccessControl, Authenticator {
@Override
public Principal authenticate(Properties props, DistributedMember arg1) throws AuthenticationFailedException {
- String user = props.getProperty(ManagementInterceptor.USER_NAME);
- String pwd = props.getProperty(ManagementInterceptor.PASSWORD);
+ String user = props.getProperty(ResourceConstants.USER_NAME);
+ String pwd = props.getProperty(ResourceConstants.PASSWORD);
User userObj = acl.get(user);
if(userObj==null)
throw new AuthenticationFailedException("Wrong username/password");
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/MBeanServerWrapper.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/MBeanServerWrapper.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/MBeanServerWrapper.java
index 50942c1..0b91350 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/MBeanServerWrapper.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/MBeanServerWrapper.java
@@ -1,6 +1,7 @@
package com.gemstone.gemfire.management.internal.security;
import java.io.ObjectInputStream;
+import java.util.HashSet;
import java.util.Set;
import javax.management.Attribute;
@@ -25,7 +26,17 @@ import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
import javax.management.remote.MBeanServerForwarder;
-
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.*;
+
+/**
+ * This class intercepts all MBean requests for GemFire MBeans and passed it to
+ * ManagementInterceptor for authorization
+ *
+ *
+ * @author tushark
+ * @since 9.0
+ *
+ */
public class MBeanServerWrapper implements MBeanServerForwarder {
private MBeanServer mbs;
@@ -35,52 +46,67 @@ public class MBeanServerWrapper implements MBeanServerForwarder {
this.interceptor = interceptor;
}
- private void doAuthorization(ObjectName name, String methodName, Object[] methodParams){
- interceptor.authorize(name,methodName, methodParams);
+ private ResourceOperationContext doAuthorization(ObjectName name, String methodName, Object[] methodParams){
+ return interceptor.authorize(name,methodName, methodParams);
+ }
+
+ private void doAuthorizationPost(ObjectName name, String methodName, ResourceOperationContext context, Object result){
+ interceptor.postAuthorize(name,methodName,context,result);
}
@Override
public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException,
InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
- doAuthorization(name, "createMBean", new Object[]{name});
- return mbs.createMBean(className, name);
+ ResourceOperationContext ctx = doAuthorization(name, CREATE_MBEAN, new Object[]{name});
+ ObjectInstance result = mbs.createMBean(className, name);
+ doAuthorizationPost(name, CREATE_MBEAN, ctx, result);
+ return result;
}
@Override
public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
- doAuthorization(name, "createMBean", new Object[]{name});
- return mbs.createMBean(className, name, loaderName);
+ ResourceOperationContext ctx = doAuthorization(name, CREATE_MBEAN, new Object[]{name});
+ ObjectInstance result = mbs.createMBean(className, name, loaderName);
+ doAuthorizationPost(name, CREATE_MBEAN, ctx, result);
+ return result;
}
@Override
public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
- doAuthorization(name, "createMBean", new Object[]{name, params});
- return mbs.createMBean(className,name,params,signature);
+ ResourceOperationContext ctx = doAuthorization(name, CREATE_MBEAN, new Object[]{name, params});
+ ObjectInstance result = mbs.createMBean(className,name,params,signature);
+ doAuthorizationPost(name, CREATE_MBEAN, ctx, result);
+ return result;
}
@Override
public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params,
String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException,
MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
- doAuthorization(name, "createMBean", new Object[]{name});
- return mbs.createMBean(className, name, loaderName, params, signature);
+ ResourceOperationContext ctx = doAuthorization(name, CREATE_MBEAN, new Object[]{name});
+ ObjectInstance result = mbs.createMBean(className, name, loaderName, params, signature);
+ doAuthorizationPost(name, CREATE_MBEAN, ctx, result);
+ return result;
}
@Override
public ObjectInstance registerMBean(Object object, ObjectName name) throws InstanceAlreadyExistsException,
MBeanRegistrationException, NotCompliantMBeanException {
- doAuthorization(name, "registerMBean", new Object[]{name});
- return mbs.registerMBean(object, name);
+ ResourceOperationContext ctx = doAuthorization(name, REGISTER_MBEAN, new Object[]{name});
+ ObjectInstance result = mbs.registerMBean(object, name);
+ doAuthorizationPost(name, REGISTER_MBEAN, ctx, result);
+ return result;
}
@Override
public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException {
- doAuthorization(name, "registerMBean", new Object[]{});
+ ResourceOperationContext ctx = doAuthorization(name, UNREGISTER_MBEAN, new Object[]{});
mbs.unregisterMBean(name);
+ doAuthorizationPost(name, UNREGISTER_MBEAN, ctx, null);
}
@Override
@@ -90,12 +116,32 @@ public class MBeanServerWrapper implements MBeanServerForwarder {
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
- return mbs.queryMBeans(name, query);
+ return filterAccessControlMBeanInstance(mbs.queryMBeans(name, query));
+ }
+
+ private Set<ObjectInstance> filterAccessControlMBeanInstance(Set<ObjectInstance> queryMBeans) {
+ Set<ObjectInstance> set = new HashSet<ObjectInstance>();
+ for(ObjectInstance oi : queryMBeans) {
+ if(!oi.getObjectName().equals(interceptor.getAccessControlMBeanON())){
+ set.add(oi);
+ }
+ }
+ return set;
}
@Override
- public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
- return mbs.queryNames(name, query);
+ public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
+ return filterAccessControlMBean(mbs.queryNames(name, query));
+ }
+
+ private Set<ObjectName> filterAccessControlMBean(Set<ObjectName> queryNames) {
+ Set<ObjectName> set = new HashSet<ObjectName>();
+ for(ObjectName oi : queryNames) {
+ if(!oi.equals(interceptor.getAccessControlMBeanON())){
+ set.add(oi);
+ }
+ }
+ return set;
}
@Override
@@ -111,36 +157,45 @@ public class MBeanServerWrapper implements MBeanServerForwarder {
@Override
public Object getAttribute(ObjectName name, String attribute) throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
- doAuthorization(name, "getAttribute", new Object[]{attribute});
- return mbs.getAttribute(name, attribute);
+ ResourceOperationContext ctx = doAuthorization(name, GET_ATTRIBUTE, new Object[]{attribute});
+ Object result = mbs.getAttribute(name, attribute);
+ doAuthorizationPost(name, GET_ATTRIBUTE, ctx, result);
+ return result;
}
@Override
public AttributeList getAttributes(ObjectName name, String[] attributes) throws InstanceNotFoundException,
ReflectionException {
- doAuthorization(name, "getAttributes", new Object[]{attributes});
- return mbs.getAttributes(name, attributes);
+ ResourceOperationContext ctx = doAuthorization(name, GET_ATTRIBUTES, new Object[]{attributes});
+ AttributeList result = mbs.getAttributes(name, attributes);
+ doAuthorizationPost(name,GET_ATTRIBUTES, ctx, result);
+ return result;
}
@Override
public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException,
AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
- doAuthorization(name, "setAttribute", new Object[]{attribute});
+ ResourceOperationContext ctx = doAuthorization(name, SET_ATTRIBUTE, new Object[]{attribute});
mbs.setAttribute(name, attribute);
+ doAuthorizationPost(name, SET_ATTRIBUTE, ctx, null);
}
@Override
public AttributeList setAttributes(ObjectName name, AttributeList attributes) throws InstanceNotFoundException,
ReflectionException {
- doAuthorization(name, "setAttributes", new Object[]{attributes});
- return mbs.setAttributes(name, attributes);
+ ResourceOperationContext ctx = doAuthorization(name, SET_ATTRIBUTES, new Object[]{attributes});
+ AttributeList result = mbs.setAttributes(name, attributes);
+ doAuthorizationPost(name, SET_ATTRIBUTES, ctx, result);
+ return result;
}
@Override
public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException {
- doAuthorization(name, operationName, new Object[]{params, signature});
- return mbs.invoke(name, operationName, params, signature);
+ ResourceOperationContext ctx = doAuthorization(name, operationName, new Object[]{params, signature});
+ Object result = mbs.invoke(name, operationName, params, signature);
+ doAuthorizationPost(name, operationName, ctx, result);
+ return result;
}
@Override
@@ -224,6 +279,7 @@ public class MBeanServerWrapper implements MBeanServerForwarder {
return mbs.instantiate(className, params, signature);
}
+ @SuppressWarnings("deprecation")
@Override
public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException,
OperationsException {
@@ -268,3 +324,4 @@ public class MBeanServerWrapper implements MBeanServerForwarder {
}
}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
index 1851977..9158ddd 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
@@ -1,13 +1,32 @@
package com.gemstone.gemfire.management.internal.security;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.ACCESS_DENIED_MESSAGE;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.GET_ATTRIBUTE;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.GET_ATTRIBUTES;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.GET_PREFIX;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.PASSWORD;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.PROCESS_COMMAND;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.SET_ATTRIBUTE;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.SET_ATTRIBUTES;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.SET_PREFIX;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.USER_NAME;
+import static com.gemstone.gemfire.management.internal.security.ResourceConstants.WRONGE_CREDENTIALS_MESSAGE;
+
import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.management.Attribute;
+import javax.management.AttributeList;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
@@ -22,234 +41,324 @@ import javax.security.auth.Subject;
import org.apache.logging.log4j.Logger;
import com.gemstone.gemfire.GemFireConfigException;
-import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.ClassLoadUtil;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.lang.StringUtils;
+import com.gemstone.gemfire.internal.logging.InternalLogWriter;
+import com.gemstone.gemfire.management.internal.ManagementConstants;
import com.gemstone.gemfire.security.AccessControl;
+import com.gemstone.gemfire.security.AuthenticationFailedException;
import com.gemstone.gemfire.security.Authenticator;
-@SuppressWarnings("rawtypes")
+/**
+ *
+ * ManagementInterceptor is central go-to place for all M&M Clients Authentication and Authorization
+ * requests
+ *
+ * @author tushark
+ * @since 9.0
+ *
+ */
public class ManagementInterceptor implements JMXAuthenticator {
- public static final String USER_NAME = "security-username";
- public static final String PASSWORD = "security-password";
- public static final String OBJECT_NAME_ACCESSCONTROL = "GemFire:service=AccessControl,type=Distributed";
- private MBeanServerWrapper mBeanServerForwarder;
- private Logger logger;
+ private MBeanServerWrapper mBeanServerForwarder;
+ private Logger logger;
+ private ObjectName accessControlMBeanON;
+ private Cache cache;
+ private String authzFactoryName;
+ private String postAuthzFactoryName;
+ private String authenticatorFactoryName;
+ private ConcurrentMap<Principal, AccessControl> cachedAuthZCallback;
+ private ConcurrentMap<Principal, AccessControl> cachedPostAuthZCallback;
- public ManagementInterceptor(Logger logger) {
- this.logger = logger;
- this.mBeanServerForwarder = new MBeanServerWrapper(this);
- registerAccessContorlMbean();
- LogService.getLogger().info("Starting management interceptor");
- }
+ public ManagementInterceptor(Cache gemFireCacheImpl, Logger logger) {
+ this.cache = gemFireCacheImpl;
+ this.logger = logger;
+ this.mBeanServerForwarder = new MBeanServerWrapper(this);
+ DistributedSystem system = cache.getDistributedSystem();
+ Properties sysProps = system.getProperties();
+ this.authzFactoryName = sysProps.getProperty(DistributionConfig.SECURITY_CLIENT_ACCESSOR_NAME);
+ this.postAuthzFactoryName = sysProps.getProperty(DistributionConfig.SECURITY_CLIENT_ACCESSOR_PP_NAME);
+ this.authenticatorFactoryName = sysProps.getProperty(DistributionConfig.SECURITY_CLIENT_AUTHENTICATOR_NAME);
+ this.cachedAuthZCallback = new ConcurrentHashMap<Principal, AccessControl>();
+ this.cachedPostAuthZCallback = new ConcurrentHashMap<Principal, AccessControl>();
+ registerAccessContorlMbean();
+ logger.info("Started Management interceptor on JMX connector");
+ }
- private void registerAccessContorlMbean() {
+ /**
+ * This method registers an AccessControlMBean which allows any remote JMX Client (for example Pulse) to check for
+ * access allowed for given Operation Code.
+ */
+ private void registerAccessContorlMbean() {
try {
- com.gemstone.gemfire.management.internal.security.AccessControl acc = new com.gemstone.gemfire.management.internal.security.AccessControl(this);
- ObjectName name = new ObjectName(OBJECT_NAME_ACCESSCONTROL);
+ com.gemstone.gemfire.management.internal.security.AccessControl acc = new com.gemstone.gemfire.management.internal.security.AccessControl(
+ this);
+ accessControlMBeanON = new ObjectName(ResourceConstants.OBJECT_NAME_ACCESSCONTROL);
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
- Set<ObjectName> names = platformMBeanServer.queryNames(name, null);
- if(names.isEmpty()) {
+ Set<ObjectName> names = platformMBeanServer.queryNames(accessControlMBeanON, null);
+ if (names.isEmpty()) {
try {
- platformMBeanServer.registerMBean(acc, name);
- logger.info("Registered AccessContorlMBean on " + name);
+ platformMBeanServer.registerMBean(acc, accessControlMBeanON);
+ logger.info("Registered AccessContorlMBean on " + accessControlMBeanON);
} catch (InstanceAlreadyExistsException e) {
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
+ throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource", e);
} catch (MBeanRegistrationException e) {
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
+ throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource", e);
} catch (NotCompliantMBeanException e) {
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
+ throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource", e);
}
}
- } catch (MalformedObjectNameException e) {
- e.printStackTrace();
+ } catch (MalformedObjectNameException e) {
+ throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource", e);
}
}
+ /**
+ * Delegates authentication to GemFire Authenticator
+ *
+ * @throws SecurityException
+ * if authentication fails
+ */
@Override
- public Subject authenticate(Object credentials) {
- String username = null, password = null;
- if (!(credentials instanceof String[])) {
- // Special case for null so we get a more informative message
- if (credentials == null) {
- // throw new SecurityException("Credentials required");
- username = "empty";
- password = "emptypwd";
- }
- // throw new SecurityException("Credentials should be String[]");
- username = "empty";
- password = "emptypwd";
-
- //TODO ***** Remove empty stuff
-
- } else {
- final String[] aCredentials = (String[]) credentials;
- username = (String) aCredentials[0];
- password = (String) aCredentials[1];
- }
-
- Properties pr = new Properties();
- pr.put(USER_NAME, username);
- pr.put(PASSWORD, password);
- getAuthenticator(pr).authenticate(pr, null);
- return new Subject(true, Collections.singleton(new JMXPrincipal(username)), Collections.EMPTY_SET,
- Collections.EMPTY_SET);
- }
-
- @SuppressWarnings("unchecked")
- public void authorize(ObjectName name, final String methodName, Object[] params) {
-
+ public Subject authenticate(Object credentials) {
+ String username = null, password = null;
+ Properties pr = new Properties();
+ if (credentials instanceof String[]) {
+ final String[] aCredentials = (String[]) credentials;
+ username = (String) aCredentials[0];
+ password = (String) aCredentials[1];
+ pr.put(USER_NAME, username);
+ pr.put(PASSWORD, password);
+ } else if (credentials instanceof Properties) {
+ pr = (Properties) credentials;
+ } else {
+ throw new SecurityException(WRONGE_CREDENTIALS_MESSAGE);
+ }
+
try {
- ObjectName accessControlMBean = new ObjectName(OBJECT_NAME_ACCESSCONTROL);
- if (name.equals(accessControlMBean)) {
- logger.info("Granting access to accessContorlMXBean.. name="+name);
- return;
+ Principal principal = getAuthenticator(cache.getDistributedSystem().getSecurityProperties()).authenticate(pr,
+ cache.getDistributedSystem().getDistributedMember());
+ return new Subject(true, Collections.singleton(new JMXPrincipal(principal.getName())), Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
+ } catch (AuthenticationFailedException e) {
+ //wrap inside Security exception. AuthenticationFailedException is gemfire class
+ //which generic JMX client can't serialize
+ throw new SecurityException("Authentication Failed " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Builds ResourceOperationContext for the given JMX MBean Request for delegates Authorization to
+ * gemfire AccessControl plugin with context as parameter
+ *
+ *
+ * @param name
+ * @param methodName
+ * @param params
+ *
+ * @throws SecurityException
+ * if access is not granted
+ */
+ public ResourceOperationContext authorize(ObjectName name, final String methodName, Object[] params) {
+
+ if (StringUtils.isBlank(authzFactoryName)){
+ return com.gemstone.gemfire.management.internal.security.AccessControlContext.ACCESS_GRANTED_CONTEXT;
+ }
+
+ if (name.equals(accessControlMBeanON)) {
+ return com.gemstone.gemfire.management.internal.security.AccessControlContext.ACCESS_GRANTED_CONTEXT;
+ }
+
+ if (!ManagementConstants.OBJECTNAME__DEFAULTDOMAIN.equals(name.getDomain()))
+ return com.gemstone.gemfire.management.internal.security.AccessControlContext.ACCESS_GRANTED_CONTEXT;
+
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+
+ // Allow operations performed locally on behalf of the connector server itself
+ if (subject == null) {
+ return com.gemstone.gemfire.management.internal.security.AccessControlContext.ACCESS_GRANTED_CONTEXT;
+ }
+
+ if (methodName.equals(ResourceConstants.CREATE_MBEAN) || methodName.equals(ResourceConstants.UNREGISTER_MBEAN)) {
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ }
+
+ Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+
+ if (principals == null || principals.isEmpty()) {
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ }
+
+ Principal principal = principals.iterator().next();
+
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Name=" + name + " methodName=" + methodName + " principal=" + principal.getName());
+ }
+
+ AccessControl accessControl = getAccessControl(principal, false);
+ String method = methodName;
+ if (methodName.equals(GET_ATTRIBUTE)) {
+ method = GET_PREFIX + (String) params[0];
+ } else if(methodName.equals(GET_ATTRIBUTES)) {
+ //Pass to first attribute getter
+ String[] attrs = (String[]) params[0];
+ method = GET_PREFIX + attrs[0];
+ } else if(methodName.equals(SET_ATTRIBUTE)) {
+ Attribute attribute = (Attribute) params[0];
+ method = SET_PREFIX + attribute.getName();
+ }
+
+ if (methodName.equals(SET_ATTRIBUTES)) {
+ AttributeList attrList = (AttributeList) params[0];
+ List<Attribute> list = attrList.asList();
+ ResourceOperationContext setterContext = null;
+ SetAttributesOperationContext resourceContext = new SetAttributesOperationContext();
+ for(int i=0;i<list.size();i++) {
+ Attribute attribute = list.get(i);
+ String setter = SET_PREFIX + attribute.getName();
+ setterContext = buildContext(name,setter,null);
+ boolean authorized = accessControl.authorizeOperation(null, setterContext);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Name=" + name + " methodName=" + methodName + " result=" + authorized + " principal="
+ + principal.getName());
+ }
+ if (!authorized)
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ else
+ resourceContext.addAttribute(attribute.getName(), setterContext);
+ }
+ return resourceContext;
+ } else {
+ ResourceOperationContext resourceContext = buildContext(name, method, params);
+ boolean authorized = accessControl.authorizeOperation(null, resourceContext);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Name=" + name + " methodName=" + methodName + " result=" + authorized + " principal="
+ + principal.getName());
}
- } catch (MalformedObjectNameException e) {
- // TODO Auto-generated catch block
- // e.printStackTrace();
- }
-
-
- //Only apply for gemfire domain
- String domain = name.getDomain();
- if(!"GemFire".equals(domain))
- return;
-
- // Retrieve Subject from current AccessControlContext
- AccessControlContext acc = AccessController.getContext();
- Subject subject = Subject.getSubject(acc);
- // Allow operations performed locally on behalf of the connector server
- // itself
- if (subject == null) {
- return;
- }
-
- // 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<JMXPrincipal> principals = subject
- .getPrincipals(JMXPrincipal.class);
- Set<Object> pubCredentials = subject.getPublicCredentials();
-
- /*System.out.println("JMXPrincipal " + principals);
- System.out.println("Principals " + subject.getPrincipals());
- System.out.println("PubCredentials " + subject.getPublicCredentials());*/
- //add condition -> check if accessor is configured
- if (principals == null || principals.isEmpty()
- /*|| pubCredentials.size() < 1 */) {
- throw new SecurityException("Access denied");
- }
-
- Principal principal = principals.iterator().next();
-
- //Give read access globally : TODO : Need to change this to map to proper getter
- LogService.getLogger().info("Name=" + name + " methodName=" + methodName + " principal="+ principal.getName());
- if("getAttribute".equals(methodName) || "getAttributes".equals(methodName))
- return;
-
- //TODO : if method=getAttributes params is directly availalbe
- //TODO : if method is operation then params is array array[0] = actual params, array[1]= signature
-
- ResourceOperationContext resourceContext = buildContext(name,methodName, params);
- boolean authorized = getAccessControl(principal).authorizeOperation(null, resourceContext);
- LogService.getLogger().info("Name=" + name + " methodName=" + methodName
- + " result="+authorized + " principal="+ principal.getName());
- if(!authorized)
- throw new SecurityException("Access denied");
- }
-
- public MBeanServerForwarder getMBeanServerForwarder() {
- return mBeanServerForwarder;
- }
-
- private static Class accessControlKlass = null;
-
- public AccessControl getAccessControl(Principal principal) {
- if(accessControlKlass==null) {
- String authorizeKlass = System.getProperty(ResourceConstants.RESORUCE_AUTH_ACCESSOR);
- try {
- accessControlKlass = Class.forName(authorizeKlass);
- } catch (ClassNotFoundException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- }
- }
-
- try {
- AccessControl accessControl = (AccessControl) accessControlKlass.newInstance();
- accessControl.init(principal, null, null); //TODO pass proper params
- LogService.getLogger().info("Returning resource accessControl");
- return accessControl;
- } catch (InstantiationException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- } catch (IllegalAccessException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- }
- }
-
- private static Class authenticatorClass = null;
- private Authenticator getAuthenticator(Properties pr) {
- if(authenticatorClass==null) {
- String authenticatorKlass = System.getProperty(ResourceConstants.RESORUCE_AUTHENTICATOR);
- try {
- authenticatorClass = Class.forName(authenticatorKlass);
- } catch (ClassNotFoundException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- }
- }
-
- try {
- Authenticator authenticator = (Authenticator) authenticatorClass.newInstance();
- authenticator.init(pr, null, null); //TODO pass proper params
- LogService.getLogger().info("Returning resource authenticator " + authenticator);
- return authenticator;
- } catch (InstantiationException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- } catch (IllegalAccessException e) {
- logger.error(e);
- throw new GemFireConfigException("Error while configuring accesscontrol for jmx resource",e);
- }
- }
- private ResourceOperationContext buildContext(ObjectName name, String methodName, Object[] params) {
- if (params != null) {
- LogService.getLogger().info("Params length=" + params.length);
- for (int i = 0; i < params.length; i++) {
- LogService.getLogger().info("Params[" + i + "] is " + arrayString(params[i]));
+ if (!authorized)
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ return resourceContext;
+ }
+ }
+
+ public MBeanServerForwarder getMBeanServerForwarder() {
+ return mBeanServerForwarder;
+ }
+
+ public AccessControl getAccessControl(Principal principal, boolean isPost) {
+ if (!isPost) {
+ if (cachedAuthZCallback.containsKey(principal)) {
+ return cachedAuthZCallback.get(principal);
+ } else if (!StringUtils.isBlank(authzFactoryName)) {
+ try {
+ Method authzMethod = ClassLoadUtil.methodFromName(authzFactoryName);
+ AccessControl authzCallback = (AccessControl) authzMethod.invoke(null, (Object[]) null);
+ authzCallback.init(principal, null, cache);
+ cachedAuthZCallback.put(principal, authzCallback);
+ return authzCallback;
+ } catch (Exception ex) {
+ throw new AuthenticationFailedException(
+ LocalizedStrings.HandShake_FAILED_TO_ACQUIRE_AUTHENTICATOR_OBJECT.toLocalizedString(), ex);
+ }
}
+ } else {
+ if (cachedPostAuthZCallback.containsKey(principal)) {
+ return cachedPostAuthZCallback.get(principal);
+ } else if (!StringUtils.isBlank(postAuthzFactoryName)) {
+ try {
+ Method authzMethod = ClassLoadUtil.methodFromName(postAuthzFactoryName);
+ AccessControl postAuthzCallback = (AccessControl) authzMethod.invoke(null, (Object[]) null);
+ postAuthzCallback.init(principal, null, cache);
+ cachedPostAuthZCallback.put(principal, postAuthzCallback);
+ return postAuthzCallback;
+ } catch (Exception ex) {
+ throw new AuthenticationFailedException(
+ LocalizedStrings.HandShake_FAILED_TO_ACQUIRE_AUTHENTICATOR_OBJECT.toLocalizedString(), ex);
+ }
+ }
+ }
+ return null;
+ }
+
+ private Authenticator getAuthenticator(Properties gfSecurityProperties) throws AuthenticationFailedException {
+ Authenticator auth;
+ try {
+ Method instanceGetter = ClassLoadUtil.methodFromName(this.authenticatorFactoryName);
+ auth = (Authenticator) instanceGetter.invoke(null, (Object[]) null);
+ } catch (Exception ex) {
+ throw new AuthenticationFailedException(
+ LocalizedStrings.HandShake_FAILED_TO_ACQUIRE_AUTHENTICATOR_OBJECT.toLocalizedString(), ex);
+ }
+ if (auth == null) {
+ throw new AuthenticationFailedException(
+ LocalizedStrings.HandShake_AUTHENTICATOR_INSTANCE_COULD_NOT_BE_OBTAINED.toLocalizedString());
}
+ auth.init(gfSecurityProperties,(InternalLogWriter) this.cache.getLogger(), (InternalLogWriter) this.cache.getSecurityLogger());
+ return auth;
+ }
+ private ResourceOperationContext buildContext(ObjectName name, String methodName, Object[] params) {
String service = name.getKeyProperty("service");
- // only member mbean does not have service KeyProperty
- if (service == null && "processCommand".equals(methodName)) {
+ if (service == null && PROCESS_COMMAND.equals(methodName)) {
Object[] array = (Object[]) params[0];
String command = (String) array[0];
- CLIOperationContext context = new CLIOperationContext(command);
- LogService.getLogger().info("Returning CLIContext for " + methodName);
+ CLIOperationContext context = new CLIOperationContext(command);
return context;
- } else {
+ } else {
ResourceOperationContext context = new JMXOperationContext(name, methodName);
- LogService.getLogger().info("Returning JMXOperationContext for " + methodName);
return context;
}
}
- private String arrayString(Object object) {
- StringBuilder sb = new StringBuilder();
- if (object instanceof Object[]) {
- Object[] array = (Object[]) object;
- for (Object a : array)
- sb.append(a).append(" ");
+ public ObjectName getAccessControlMBeanON() {
+ return accessControlMBeanON;
+ }
+
+ public void postAuthorize(ObjectName name, final String methodName, ResourceOperationContext context, Object result) {
+
+ if (StringUtils.isBlank(postAuthzFactoryName)){
+ return ;
+ }
+
+ context.setPostOperationResult(result);
+
+ if (context.equals(com.gemstone.gemfire.management.internal.security.AccessControlContext.ACCESS_GRANTED_CONTEXT))
+ return;
+
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+ Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+ if (principals == null || principals.isEmpty()) {
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ }
+ Principal principal = principals.iterator().next();
+ AccessControl accessControl = getAccessControl(principal, true);
+ if (context instanceof SetAttributesOperationContext) {
+ SetAttributesOperationContext setterContext = (SetAttributesOperationContext) context;
+ for (Entry<String, ResourceOperationContext> e : setterContext.getAttributesContextMap().entrySet()) {
+ //TODO : Retrieve proper values from AttributeList and set to its jmxContext
+ e.getValue().setPostOperationResult(result);
+ boolean authorized = accessControl.authorizeOperation(null, e.getValue());
+ if (!authorized)
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
+ }
+ } else {
+ boolean authorized = accessControl.authorizeOperation(null, context);
+ if (logger.isDebugEnabled()) {
+ logger.debug("postAuthorize: Name=" + name + " methodName=" + methodName + " result=" + authorized
+ + " principal=" + principal.getName());
+ }
+ if (!authorized)
+ throw new SecurityException(ACCESS_DENIED_MESSAGE);
}
- return sb.toString();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/Resource.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/Resource.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/Resource.java
index 4dc27e1..68b0468 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/Resource.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/Resource.java
@@ -1,10 +1,17 @@
package com.gemstone.gemfire.management.internal.security;
+/**
+ *
+ * @author tushark
+ *
+ * @since 9.0
+ */
public enum Resource {
DISTRIBUTED_SYSTEM,
MEMBER,
REGION,
DISKSTORE,
GATEWAY_SENDER,
- GATEWAT_LISTENER,
+ GATEWAY_RECEIVER,
}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceConstants.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceConstants.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceConstants.java
index 3f4d7cb..e26bc64 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceConstants.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceConstants.java
@@ -1,37 +1,32 @@
package com.gemstone.gemfire.management.internal.security;
+/**
+ *
+ * @author tushark
+ *
+ * @since 9.0
+ */
public class ResourceConstants {
-
- //public static final String LIST_DS = "LIST_DS";
- public static final String READ_DS = "READ_DS";
- public static final String SET_DS = "SET_DS";
- public static final String CHANGE_ALERT_LEVEL_DS = "CHANGE_ALERT_LEVEL_DS";
- public static final String BACKUP_DS = "BACKUP_DS";
- public static final String REMOVE_DISKSTORE_DS = "REMOVE_DISKSTORE_DS";
- public static final String SHUTDOWN_DS = "SHUTDOWN_DS";
- public static final String QUERYDATA_DS = "QUERYDATA_DS";
- public static final String ADMIN_DS = "ADMIN_DS";
-
- /*
- public static final String REBALANCE = "REBALANCE";
- public static final String PUT = "PUT";
- public static final String EXPORT_DATA = "EXPORT_DATA";
- public static final String IMPORT_DATA = "IMPORT_DATA";
- public static final String LOCATE_ENTRY = "LOCATE_ENTRY";*/
-
- public static final String PULSE_DASHBOARD = "PULSE_DASHBOARD";
- public static final String PULSE_DATABROWSER = "PULSE_DATABROWSER";
- public static final String PULSE_ADMIN_V1 = "PULSE_ADMIN_V1";
- public static final String PULSE_WEBGFSH = "PULSE_WEBGFSH";
-
- public static final String DEFAULT_LABEL="";
-
- public static final String RESORUCE_SEC_DESCRIPTOR = "resource.secDescriptor";
- public static final String RESORUCE_AUTH_ACCESSOR = "resource-auth-accessor";
- public static final String RESORUCE_AUTHENTICATOR = "resource-authenticator";
- public static final String RESORUCE_DEFAULT_SEC_DESCRIPTOR = "resourceSecDesc.json";
- //All ResourceOperation Codes
+ public static final String DEFAULT_LABEL="";
+
+ public static final String RESORUCE_SEC_DESCRIPTOR = "resource.secDescriptor";
+ public static final String RESORUCE_AUTH_ACCESSOR = "resource-auth-accessor";
+ public static final String RESORUCE_AUTHENTICATOR = "resource-authenticator";
+ public static final String RESORUCE_DEFAULT_SEC_DESCRIPTOR = "resourceSecDesc.json";
+ public static final String CREATE_MBEAN = "createMBean";
+ public static final String UNREGISTER_MBEAN = "unregisterMBean";
+ public static final String SET_PREFIX = "set";
+ public static final String SET_ATTRIBUTE = "setAttribute";
+ public static final String SET_ATTRIBUTES= "setAttributes";
+ public static final String GET_ATTRIBUTES= "getAttributes";
+ public static final String GET_ATTRIBUTE = "getAttribute";
+ public static final String GET_PREFIX = "get";
+ public static final String GET_IS_PREFIX = "is";
+ public static final String REGISTER_MBEAN = "registerMBean";
+ public static final String PROCESS_COMMAND ="processCommand";
+ public static final String ACCESS_DENIED_MESSAGE = "Access Denied";
+ public static final String WRONGE_CREDENTIALS_MESSAGE = "Wrong Credentials";
public static final String ALTER_REGION = "ALTER_REGION";
public static final String ALTER_RUNTIME = "ALTER_RUNTIME";
@@ -51,6 +46,7 @@ public class ResourceConstants {
public static final String DESTROY_DISKSTORE = "DESTROY_DISKSTORE";
public static final String DESTROY_FUNCTION = "DESTROY_FUNCTION";
public static final String DESTROY_INDEX = "DESTROY_INDEX";
+
public static final String DESTROY_REGION = "DESTROY_REGION";
public static final String EXECUTE_FUNCTION = "EXECUTE_FUNCTION";
public static final String EXPORT_CONFIG = "EXPORT_CONFIG";
@@ -86,6 +82,7 @@ public class ResourceConstants {
public static final String BACKUP_MEMBERS = "BACKUP_MEMBERS";
public static final String ROLL_DISKSTORE = "ROLL_DISKSTORE";
public static final String FORCE_COMPACTION = "FORCE_COMPACTION";
+ public static final String FORCE_ROLL = "FORCE_ROLL";
public static final String FLUSH_DISKSTORE = "FLUSH_DISKSTORE";
public static final String START_GW_RECEIVER = "START_GW_RECEIVER";
public static final String START_GW_SENDER = "START_GW_SENDER";
@@ -93,7 +90,55 @@ public class ResourceConstants {
public static final String START_MANAGER = "START_MANAGER";
public static final String STOP_MANAGER = "STOP_MANAGER";
public static final String CREATE_MANAGER = "CREATE_MANAGER";
+ public static final String STOP_CONTINUOUS_QUERY = "STOP_CONTINUOUS_QUERY";
+ public static final String SET_DISK_USAGE = "SET_DISK_USAGE";
+
+ public static final String CREATE_HDFS_STORE = "CREATE_HDFS_STORE";
+ public static final String ALTER_HDFS_STORE = "ALTER_HDFS_STORE";
+ public static final String DESTROY_HDFS_STORE = "DESTROY_HDFS_STORE";
+
+ public static final String PULSE_DASHBOARD = "PULSE_DASHBOARD";
+ public static final String PULSE_DATABROWSER = "PULSE_DATABROWSER";
+ public static final String PULSE_ADMIN_V1 = "PULSE_ADMIN_V1";
+ public static final String PULSE_WEBGFSH = "PULSE_WEBGFSH";
+
+ public static final String DATA_READ = "DATA_READ";
+ public static final String DATA_WRITE = "DATA_WRITE";
+ public static final String MONITOR = "MONITOR";
+ public static final String ADMIN = "ADMIN";
+
+ public static final String OBJECT_NAME_ACCESSCONTROL = "GemFire:service=AccessControl,type=Distributed";
+ public static final String USER_NAME = "security-username";
+ public static final String PASSWORD = "security-password";
+ public static final String MBEAN_TYPE_DISTRIBUTED = "Distributed";
+ public static final String MBEAN_TYPE_MEMBER = "Member";
+
+ public static final String MBEAN_SERVICE_MANAGER = "Manager";
+ public static final String MBEAN_SERVICE_CACHESERVER="CacheServer";
+ public static final String MBEAN_SERVICE_REGION = "Region";
+ public static final String MBEAN_SERVICE_LOCKSERVICE = "LockService";
+ public static final String MBEAN_SERVICE_DISKSTORE = "DiskStore";
+ public static final String MBEAN_SERVICE_GATEWAY_RECEIVER = "GatewayReceiver";
+ public static final String MBEAN_SERVICE_GATEWAY_SENDER = "GatewaySender";
+ public static final String MBEAN_SERVICE_ASYNCEVENTQUEUE = "AsyncEventQueue";
+ public static final String MBEAN_SERVICE_LOCATOR = "Locator";
+ public static final String MBEAN_SERVICE_SYSTEM = "System";
+
+ public static final String MBEAN_KEY_SERVICE ="service";
+ public static final String MBEAN_KEY_TYPE ="type";
+
+ public static final String GETTER_IS= "is";
+ public static final String GETTER_GET = "get";
+ public static final String GETTER_FETCH = "fetch";
+ public static final String GETTER_SHOW = "show";
+ public static final String GETTER_HAS = "has";
+ public static final String GETTER_VIEW = "view";
+ public static final String GETTER_LIST = "list";
+ public static final String GETTER_DESCRIBE = "describe";
+ public static final String GETTER_STATUS = "status";
+
+ public static final String MANAGEMENT_PACKAGE = "com.gemstone.gemfire.management";
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d511979e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceOperation.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceOperation.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceOperation.java
index f149479..48cbd94 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceOperation.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/security/ResourceOperation.java
@@ -6,6 +6,12 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * Annotation describing Security Level required to perform any resource operation
+ * @author tushark
+ *
+ * @since 9.0
+ */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited