geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tush...@apache.org
Subject [78/79] incubator-geode git commit: Integrated Security DUnitTest for data/monitor commands
Date Tue, 03 Nov 2015 11:26:40 GMT
  Integrated Security DUnitTest for data/monitor commands

  ReviewBoard URL : https://reviews.apache.org/r/39585/


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/3f931bab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/3f931bab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/3f931bab

Branch: refs/heads/feature/GEODE-17
Commit: 3f931babacccb41cf3e66592f41194fc98d8fd3b
Parents: 9525e69
Author: tushark <tushark@apache.org>
Authored: Fri Oct 23 14:58:37 2015 +0530
Committer: tushark <tushark@apache.org>
Committed: Tue Nov 3 16:54:35 2015 +0530

----------------------------------------------------------------------
 .../internal/security/CommandTestBase.java      | 601 +++++++++++++++++
 .../internal/security/HeadlessGfsh.java         | 315 +++++++++
 .../security/HeadlessGfshJUnitTest.java         |  68 ++
 .../security/IntegratedSecDUnitTest.java        | 661 +++++++++++++++++++
 .../security/MBeanSecurityJUnitTest.java        | 585 ++++++++++++++++
 .../internal/security/ResultHandler.java        |   7 +
 .../internal/security/TestAccessControl.java    | 130 ++++
 .../internal/security/TestAuthenticator.java    |  50 ++
 8 files changed, 2417 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f931bab/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/CommandTestBase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/CommandTestBase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/CommandTestBase.java
new file mode 100644
index 0000000..a95e605
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/CommandTestBase.java
@@ -0,0 +1,601 @@
+package com.gemstone.gemfire.management.internal.security;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import util.TestException;
+//import util.TestHelper;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache30.CacheTestCase;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.management.ManagementService;
+import com.gemstone.gemfire.management.internal.cli.CommandManager;
+import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+import com.gemstone.gemfire.management.internal.cli.parser.CommandTarget;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResult;
+import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
+import com.gemstone.gemfire.management.internal.cli.util.CommandStringBuilder;
+
+import dunit.Host;
+import dunit.SerializableCallable;
+import dunit.SerializableRunnable;
+
+/**
+ * Base class for all the CLI/gfsh command dunit tests. Derived from CliCommandTestBase but not using
+ * TestableGfsh but HeadlessGfsh
+ * 
+ * @author Tushar Khairnar
+ */
+public class CommandTestBase extends CacheTestCase {
+  
+  private static final long serialVersionUID = 1L;
+
+  protected static final String USE_HTTP_SYSTEM_PROPERTY = "useHTTP";
+
+  private ManagementService managementService;
+  
+  private transient HeadlessGfsh shell;
+
+  private boolean useHttpOnConnect = Boolean.getBoolean("useHTTP");
+
+  private int httpPort;
+  private int jmxPort;
+
+  private String jmxHost;
+  
+  protected String securityFile = null;
+  protected String userName = null;
+  protected String password = null;
+  protected String commandError = null;
+  
+  public CommandTestBase(String name) {
+    super(name);
+  }
+
+  public void setUp() throws Exception {
+    super.setUp();
+  }
+
+  @Override
+  public void tearDown2() throws Exception {
+    destroyDefaultSetup();
+    super.tearDown2();
+  }
+  
+  protected void setUseHttpOnConnect(boolean useHttpOnConnect){
+    this.useHttpOnConnect = useHttpOnConnect;
+  }
+  
+  /**
+   * Create all of the components necessary for the default setup. The provided properties will be used when creating
+   * the default cache. This will create GFSH in the controller VM (VM[4]) (no cache) and the manager in VM[0] (with
+   * cache). When adding regions, functions, keys, whatever to your cache for tests, you'll need to use
+   * Host.getHost(0).getVM(0).invoke(new SerializableRunnable() { public void run() { ... } } in order to have this
+   * setup run in the same VM as the manager.
+   * <p/>
+   * @param props the Properties used when creating the cache for this default setup.
+   * @return the default testable GemFire shell.
+   */
+  @SuppressWarnings("serial")
+  protected final HeadlessGfsh createDefaultSetup(final Properties props) {
+    Object[] result = (Object[]) Host.getHost(0).getVM(0).invoke(new SerializableCallable() {
+      public Object call() {
+        final Object[] result = new Object[3];
+        final Properties localProps = (props != null ? props : new Properties());
+
+        try {
+          jmxHost = InetAddress.getLocalHost().getHostName();
+        }
+        catch (UnknownHostException ignore) {
+          jmxHost = "localhost";
+        }
+
+        if (!localProps.containsKey(DistributionConfig.NAME_NAME)) {
+          localProps.setProperty(DistributionConfig.NAME_NAME, "Manager");
+        }
+
+        final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+
+        jmxPort = ports[0];
+        httpPort = ports[1];
+
+        localProps.setProperty(DistributionConfig.JMX_MANAGER_NAME, "true");
+        localProps.setProperty(DistributionConfig.JMX_MANAGER_START_NAME, "true");
+        localProps.setProperty(DistributionConfig.JMX_MANAGER_BIND_ADDRESS_NAME, String.valueOf(jmxHost));
+        localProps.setProperty(DistributionConfig.JMX_MANAGER_PORT_NAME, String.valueOf(jmxPort));
+        localProps.setProperty(DistributionConfig.HTTP_SERVICE_PORT_NAME, String.valueOf(httpPort));
+
+        getSystem(localProps);
+        verifyManagementServiceStarted(getCache());
+
+        result[0] = jmxHost;
+        result[1] = jmxPort;
+        result[2] = httpPort;
+
+        return result;
+      }
+    });
+
+    this.jmxHost = (String) result[0];
+    this.jmxPort = (Integer) result[1];
+    this.httpPort = (Integer) result[2];
+
+    return defaultShellConnect();
+  }
+  
+  protected boolean useHTTPByTest(){
+    return false;
+  }
+
+  /**
+   * Destroy all of the components created for the default setup.
+   */
+  @SuppressWarnings("serial")
+  protected final void destroyDefaultSetup() {
+    if (this.shell != null) {
+      // Note: HeadlessGfsh doesn't use Launcher & code that does System.exit()
+      // for gfsh is in Launcher. This is just to ensure cleanup.
+      executeCommand(shell, "exit");
+      if(shell.isConnectedAndReady()){
+        executeCommand(shell, "disconnect");
+      }
+
+      this.shell.terminate();
+      this.shell = null;
+    }
+
+    disconnectAllFromDS();
+
+    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
+      public void run() {
+        verifyManagementServiceStopped();
+        //if (Boolean.getBoolean(USE_HTTP_SYSTEM_PROPERTY)) {
+        //  System.gc();
+        //}
+      }
+    });
+  }
+
+  /**
+   * Start the default management service using the provided Cache.
+   * 
+   * @param cache
+   *          Cache to use when creating the management service
+   */
+  private void verifyManagementServiceStarted(Cache cache) {
+    assert(cache != null);
+
+    this.managementService = ManagementService.getExistingManagementService(cache);
+    assertNotNull(this.managementService);
+    assertTrue(this.managementService.isManager());
+    assertTrue(checkIfCommandsAreLoadedOrNot());
+  }
+  
+  public static boolean checkIfCommandsAreLoadedOrNot(){          
+    CommandManager manager;
+    try {
+      manager = CommandManager.getInstance();
+      Map<String,CommandTarget> commands = manager.getCommands();
+      Set set = commands.keySet();
+      if(commands.size() < 1 ){
+        return false;
+      }
+      return true;
+    } catch (ClassNotFoundException | IOException e) {
+      throw new RuntimeException("Could not load commands", e);
+    }                
+}
+
+  /**
+   * Stop the default management service.
+   */
+  private void verifyManagementServiceStopped() {
+    if (this.managementService != null) {
+      assertFalse(this.managementService.isManager());
+      this.managementService = null;
+    }
+  }
+
+  /**
+   * Connect the default shell to the default JMX server.
+   * 
+   * @return The default shell.
+   */
+  protected HeadlessGfsh defaultShellConnect() {
+    HeadlessGfsh shell = getDefaultShell();
+    shellConnect(this.jmxHost, this.jmxPort, this.httpPort, shell);
+    return shell;
+  }
+
+  /**
+   * Connect a shell to the JMX server at the given host and port
+   * 
+   * @param host
+   *          Host of the JMX server
+   * @param jmxPort
+   *          Port of the JMX server
+   * @param shell
+   *          Shell to connect
+   */
+  protected void shellConnect(final String host, final int jmxPort, final int httpPort, HeadlessGfsh shell) {
+    assert(host != null);
+    assert(shell != null);
+
+    final CommandStringBuilder command = new CommandStringBuilder(CliStrings.CONNECT);
+    String endpoint;
+
+    if (useHttpOnConnect) {
+      endpoint = "http://" + host + ":" + httpPort + "/gemfire/v1";
+      command.addOption(CliStrings.CONNECT__USE_HTTP, Boolean.TRUE.toString());
+      command.addOption(CliStrings.CONNECT__URL, endpoint);
+     
+    }
+    else {
+      endpoint = host + "[" + jmxPort + "]";
+      command.addOption(CliStrings.CONNECT__JMX_MANAGER, endpoint);
+    }
+
+    if(this.securityFile != null){
+      command.addOption(CliStrings.CONNECT__SECURITY_PROPERTIES, securityFile);
+    }
+    
+    if(this.userName!=null) {
+      command.addOption(CliStrings.CONNECT__USERNAME, userName);
+    }
+    
+    if(this.password!=null) {
+      command.addOption(CliStrings.CONNECT__PASSWORD, password);
+    }
+
+    CommandResult result = executeCommand(shell, command.toString());
+
+    if (!shell.isConnectedAndReady()) {
+      throw new TestException("Connect command failed to connect to manager " + endpoint + " result=" + commandResultToString(result));
+    }
+
+    info("Successfully connected to managing node using " + (useHttpOnConnect ? "HTTP" : "JMX"));
+    assertEquals(true, shell.isConnectedAndReady());
+  }
+
+  /**
+   * Get the default shell (will create one if it doesn't already exist).
+   * 
+   * @return The default shell
+   */
+  protected synchronized final HeadlessGfsh getDefaultShell() {
+    if (this.shell == null) {
+      this.shell = createShell();
+    }
+
+    return this.shell;
+  }
+
+  /**
+   * Create a TestableGfsh object.
+   * 
+   * @return The created shell.
+   */
+  protected HeadlessGfsh createShell() {
+    try {
+      Gfsh.SUPPORT_MUTLIPLESHELL = true;
+      String shellId = getClass().getSimpleName()+"_"+getName();
+      HeadlessGfsh shell = new HeadlessGfsh(shellId, 300);
+      //Various command use ThreadLocal instance. following call makes
+      //HeadlessGfsh available to all the commands
+      shell.setThreadLocalInstance();
+      //Added to avoid trimming of the columns
+      //shell.setEnvProperty(Gfsh.ENV_APP_RESULT_VIEWER, "non-basic");
+      //shell.start();
+      info("Started headless shell: " + shell);
+      return shell;
+    } catch (ClassNotFoundException e) {
+      throw new TestException(getStackTrace(e));
+    } catch (IOException e) {
+      throw new TestException(getStackTrace(e));
+    }
+  }
+
+  /**
+   * Execute a command using the default shell and clear the shell events before returning.
+   * 
+   * @param command
+   *          Command to execute
+   * @return The result of the command execution
+   */
+  protected CommandResult executeCommand(String command) {
+    assert(command != null);
+
+    return executeCommand(getDefaultShell(), command);
+  }
+
+  /**
+   * Execute a command in the provided shell and clear the shell events before returning.
+   * 
+   * @param shell
+   *          Shell in which to execute the command.
+   * @param command
+   *          Command to execute
+   * @return The result of the command execution
+   */
+  protected CommandResult executeCommand(HeadlessGfsh shell, String command) {
+    assert(shell != null);
+    assert(command != null);
+    CommandResult commandResult = executeCommandWithoutClear(shell, command);
+    shell.clear();
+    return commandResult;
+  }
+
+  /**
+   * Execute a command using the default shell. Useful for getting additional information from the shell after the
+   * command has been executed (using getDefaultShell().???). Caller is responsible for calling
+   * getDefaultShell().clearEvents() when done.
+   * 
+   * @param command
+   *          Command to execute
+   * @return The result of the command execution
+   */
+  @SuppressWarnings("unused")
+  protected CommandResult executeCommandWithoutClear(String command) {
+    assert(command != null);
+
+    return executeCommandWithoutClear(getDefaultShell(), command);
+  }
+
+  /**
+   * Execute a command in the provided shell. Useful for getting additional information from the shell after the command
+   * has been executed (using getDefaultShell().???). Caller is responsible for calling getDefaultShell().clearEvents()
+   * when done.
+   * 
+   * @param shell
+   *          Shell in which to execute the command.
+   * @param command
+   *          Command to execute
+   * @return The result of the command execution
+   */
+  protected CommandResult executeCommandWithoutClear(HeadlessGfsh shell, String command) {
+    assert(shell != null);
+    assert(command != null);
+
+    try {
+      info("Executing command " + command + " with command Mgr " + CommandManager.getInstance());
+    } catch (ClassNotFoundException cnfex) {
+      throw new TestException(getStackTrace(cnfex));
+    } catch (IOException ioex) {
+      throw new TestException(getStackTrace(ioex));
+    }
+    
+    Object result =null;
+    
+    try {
+      
+      boolean status = shell.executeCommand(command);
+      result = shell.getResult();
+      
+      info("CommandExecutionSuccess=" + status );
+      info("Status=" + shell.getCommandExecutionStatus());
+      info("ShellOutputString=<" + shell.outputString + ">");
+      info("ErrorString=<" + shell.getErrorString() + ">");
+      
+      if (shell.hasError() || shell.getCommandExecutionStatus() == -1) {
+        error("executeCommand completed with error : " + shell.getErrorString() + " output=<" + shell.outputString
+            + ">");
+      }
+      
+      if(result == null || result.equals(HeadlessGfsh.ERROR_RESULT))
+          return null;
+      
+    } catch (InterruptedException e) {
+      throw new TestException(getStackTrace(e));
+    }
+    
+    return (CommandResult)result;     
+  }
+
+  /**
+   * Utility method for viewing the results of a command.
+   * 
+   * @param commandResult
+   *          Results to dump
+   * @param printStream
+   *          Stream to dump the results to
+   */
+  protected void printResult(final CommandResult commandResult, PrintStream printStream) {
+    assert(commandResult != null);
+    assert(printStream != null);
+    commandResult.resetToFirstLine();
+    printStream.print(commandResultToString(commandResult));
+  }
+
+  protected String commandResultToString(final CommandResult commandResult) {
+    assertNotNull(commandResult);
+    commandResult.resetToFirstLine();
+    StringBuilder buffer = new StringBuilder(commandResult.getHeader());
+    while (commandResult.hasNextLine()) {
+      buffer.append(commandResult.nextLine());
+    }
+    buffer.append(commandResult.getFooter());
+    return buffer.toString();
+  }
+
+  /**
+   * Utility method for finding the CommandResult object in the Map of CommandOutput objects.
+   * 
+   * @param commandOutput
+   *          CommandOutput Map to search
+   * @return The CommandResult object or null if not found.
+   */
+  protected CommandResult extractCommandResult(Map<String, Object> commandOutput) {
+    assert(commandOutput != null);
+
+    for (Object resultObject : commandOutput.values()) {
+      if (resultObject instanceof CommandResult) {
+        CommandResult result = (CommandResult) resultObject;
+        result.resetToFirstLine();
+        return result;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Utility method to determine how many times a string occurs in another string. Note that when looking for matches
+   * substrings of other matches will be counted as a match. For example, looking for "AA" in the string "AAAA" will
+   * result in a return value of 3.
+   * 
+   * @param stringToSearch
+   *          String to search
+   * @param stringToCount
+   *          String to look for and count
+   * @return The number of matches.
+   */
+  protected int countMatchesInString(final String stringToSearch, final String stringToCount) {
+    assert(stringToSearch != null);
+    assert(stringToCount != null);
+    
+    int length = stringToSearch.length();
+    int count = 0;
+    for (int i = 0; i < length; i++) {
+      if (stringToSearch.substring(i).startsWith(stringToCount)) {
+        count++;
+      }
+    }
+    return count;
+  }
+
+  /**
+   * Determines if a string contains a trimmed line that matches the pattern. So, any single line whose leading and
+   * trailing spaces have been removed which contains a string that exactly matches the given pattern will be considered
+   * a match.
+   * 
+   * @param stringToSearch
+   *          String to search
+   * @param stringPattern
+   *          Pattern to search for
+   * @return True if a match is found, false otherwise
+   */
+  protected boolean stringContainsLine(final String stringToSearch, final String stringPattern) {
+    assert(stringToSearch != null);
+    assert(stringPattern != null);
+    
+    Pattern pattern = Pattern.compile("^\\s*" + stringPattern + "\\s*$", Pattern.MULTILINE);
+    Matcher matcher = pattern.matcher(stringToSearch);
+    return matcher.find();
+  }
+
+  /**
+   * Counts the number of distinct lines in a String.
+   * 
+   * @param stringToSearch
+   *          String to search for lines.
+   * @param countBlankLines
+   *          Whether to count blank lines (true to count)
+   * @return The number of lines found.
+   */
+  protected int countLinesInString(final String stringToSearch, final boolean countBlankLines) {
+    assert(stringToSearch != null);
+    
+    int length = stringToSearch.length();
+    int count = 0;
+    char character = 0;
+    boolean foundNonSpaceChar = false;
+
+    for (int i = 0; i < length; i++) {
+      character = stringToSearch.charAt(i);
+      if (character == '\n' || character == '\r') {
+        if (countBlankLines) {
+          count++;
+        } else {
+          if (foundNonSpaceChar) {
+            count++;
+          }
+        }
+        foundNonSpaceChar = false;
+      } else if (character != ' ' && character != '\t') {
+        foundNonSpaceChar = true;
+      }
+    }
+
+    // Even if the last line isn't terminated, it still counts as a line
+    if (character != '\n' && character != '\r') {
+      count++;
+    }
+
+    return count;
+  }
+
+  /** 
+   * Get a specific line from the string (using \n or \r as a line separator).
+   * 
+   * @param stringToSearch String to get the line from
+   * @param lineNumber Line number to get
+   * @return The line
+   */
+  protected String getLineFromString(final String stringToSearch, final int lineNumber) {
+    assert(stringToSearch != null);
+    assert(lineNumber > 0);
+    
+    int length = stringToSearch.length();
+    int count = 0;
+    int startIndex = 0;
+    char character;
+    int endIndex = length;
+
+    for (int i = 0; i < length; i++) {
+      character = stringToSearch.charAt(i);
+      if (character == '\n' || character == '\r') {
+        if (lineNumber == 1) {
+          endIndex = i;
+          break;
+        }
+        if (++count == lineNumber-1) {
+          startIndex = i+1;
+        } else if (count >= lineNumber) {
+          endIndex = i;
+          break;
+        }
+      }
+    }
+
+    return stringToSearch.substring(startIndex, endIndex);
+  }
+  
+  protected void info(String string) {
+    getLogWriter().info(string);
+  }
+
+  protected void debug(String string) {
+    getLogWriter().fine(string);
+  }
+
+  protected void error(String string) {
+    commandError = string;
+    getLogWriter().error(string);
+  }
+
+  protected void error(String string, Throwable e) {
+    commandError = string;
+    getLogWriter().error(string, e);
+  }
+  
+  protected Object[] getJMXEndPoint(){
+    return new Object[] {jmxHost, jmxPort };
+  }
+  
+  public static String getStackTrace(Throwable aThrowable) {
+    StringWriter sw = new StringWriter();
+    aThrowable.printStackTrace(new PrintWriter(sw, true));
+    return sw.toString();
+ }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f931bab/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfsh.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfsh.java b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfsh.java
new file mode 100644
index 0000000..d73a260
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfsh.java
@@ -0,0 +1,315 @@
+package com.gemstone.gemfire.management.internal.security;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+
+import jline.ConsoleReader;
+
+import org.springframework.shell.core.ExitShellRequest;
+import org.springframework.shell.event.ShellStatus.Status;
+
+import com.gemstone.gemfire.management.internal.cli.CliUtil;
+import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
+import com.gemstone.gemfire.management.internal.cli.shell.GfshConfig;
+import com.gemstone.gemfire.management.internal.cli.shell.jline.GfshUnsupportedTerminal;
+
+
+/**
+ * This is headless shell which can be used to submit random commands and get command-result 
+ * It is used for commands testing but can be used as for anything like programmatically
+ * sending commands to operate on GemFire Distributed systems.
+ * TODO : Merge HeadlessGfsh and HeadlessGfshShell
+ * TODO : Provide constructor for optionally specifying GfshConfig to provide logDirectory and logLevel
+ *  
+ * @author tushark
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class HeadlessGfsh  implements ResultHandler {
+  
+  public static final String ERROR_RESULT = "_$_ERROR_RESULT";
+
+  private HeadlessGfshShell shell = null;  
+  private LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
+  private long timeout = 20;
+  public String outputString=null;
+  
+  public HeadlessGfsh(String name, int timeout) throws ClassNotFoundException, IOException {
+    this.timeout = timeout;
+    System.setProperty("jline.terminal", GfshUnsupportedTerminal.class.getName());    
+    this.shell = new HeadlessGfshShell(name, this);
+    this.shell.start();
+  }
+  
+  public void setThreadLocalInstance(){
+    shell.setThreadLocalInstance();
+  }
+  
+  //TODO : Have non-blocking method also where we move executeCommand call to separate thread-pool
+  public boolean executeCommand(String command) {
+    boolean status = false;
+    try {
+      outputString = null;
+      status = shell.executeCommand(command);
+    } catch (Exception e) {
+      outputString = e.getMessage();
+    }
+    return status;
+  }
+  
+  int getCommandExecutionStatus(){
+    return shell.getCommandExecutionStatus();
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Override
+  public void handleExecutionResult(Object result, String sysout) {    
+    queue.add(result);
+    outputString = sysout;
+  }
+  
+  public Object getResult() throws InterruptedException {
+    Object result = queue.poll(timeout, TimeUnit.SECONDS);
+    queue.clear();
+    return result;
+  }
+  
+  public void clear(){
+    queue.clear();
+    outputString = null;
+  }
+  
+  public void terminate() {    
+    shell.terminate();
+  }
+  
+  public boolean isConnectedAndReady() {
+    return shell.isConnectedAndReady();
+  }
+  
+  public String getErrorString() {
+    return shell.errorString;
+  }
+
+  public boolean hasError() {
+    return shell.hasError();
+  }   
+  
+  public static class HeadlessGfshShell extends Gfsh {
+
+    private ResultHandler handler = null;
+    private final Lock lock = new ReentrantLock();
+    private final Condition endOfShell = lock.newCondition();
+    private ByteArrayOutputStream output = null;
+    private String errorString = null;
+    private boolean hasError = false;
+
+    protected HeadlessGfshShell(String testName, ResultHandler handler) throws ClassNotFoundException, IOException {
+      super(false, new String[] {}, new HeadlessGfshConfig(testName));
+      this.handler = handler;
+    }
+
+    public void setThreadLocalInstance() {
+      gfshThreadLocal.set(this);      
+    }
+
+    protected void handleExecutionResult(Object result) {
+      if(!result.equals(ERROR_RESULT)) {
+        super.handleExecutionResult(result);
+        handler.handleExecutionResult(result, output.toString());
+        output.reset();
+      } else {
+        //signal waiting queue with error condition with empty output
+        output.reset();
+        handler.handleExecutionResult(result, output.toString());        
+      }
+    }      
+
+    int getCommandExecutionStatus() {
+      return getLastExecutionStatus();
+    }
+
+    public void terminate() {
+      closeShell();
+      stopPromptLoop();
+      stop();
+    }
+    
+    private void stopPromptLoop() {
+      lock.lock();
+      try {
+        endOfShell.signalAll();
+      } finally {
+        lock.unlock();
+      }      
+    }
+    
+    public String getErrorString() {
+      return errorString;
+    }
+
+    public boolean hasError() {
+      return hasError;
+    }
+
+    /**
+     * We override this method just to fool runner thread in reading from nothing. It waits for Condition endOfShell
+     * which is signalled when terminate is called. This achieves clean shutdown of runner thread. 
+     */
+    @Override
+    public void promptLoop() {
+      lock.lock();
+      try {
+        while (true) {
+          try {
+            endOfShell.await();
+          } catch (InterruptedException e) {
+            //e.printStackTrace();
+          }
+          this.exitShellRequest = ExitShellRequest.NORMAL_EXIT;
+          setShellStatus(Status.SHUTTING_DOWN);
+          break;
+        }
+      } finally {
+        lock.unlock();
+      }
+    }
+
+    private static void setGfshOutErr(PrintStream outToUse) {
+      Gfsh.gfshout = outToUse;
+      Gfsh.gfsherr = outToUse;
+    }
+    
+    /**
+     * This prints out error messages when Exceptions occur in shell. Capture it
+     * and set error flag=true and send ERROR_RESULT on the queue to signal thread
+     * waiting for CommandResult
+     */
+    @Override
+    public void logWarning(String message, Throwable t) {
+      super.logWarning(message, t);
+      errorString = message;
+      hasError = true;
+      //signal waiting queue with error condition
+      handleExecutionResult(ERROR_RESULT);
+    }
+
+    /**
+     * This prints out error messages when Exceptions occur in shell. Capture it
+     * and set error flag=true and send ERROR_RESULT on the queue to signal thread
+     * waiting for CommandResult
+     */
+    @Override
+    public void logSevere(String message, Throwable t) {
+      super.logSevere(message, t);
+      errorString = message;
+      hasError = true;
+      //signal waiting queue with error condition
+      handleExecutionResult(ERROR_RESULT);
+    }
+    
+    /**
+     * Setup console-reader to capture Shell output
+     */
+    @Override
+    protected ConsoleReader createConsoleReader() {
+      try {        
+        output = new ByteArrayOutputStream(1024 * 10);
+        PrintStream sysout = new PrintStream(output);
+        Writer wrappedOut = new BufferedWriter(new OutputStreamWriter(sysout));
+        setGfshOutErr(sysout);
+        return new ConsoleReader(new FileInputStream(FileDescriptor.in),new PrintWriter(wrappedOut));
+      } catch (IOException e) {        
+        throw new RuntimeException(e);
+      }
+    }
+  }
+  
+  
+  /**
+   * HeadlessGfshConfig for tests. Taken from TestableGfsh
+   */
+  static class HeadlessGfshConfig extends GfshConfig {
+    {
+      // set vm as a gfsh vm
+      CliUtil.isGfshVM = true;
+    }
+
+    private File   parentDir;
+    private String fileNamePrefix;
+    private String name;
+    private String generatedHistoryFileName = null;
+
+    public HeadlessGfshConfig(String name) {
+      this.name = name;
+
+      if (isDUnitTest(this.name)) {
+        fileNamePrefix = this.name;
+      } else {        
+        fileNamePrefix = "non-hydra-client";
+      }
+
+      parentDir = new File("gfsh_files");
+      parentDir.mkdirs();
+    }
+
+    private static boolean isDUnitTest(String name) {
+      boolean isDUnitTest = false;
+      if (name != null) {
+        String[] split = name.split("_");
+        if (split.length != 0 && split[0].endsWith("DUnitTest")) {
+          isDUnitTest = true;
+        }
+      }
+      return isDUnitTest;
+    }
+
+    @Override
+    public String getLogFilePath() {
+      return new File(parentDir, getFileNamePrefix() + "-gfsh.log").getAbsolutePath();
+    }
+
+    private String getFileNamePrefix() {
+      String timeStamp = new java.sql.Time(System.currentTimeMillis()).toString();
+      timeStamp = timeStamp.replace(':', '_');
+      return fileNamePrefix + "-" + timeStamp;
+    }
+
+    @Override
+    public String getHistoryFileName() {
+      if(generatedHistoryFileName == null) {
+        String fileName = new File(parentDir, (getFileNamePrefix() +"-gfsh.history")).getAbsolutePath();
+        generatedHistoryFileName = fileName;
+        return fileName;
+      } else {
+        return generatedHistoryFileName;
+      }
+    }
+
+    @Override
+    public boolean isTestConfig() {
+      return true;
+    }
+
+    @Override
+    public Level getLogLevel() {
+      // Keep log level fine for tests
+      return Level.FINE;
+    }
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f931bab/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfshJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfshJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfshJUnitTest.java
new file mode 100644
index 0000000..a5abc33
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/HeadlessGfshJUnitTest.java
@@ -0,0 +1,68 @@
+package com.gemstone.gemfire.management.internal.security;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.management.ObjectName;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.AvailablePort;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.management.internal.MBeanJMXAdapter;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+
+/**
+ * TODO : Add more tests for error-catch, different type of results etc
+ * 
+ * @author tushark
+ *
+ */
+@Category(UnitTest.class)
+public class HeadlessGfshJUnitTest {
+
+  @SuppressWarnings({ "unused", "deprecation", "unused" })
+  @Test
+  public void testHeadlessGfshTest() throws ClassNotFoundException, IOException, InterruptedException {    
+    GemFireCacheImpl cache = null;
+    DistributedSystem ds = null;
+    Properties pr = new Properties();
+    pr.put("name", "testHeadlessGfshTest");
+    pr.put(DistributionConfig.JMX_MANAGER_NAME, "true");
+    pr.put(DistributionConfig.JMX_MANAGER_START_NAME, "true");
+    int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
+    pr.put(DistributionConfig.JMX_MANAGER_PORT_NAME, String.valueOf(port));
+    pr.put(DistributionConfig.HTTP_SERVICE_PORT_NAME, "0");
+    pr.put(DistributionConfig.MCAST_PORT_NAME,"0");
+    
+    ds = DistributedSystem.connect(pr);
+    cache = (GemFireCacheImpl) CacheFactory.create(ds);
+    ObjectName name = MBeanJMXAdapter.getDistributedSystemName();
+    
+    HeadlessGfsh gfsh = new HeadlessGfsh("Test",20);
+    for(int i=0;i<5;i++) {
+      gfsh.executeCommand("connect --jmx-manager=localhost["+port+"]");
+      Object result = gfsh.getResult();
+      assertTrue(gfsh.isConnectedAndReady());
+      assertNotNull(result);
+      gfsh.clear();
+      gfsh.executeCommand("list members");
+      result = gfsh.getResult();
+      assertNotNull(result);
+      gfsh.executeCommand("disconnect");
+      gfsh.getResult();
+    }
+    gfsh.terminate();    
+    cache.close();
+    ds.disconnect();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f931bab/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/IntegratedSecDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/IntegratedSecDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/IntegratedSecDUnitTest.java
new file mode 100644
index 0000000..8258e49
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/security/IntegratedSecDUnitTest.java
@@ -0,0 +1,661 @@
+package com.gemstone.gemfire.management.internal.security;
+
+import hydra.Log;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionFactory;
+import com.gemstone.gemfire.cache.RegionService;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.client.ClientCacheFactory;
+import com.gemstone.gemfire.cache.client.ClientRegionFactory;
+import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
+import com.gemstone.gemfire.cache.operations.OperationContext.OperationCode;
+import com.gemstone.gemfire.cache.server.CacheServer;
+import com.gemstone.gemfire.distributed.DistributedMember;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.management.internal.MBeanJMXAdapter;
+import com.gemstone.gemfire.management.internal.cli.domain.DataCommandRequest;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResult;
+import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData;
+import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData.SectionResultData;
+import com.gemstone.gemfire.management.internal.cli.result.ErrorResultData;
+import com.gemstone.gemfire.management.internal.cli.result.ResultData;
+import com.gemstone.gemfire.management.internal.security.ResourceOperationContext.ResourceOperationCode;
+import com.gemstone.gemfire.security.AuthInitialize;
+import com.gemstone.gemfire.security.AuthenticationFailedException;
+
+import dunit.Host;
+import dunit.SerializableRunnable;
+import dunit.VM;
+
+/**
+ * @author tushark
+ * 
+ */
+public class IntegratedSecDUnitTest extends CommandTestBase {
+
+  public static class AuthInitializer implements AuthInitialize {
+
+    public static AuthInitialize create() {
+      return new AuthInitializer();
+    }
+
+    public void init(LogWriter systemLogger, LogWriter securityLogger) throws AuthenticationFailedException {
+    }
+
+    public Properties getCredentials(Properties p, DistributedMember server, boolean isPeer)
+        throws AuthenticationFailedException {
+      return p;
+    }
+
+    public void close() {
+    }
+  }
+
+  private static final long serialVersionUID = 1L;
+  private static IntegratedSecDUnitTest instance = new IntegratedSecDUnitTest("IntegratedSecDUnitTest");
+
+  private Cache cache;
+  private DistributedSystem ds;
+  private CacheServer cacheServer;
+  private ClientCache clientCache;
+  private int cacheServerPort;
+  private String hostName;
+
+  public IntegratedSecDUnitTest(String name) {
+    super(name);
+  }
+
+  public Cache createCache(Properties props) throws Exception {
+    ds = getSystem(props);
+    cache = CacheFactory.create(ds);
+    if (cache == null) {
+      throw new Exception("CacheFactory.create() returned null ");
+    }
+    return cache;
+  }
+
+  private void createServer() throws IOException {
+    cacheServerPort = AvailablePortHelper.getRandomAvailableTCPPort();
+    cacheServer = cache.addCacheServer();
+    cacheServer.setPort(cacheServerPort);
+    cacheServer.start();
+    hostName = cacheServer.getHostnameForClients();
+  }
+
+  public int getCacheServerPort() {
+    return cacheServerPort;
+  }
+
+  public String getCacheServerHost() {
+    return hostName;
+  }
+
+  public void stopCacheServer() {
+    this.cacheServer.stop();
+  }
+
+  @SuppressWarnings("rawtypes")
+  public void setUpServerVM(Properties gemFireProps) throws Exception {
+    Log.getLogWriter().info("Creating server vm cache with props =" + gemFireProps);
+    gemFireProps.setProperty(DistributionConfig.NAME_NAME, testName + "Server");
+    createCache(gemFireProps);
+    RegionFactory factory = cache.createRegionFactory(RegionShortcut.REPLICATE);
+    Region r = factory.create("serverRegion");
+    assertNotNull(r);
+    r.put("serverkey", "servervalue");
+    assertEquals(1,r.size());
+    Log.getLogWriter().info("Created serverRegion with 1 key=serverKey");
+  }
+
+  public void setUpClientVM(Properties gemFireProps, String host, int port, String user, String password) {
+    gemFireProps.setProperty(DistributionConfig.NAME_NAME, testName + "Client");
+    //gemFireProps.setProperty("security-username", user);
+    //gemFireProps.setProperty("security-password", password);
+    gemFireProps.setProperty("security-client-auth-init",
+        "com.gemstone.gemfire.management.internal.security.IntegratedSecDUnitTest$AuthInitializer.create");
+    Log.getLogWriter().info("Creating client cache with props =" + gemFireProps);
+    ClientCacheFactory clientCacheFactory = new ClientCacheFactory(gemFireProps);
+    clientCacheFactory.addPoolServer(host, port);
+    clientCacheFactory.setPoolMultiuserAuthentication(true);
+    clientCache = clientCacheFactory.create();
+    ClientRegionFactory<String, String> regionFactory = clientCache
+        .createClientRegionFactory(ClientRegionShortcut.PROXY);
+           
+    Region<String, String> region = regionFactory.create("serverRegion");
+    assertNotNull(region);    
+    
+    Properties properties = new Properties();
+    properties.setProperty("security-username", user);
+    properties.setProperty("security-password", password);
+    RegionService regionService = instance.clientCache.createAuthenticatedView(properties);
+    Region secRegion = regionService.getRegion("serverRegion");
+    assertNotNull(secRegion.get("serverkey"));
+  }
+
+  public static void setUpServerVMTask(Properties props) throws Exception {
+    instance.setUpServerVM(props);
+  }
+
+  public static void createServerTask() throws Exception {
+    instance.createServer();
+  }
+
+  public static void setUpClientVMTask(Properties gemFireProps, String host, int port, String user, String password)
+      throws Exception {
+    instance.setUpClientVM(gemFireProps, host, port, user, password);
+  }
+
+  public static Object[] getCacheServerEndPointTask() {
+    Object[] array = new Object[2];
+    array[0] = instance.getCacheServerHost();
+    array[1] = instance.getCacheServerPort();
+    return array;
+  }
+
+  public static void closeCacheTask() {
+    instance.cache.close();
+  }
+
+  public static void closeClientCacheTask() {
+    instance.clientCache.close();
+  }
+
+  /**
+   * 
+   * VM0 -> Manager
+   * VM1 -> Server
+   * Vm2 -> CacheClient
+   * 
+   * @param testName
+   * @throws IOException
+   */
+
+  @SuppressWarnings("serial")
+  void setup(String testName) throws IOException {
+
+    configureIntSecDescriptor();
+
+    Properties props = new Properties();
+
+    props.put(DistributionConfig.SECURITY_CLIENT_AUTHENTICATOR_NAME,
+        "com.gemstone.gemfire.management.internal.security.TestAuthenticator.create");
+    props.put(DistributionConfig.SECURITY_CLIENT_ACCESSOR_NAME,
+        "com.gemstone.gemfire.management.internal.security.TestAccessControl.create");
+    props.put(DistributionConfig.SECURITY_CLIENT_ACCESSOR_PP_NAME,
+        "com.gemstone.gemfire.management.internal.security.TestAccessControl.create");
+    props.setProperty(DistributionConfig.NAME_NAME, "Manager");
+    HeadlessGfsh gfsh = createDefaultSetup(props);
+    assertNotNull(gfsh);
+    assertEquals(true, gfsh.isConnectedAndReady());
+
+    props.list(System.out);
+
+    final Host host = Host.getHost(0);
+    VM serverVM = host.getVM(1);
+    VM clientVM = host.getVM(2);
+    serverVM.invoke(IntegratedSecDUnitTest.class, "setUpServerVMTask", new Object[] { props });
+    serverVM.invoke(IntegratedSecDUnitTest.class, "createServerTask");
+
+    Object array[] = (Object[]) serverVM.invoke(IntegratedSecDUnitTest.class, "getCacheServerEndPointTask");
+    String hostName = (String) array[0];
+    int port = (Integer) array[1];
+    Object params[] = new Object[] { props, hostName, port, "tushark", "password123" };
+    Log.getLogWriter().info("Starting client with server endpoint " + hostName + ":" + port);
+    clientVM.invoke(IntegratedSecDUnitTest.class, "setUpClientVMTask", params);
+    
+    Log.getLogWriter().info("Sleeping for 5 seconds to get all mbeans registered on manager");
+    try {
+      Thread.sleep(5000);
+    } catch (InterruptedException e) {
+      e.printStackTrace();
+    }
+    
+  }
+
+  @SuppressWarnings("serial")
+  private void configureIntSecDescriptor() {
+    this.userName = "tushark";
+    this.password = "password123";
+
+    final Host host = Host.getHost(0);
+    final VM serverVM = host.getVM(1);
+    final VM clientVM = host.getVM(2);
+    final VM managerVM = host.getVM(0);
+    SerializableRunnable grantOpsUser1Runnable = new SerializableRunnable() {
+      @Override
+      public void run() {
+        TestAuthenticator.addUser("tushark", "password123");
+        TestAuthenticator.addUser("dataRead", "password123");
+        TestAuthenticator.addUser("dataWrite", "password123");
+        TestAuthenticator.addUser("monitor", "password123");
+        TestAuthenticator.addUser("admin", "password123");
+        TestAuthenticator.addUser("custom", "password123");
+
+        TestAccessControl.grantCacheOp("tushark", OperationCode.GET);
+        TestAccessControl.grantCacheOp("tushark", OperationCode.PUT);
+        TestAccessControl.grantCacheOp("tushark", OperationCode.DESTROY);
+        TestAccessControl.grantCacheOp("tushark", OperationCode.REMOVEALL);
+        TestAccessControl.grantCacheOp("tushark", OperationCode.EXECUTE_FUNCTION);
+        TestAccessControl.grantCacheOp("tushark", OperationCode.QUERY);
+
+        TestAccessControl.grantResourceOp("tushark", ResourceOperationCode.DATA_READ);
+        TestAccessControl.grantResourceOp("tushark", ResourceOperationCode.DATA_WRITE);
+        TestAccessControl.grantResourceOp("tushark", ResourceOperationCode.MONITOR);
+        TestAccessControl.grantResourceOp("tushark", ResourceOperationCode.CHANGE_ALERT_LEVEL);
+
+        TestAccessControl.grantCacheOp("dataRead", OperationCode.GET);
+        TestAccessControl.grantResourceOp("dataRead", ResourceOperationCode.DATA_READ);
+
+        TestAccessControl.grantCacheOp("dataWrite", OperationCode.GET);
+        TestAccessControl.grantCacheOp("dataWrite", OperationCode.PUT);
+        TestAccessControl.grantCacheOp("dataWrite", OperationCode.DESTROY);
+        TestAccessControl.grantCacheOp("dataWrite", OperationCode.REGION_CREATE);
+        TestAccessControl.grantCacheOp("dataWrite", OperationCode.REGION_DESTROY);
+        TestAccessControl.grantResourceOp("dataWrite", ResourceOperationCode.DATA_WRITE);
+
+        TestAccessControl.grantResourceOp("monitor", ResourceOperationCode.DATA_READ);
+        TestAccessControl.grantResourceOp("monitor", ResourceOperationCode.MONITOR);
+
+        TestAccessControl.grantResourceOp("admin", ResourceOperationCode.ADMIN);
+
+        TestAccessControl.grantResourceOp("custom", ResourceOperationCode.DATA_READ);
+        TestAccessControl.grantResourceOp("custom", ResourceOperationCode.SHOW_DEADLOCKS);        
+        TestAccessControl.grantResourceOp("custom", ResourceOperationCode.CREATE_REGION);
+        TestAccessControl.grantCacheOp("custom", OperationCode.REGION_CREATE);
+      }
+    };
+    managerVM.invoke(grantOpsUser1Runnable);
+    serverVM.invoke(grantOpsUser1Runnable);
+  }
+
+  @SuppressWarnings("serial")
+  public static void grantCacheOp(final String user, final String code) {
+    final Host host = Host.getHost(0);
+    final VM serverVM = host.getVM(1);
+    final VM managerVM = host.getVM(0);
+    SerializableRunnable grantOpsUser1Runnable = new SerializableRunnable() {
+      @Override
+      public void run() {
+        TestAccessControl.grantCacheOp(user, OperationCode.parse(code));
+      }
+    };
+    managerVM.invoke(grantOpsUser1Runnable);
+    serverVM.invoke(grantOpsUser1Runnable);
+  }
+
+  @SuppressWarnings("serial")
+  public static void revokeCacheOp(final String user, final String code) {
+    final Host host = Host.getHost(0);
+    final VM serverVM = host.getVM(1);
+    final VM managerVM = host.getVM(0);
+    SerializableRunnable grantOpsUser1Runnable = new SerializableRunnable() {
+      @Override
+      public void run() {
+        TestAccessControl.revokeCacheOp(user, OperationCode.parse(code));
+      }
+    };
+    managerVM.invoke(grantOpsUser1Runnable);
+    serverVM.invoke(grantOpsUser1Runnable);
+  }
+
+  @SuppressWarnings("serial")
+  public static void grantResourceOp(final String user, final String code) {
+    final Host host = Host.getHost(0);
+    final VM serverVM = host.getVM(1);
+    final VM managerVM = host.getVM(0);
+    SerializableRunnable grantOpsUser1Runnable = new SerializableRunnable() {
+      @Override
+      public void run() {
+        TestAccessControl.grantResourceOp(user, ResourceOperationCode.parse(code));
+      }
+    };
+    managerVM.invoke(grantOpsUser1Runnable);
+    serverVM.invoke(grantOpsUser1Runnable);
+  }
+
+  @SuppressWarnings("serial")
+  public static void revokeResourceOp(final String user, final String code) {
+    final Host host = Host.getHost(0);
+    final VM serverVM = host.getVM(1);
+    final VM managerVM = host.getVM(0);
+    SerializableRunnable grantOpsUser1Runnable = new SerializableRunnable() {
+      @Override
+      public void run() {
+        TestAccessControl.revokeResourceOp(user, ResourceOperationCode.parse(code));
+      }
+    };
+    managerVM.invoke(grantOpsUser1Runnable);
+    serverVM.invoke(grantOpsUser1Runnable);
+  }
+
+  
+  public static void doPutUsingClientCache(final String regionPath, final String key, final String value,
+      final boolean expectSuccess, String user, String password) {   
+    try {
+      Properties properties = new Properties();
+      properties.setProperty("security-username", user);
+      properties.setProperty("security-password", password);
+      RegionService regionService = instance.clientCache.createAuthenticatedView(properties);
+      Region region = regionService.getRegion(regionPath);
+      assertNotNull(region);
+      Object oldValue = region.put(key, value);
+      Log.getLogWriter().info("doPutUsingClientCache : Put key=" + key + " for user="+ user+" newValue="+ value + " oldValue="+ oldValue + " expectSuccess="+expectSuccess);
+      if (!expectSuccess)
+        fail("Region Put was expected to fail");
+    } catch (Exception e) {
+      if (!expectSuccess) {
+        Log.getLogWriter().info("expectSuccess=false => " + e.getMessage());
+      } else {
+        Log.getLogWriter().error("Unexpected error", e);
+        fail("Unknown reason " + e.getMessage());
+      }
+    }
+  }
+
+  public void doPutUsingGfsh(final String regionPath, final String key, final String value,
+      final boolean expectSuccess, String user, String password) {
+    String command = "put --region=" + regionPath + " --key=" + key + " --value=" + value;
+    changeGfshUser(user, password);
+    CommandResult result = executeCommand(command);
+    Log.getLogWriter().info("CommandResult " + result);
+    if (expectSuccess) {
+      validateGfshResult(result, expectSuccess);
+      printCommandOutput(result);
+    }
+    else {
+      Log.getLogWriter().info("Error line :" + this.commandError);
+      assertTrue(this.commandError.contains("Access Denied"));
+      this.commandError = null;
+      // validateGfshResultError(result);
+    }
+  }
+
+  private static void validateGfshResultError(CommandResult result) {
+    if (result.getType().equals(ResultData.TYPE_ERROR)) {
+      ErrorResultData data = (ErrorResultData) result.getResultData();
+      Log.getLogWriter().info("Error resultData : " + data.toString());
+    } else
+      fail("Unexpected result type " + result.getType());
+  }
+
+  private static void validateGfshResult(CommandResult cmdResult, boolean expected) {
+    if (ResultData.TYPE_COMPOSITE.equals(cmdResult.getType())) {
+      CompositeResultData rd = (CompositeResultData) cmdResult.getResultData();
+      SectionResultData section = rd.retrieveSectionByIndex(0);
+      boolean result = (Boolean) section.retrieveObject("Result");
+      assertEquals(expected, result);
+    } else
+      fail("Expected CompositeResult Returned Result Type " + cmdResult.getType());
+  }
+
+  public static void doGetUsingClientCache(final String regionPath, final String key, final boolean expectSuccess,
+      String user, String password) {    
+    try {
+      Properties properties = new Properties();
+      properties.setProperty("security-username", user);
+      properties.setProperty("security-password", password);
+      RegionService regionService = instance.clientCache.createAuthenticatedView(properties);
+      Region region = regionService.getRegion(regionPath);
+      assertNotNull(region);
+      Object value = region.get(key);
+      Log.getLogWriter().info("doGetUsingClientCache : Get key=" + key + " for user="+ user+" value="+ value + " expectSuccess="+expectSuccess);
+      assertNotNull(value);
+      if (!expectSuccess)
+        fail("Region Get was expected to fail");
+    } catch (Exception e) {
+      if (!expectSuccess) {
+        Log.getLogWriter().info("expectSuccess=true => " + e.getMessage());
+      } else {
+        Log.getLogWriter().error("Unexpected error", e);
+        fail("Unknown reason " + e.getMessage());
+      }
+    }
+  }
+  
+  public void doGetUsingGfsh(final String regionPath, final String key, final boolean expectSuccess, String user,
+      String password) {
+    String command = "get --region=" + regionPath + " --key=" + key;
+    changeGfshUser(user, password);
+    CommandResult result = executeCommand(command);    
+    if (expectSuccess) {
+      printCommandOutput(result);
+      validateGfshResult(result, expectSuccess);      
+    }
+    else {
+      Log.getLogWriter().info("Error line :" + this.commandError);
+      assertTrue(this.commandError.contains("Access Denied"));
+      this.commandError = null;
+    }
+  }
+
+  private void changeGfshUser(String user, String password) {
+    if (!this.userName.equals(user)) {
+      executeCommand("disconnect");
+      this.userName = user;
+      this.password = password;
+      defaultShellConnect();
+    }
+  }
+  
+  public void doCommandUsingGfsh(String command, final boolean expectSuccess, String user, String password) {
+    changeGfshUser(user, password);
+    CommandResult result = executeCommand(command);
+    if (expectSuccess) {
+      assertNotNull(result);
+      printCommandOutput(result);
+      //assertFalse(result.getType().equals(ResultData.TYPE_ERROR));
+    }
+    else {
+      Log.getLogWriter().info("Error line :" + this.commandError);
+      assertTrue(this.commandError.contains("Access Denied"));
+      this.commandError = null;
+    }
+  }
+  
+  private static void printCommandOutput(CommandResult cmdResult) {
+    assertNotNull(cmdResult);
+    Log.getLogWriter().info("Command Output : ");
+    StringBuilder sb = new StringBuilder();
+    cmdResult.resetToFirstLine();
+    while (cmdResult.hasNextLine()) {
+      sb.append(cmdResult.nextLine()).append(DataCommandRequest.NEW_LINE);
+    }
+    Log.getLogWriter().info(sb.toString());
+    Log.getLogWriter().info("");      
+  }
+  
+  private void doShowLogUsingJMX(boolean expectSuccess, String user, String password) {
+    Object[] endPoint = getJMXEndPoint();
+    String[] creds = new String[] { user, password };
+    try {
+      JMXConnector connector = _getGemfireMBeanServer((Integer) endPoint[1], creds);
+      MBeanServerConnection mbeanServer = connector.getMBeanServerConnection();
+      ObjectName memberON = (ObjectName)mbeanServer.invoke(MBeanJMXAdapter.getDistributedSystemName(), "fetchMemberObjectName", 
+          new Object[]{"Manager"}, new String[]{String.class.getCanonicalName()});      
+      String logs = (String) mbeanServer.invoke(memberON, "showLog", new Object[]{60}, new String[]{int.class.toString()});
+      Log.getLogWriter().info("JMX Output :" + logs);
+      connector.close();
+      if(!expectSuccess)
+        fail("Expected Access Denied...");      
+    } catch (InstanceNotFoundException e) {
+      Log.getLogWriter().error("Unexpected Error", e);
+      fail("Unexpected Error " + e.getMessage());
+    } catch (MBeanException e) {
+      Log.getLogWriter().error("Unexpected Error", e);
+      fail("Unexpected Error " + e.getMessage());
+    } catch (ReflectionException e) {
+      Log.getLogWriter().error("Unexpected Error", e);
+      fail("Unexpected Error " + e.getMessage());
+    } catch (IOException e) {
+      Log.getLogWriter().error("Unexpected Error", e);
+      fail("Unexpected Error " + e.getMessage());
+    } catch (SecurityException e) {
+      if(expectSuccess){
+        fail("Expected successful jmx execution");
+      } else {
+        //expected
+      }
+    }
+  }
+  
+  
+  
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  private JMXConnector _getGemfireMBeanServer(int port, Object creds) {
+    JMXServiceURL url;
+    try {
+      url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:" + port + "/jmxrmi");
+      if (creds != null) {
+        Map env = new HashMap();        
+        env.put(JMXConnector.CREDENTIALS, creds);
+        JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
+        return jmxc;
+      } else {
+        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
+        return jmxc;
+      }
+    } catch (MalformedURLException e) {
+      fail("Error connecting to port=" + port + " " + e.getMessage());
+    } catch (IOException e) {
+      fail("Error connecting to port=" + port + " " + e.getMessage());
+    }
+    return null;
+  }
+
+  public void testDataCommandsFromDifferentClients() throws IOException {
+    final Host host = Host.getHost(0);
+    final VM clientVM = host.getVM(2);
+
+    setup("testDataCommandsFromDifferentClients");
+    executeCommand("list members");
+    changeGfshUser("dataRead", "password123");
+    executeCommand("list members");
+
+    // check tushark can execute get/put/delete/execute function/query operation from cacheclient and through
+    // data-commands
+    String region = "serverRegion";
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", true,
+        "tushark", "password123" });
+    doGetUsingGfsh(region, "myk1", true, "tushark", "password123");
+    doPutUsingGfsh(region, "myk2", "myv2", true, "tushark", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", true,
+        "tushark", "password123" });
+    revokeCacheOp("tushark", "PUT");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1",
+        false, "tushark", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", false, "tushark", "password123");
+    grantCacheOp("tushark", "PUT");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", true,
+        "tushark", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", true, "tushark", "password123");
+    
+    
+    //dataRead Role
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", false,
+      "dataRead", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", false, "dataRead", "password123");
+    doGetUsingGfsh(region, "myk1", true, "dataRead", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", true,
+      "dataRead", "password123" });    
+    
+    //dataWrite Role
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", true,
+      "dataWrite", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", true, "dataWrite", "password123");
+    doGetUsingGfsh(region, "myk1", true, "dataWrite", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", true,
+      "dataWrite", "password123" });
+    
+    
+    
+    //admin and monitor and custom roles can not execute get-put commands 
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", false,
+      "admin", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", false, "admin", "password123");
+    doGetUsingGfsh(region, "myk1", false, "admin", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", false,
+      "admin", "password123" });
+    
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", false,
+      "monitor", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", false, "monitor", "password123");
+    doGetUsingGfsh(region, "myk1", false, "monitor", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", false,
+      "monitor", "password123" });
+    
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doPutUsingClientCache", new Object[] { region, "myk1", "myv1", false,
+      "custom", "password123" });
+    doPutUsingGfsh(region, "myk2", "myv2", false, "custom", "password123");
+    doGetUsingGfsh(region, "myk1", false, "custom", "password123");
+    clientVM.invoke(IntegratedSecDUnitTest.class, "doGetUsingClientCache", new Object[] { region, "myk2", false,
+      "custom", "password123" });    
+    
+    // tushark can execute monitor command but not region create        
+    doCommandUsingGfsh("show metrics", true, "monitor", "password123");
+    doCommandUsingGfsh("show dead-locks --file=deadlocks_monitor.txt", true, "monitor", "password123");
+    
+    // dataWrite can execute create region
+    doCommandUsingGfsh("create region --type=REPLICATE --name=dataWriteRegion", true, "dataWrite", "password123");
+    doCommandUsingGfsh("create region --type=REPLICATE --name=dataReadRegion", false, "dataRead", "password123");
+    
+    // custom can create region create but not put region
+    doCommandUsingGfsh("create region --type=REPLICATE --name=customRegion", true, "custom", "password123");
+    doPutUsingGfsh("customRegion", "key", "value", false, "custom", "password123");
+    
+    // custom can execute show deadlocks - revoke it check again
+    doCommandUsingGfsh("show metrics", false, "custom", "password123");
+    doCommandUsingGfsh("show dead-locks --file=deadlocks_custom_1.txt", true, "custom", "password123");
+    revokeResourceOp("custom", ResourceOperationCode.SHOW_DEADLOCKS.toString());
+    grantResourceOp("custom", ResourceOperationCode.SHOW_METRICS.toString());
+    doCommandUsingGfsh("show metrics", true, "custom", "password123");
+    doCommandUsingGfsh("show dead-locks --file=deadlocks_custom_2.txt", false, "custom", "password123");
+    grantResourceOp("custom", ResourceOperationCode.SHOW_DEADLOCKS.toString());    
+    doCommandUsingGfsh("show metrics", true, "custom", "password123");
+    doCommandUsingGfsh("show dead-locks --file=deadlocks_custom_3.txt", true, "custom", "password123");    
+    
+    /* Commented due to error with gradle :  TailLogRequest/Response processed in application vm with shared logging
+    //check jmx and gfsh
+    doCommandUsingGfsh("show log --member=Manager", true, "monitor", "password123");
+    doCommandUsingGfsh("show log --member=Manager", false, "dataWrite", "password123");
+    doCommandUsingGfsh("show log --member=Manager", false, "custom", "password123");
+    
+    
+    doShowLogUsingJMX(true, "monitor", "password123");
+    doShowLogUsingJMX(false, "dataWrite", "password123");
+    doShowLogUsingJMX(false, "custom", "password123");
+
+    
+    grantResourceOp("custom", ResourceOperationCode.SHOW_LOG.toString());
+    doCommandUsingGfsh("show log --member=Manager", true, "custom", "password123");
+    doShowLogUsingJMX(true, "custom", "password123");*/
+  }
+
+  
+
+  public void tearDown2() throws Exception {
+    super.tearDown2();
+  }
+
+}


Mime
View raw message