GEODE-17: enable authentication/authorization of rest admin API and add a test suite to test it.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/24cdcbbb Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/24cdcbbb Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/24cdcbbb Branch: refs/heads/feature/GEODE-17-2 Commit: 24cdcbbb8089a3a4d545eb8d24f943e6db75ff61 Parents: 3d45e75 Author: Jinmei Liao <jil...@pivotal.io> Authored: Tue Apr 12 14:13:27 2016 -0700 Committer: Jinmei Liao <jil...@pivotal.io> Committed: Tue Apr 12 14:13:27 2016 -0700 ---------------------------------------------------------------------- .../management/internal/ManagementAgent.java | 16 ++++-- .../controllers/AbstractCommandsController.java | 28 ++++++++-- .../EnvironmentVariablesHandlerInterceptor.java | 4 +- .../cli/commands/CliCommandTestBase.java | 17 ++++-- .../commands/CommandOverHttpSecurityTests.java | 58 ++++++++++++++++++++ .../ConfigCommandsSecurityDunitTest.java | 22 -------- 6 files changed, 105 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/main/java/com/gemstone/gemfire/management/internal/ManagementAgent.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/ManagementAgent.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/ManagementAgent.java index d408e26..64229db 100755 --- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/ManagementAgent.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/ManagementAgent.java @@ -82,6 +82,7 @@ public class ManagementAgent { private JMXConnectorServer cs; private final DistributionConfig config; private boolean isHttpServiceRunning = false; + private ManagementInterceptor managementInterceptor = null; /** * This system property is set to true when the embedded HTTP server is @@ -98,6 +99,10 @@ public class ManagementAgent { return this.running; } + public ManagementInterceptor getManagementInterceptor() { + return managementInterceptor; + } + public synchronized boolean isHttpServiceRunning() { return isHttpServiceRunning; } @@ -388,11 +393,10 @@ public class ManagementAgent { // Environment map. KIRK: why is this declared as HashMap? final HashMap<String, Object> env = new HashMap<String, Object>(); - ManagementInterceptor securityInterceptor = null; Cache cache = CacheFactory.getAnyInstance(); if (isCustomAuthenticator()) { - securityInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getProperties()); - env.put(JMXConnectorServer.AUTHENTICATOR, securityInterceptor); + managementInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getProperties()); + env.put(JMXConnectorServer.AUTHENTICATOR, managementInterceptor); } else { /* Disable the old authenticator mechanism */ @@ -466,10 +470,10 @@ public class ManagementAgent { }; if (isCustomAuthorizer()) { - if(securityInterceptor==null){ - securityInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getProperties()); + if(managementInterceptor==null){ + managementInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getProperties()); } - MBeanServerWrapper mBeanServerWrapper = new MBeanServerWrapper(securityInterceptor); + MBeanServerWrapper mBeanServerWrapper = new MBeanServerWrapper(managementInterceptor); cs.setMBeanServerForwarder(mBeanServerWrapper); logger.info("Starting RMI Connector with Security Interceptor"); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java index 1750bd3..fc90c79 100644 --- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java @@ -18,7 +18,6 @@ package com.gemstone.gemfire.management.internal.web.controllers; import com.gemstone.gemfire.cache.CacheFactory; -import com.gemstone.gemfire.internal.cache.GemFireCacheImpl; import com.gemstone.gemfire.internal.lang.StringUtils; import com.gemstone.gemfire.internal.logging.LogService; import com.gemstone.gemfire.internal.logging.log4j.LogMarker; @@ -91,7 +90,6 @@ public abstract class AbstractCommandsController { private Class accessControlKlass; - private GemFireCacheImpl cache; // Convert a predefined exception to an HTTP Status code @ResponseStatus(value=HttpStatus.UNAUTHORIZED, reason="Not authenticated") // 401 @@ -619,11 +617,31 @@ public abstract class AbstractCommandsController { protected String processCommand(final String command, final Map<String, String> environment, final byte[][] fileData) { logger.info(LogMarker.CONFIG, "Processing Command ({}) with Environment ({}) having File Data ({})...", command, environment, (fileData != null)); - - ResourceOperationContext ctx = authorize(command); +// // create the jmx connection +// // con.getMemberMXBean then call the processCommand on that bean +// Map<String, String[]> env = new HashMap<>(); +// GemFireCacheImpl cache = GemFireCacheImpl.getInstance(); +// int jmxPort = cache.getDistributedSystem().getConfig().getJmxManagerPort(); +// Properties credentials = EnvironmentVariablesHandlerInterceptor.CREDENTIALS.get(); +// if(credentials!=null) { +// env.put(JMXConnector.CREDENTIALS, new String[] { credentials.getProperty("security-username"), credentials.getProperty("security-password") }); +// } +// +// String result = null; +// try { +// JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:" + jmxPort + "/jmxrmi"); +// JMXConnector jmxConnector = JMXConnectorFactory.connect(url, env); +// MBeanServerConnection con = jmxConnector.getMBeanServerConnection(); +// +// MemberMXBean memberMXBean = JMX.newMXBeanProxy(con, ObjectName.getInstance("GemFire:type=Member,member=Manager"), MemberMXBean.class); +// result = memberMXBean.processCommand(command, environment, ArrayUtils.toByteArray(fileData)); +// } +// catch(Exception e){ +// e.printStackTrace(); +// } + ResourceOperationContext ctx = authorize(command); String result = getManagingMemberMXBean().processCommand(command, environment, ArrayUtils.toByteArray(fileData)); - ctx = postAuthorize(command, ctx, result); return result; http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java index fec9e97..29a3005 100644 --- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java @@ -120,11 +120,13 @@ public class EnvironmentVariablesHandlerInterceptor extends HandlerInterceptorAd } } + GemFireCacheImpl instance = GemFireCacheImpl.getInstance(); if(instance != null){ SystemManagementService service = (SystemManagementService) ManagementService .getExistingManagementService(instance); - service.getAuthManager().verifyCredentials(credentials); + //service.getAuthManager().verifyCredentials(credentials); + service.getManagementAgent().getManagementInterceptor().authenticate(credentials); CREDENTIALS.set(credentials); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CliCommandTestBase.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CliCommandTestBase.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CliCommandTestBase.java index bda8e23..6d2b3be 100644 --- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CliCommandTestBase.java +++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CliCommandTestBase.java @@ -56,12 +56,14 @@ public class CliCommandTestBase extends JUnit4CacheTestCase { private static final long serialVersionUID = 1L; public static final String USE_HTTP_SYSTEM_PROPERTY = "useHTTP"; + public static final String JSON_AUTHORIZATION_SYSTEM_PROPERTY = "jsonAuthorization"; private ManagementService managementService; private transient HeadlessGfsh shell; private boolean useHttpOnConnect = Boolean.getBoolean(USE_HTTP_SYSTEM_PROPERTY); + private String jsonAuthorization = System.getProperty(JSON_AUTHORIZATION_SYSTEM_PROPERTY); private int httpPort; private int jmxPort; @@ -89,7 +91,8 @@ public class CliCommandTestBase extends JUnit4CacheTestCase { * @return the default testable GemFire shell. */ @SuppressWarnings("serial") - protected final HeadlessGfsh createDefaultSetup(final Properties props) { + protected HeadlessGfsh createDefaultSetup(final Properties props) { + final String json = System.getProperty("jsonAuthorization"); Object[] result = (Object[]) Host.getHost(0).getVM(0).invoke( "createDefaultSetup", () -> { final Object[] results = new Object[3]; final Properties localProps = (props != null ? props : new Properties()); @@ -115,19 +118,18 @@ public class CliCommandTestBase extends JUnit4CacheTestCase { localProps.setProperty(DistributionConfig.JMX_MANAGER_PORT_NAME, String.valueOf(jmxPort)); localProps.setProperty(DistributionConfig.HTTP_SERVICE_PORT_NAME, String.valueOf(httpPort)); - if(localProps.getProperty("jsonFile")!=null){ + if(json!=null){ localProps.put(DistributionConfig.SECURITY_CLIENT_AUTHENTICATOR_NAME, JSONAuthorization.class.getName() + ".create"); localProps.put(DistributionConfig.SECURITY_CLIENT_ACCESSOR_NAME, JSONAuthorization.class.getName() + ".create"); try { - JSONAuthorization.setUpWithJsonFile(localProps.getProperty("jsonFile")); + JSONAuthorization.setUpWithJsonFile(json); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } - localProps.remove("jsonFile"); } getSystem(localProps); @@ -231,12 +233,15 @@ public class CliCommandTestBase extends JUnit4CacheTestCase { final CommandStringBuilder command = new CommandStringBuilder(CliStrings.CONNECT); String endpoint; + if(jsonAuthorization!=null) { + command.addOption(CliStrings.CONNECT__USERNAME, "super-user"); + command.addOption(CliStrings.CONNECT__PASSWORD, "1234567"); + } + if (useHttpOnConnect) { endpoint = "http://" + host + ":" + httpPort + "/gemfire/v1"; command.addOption(CliStrings.CONNECT__USE_HTTP, Boolean.TRUE.toString()); command.addOption(CliStrings.CONNECT__URL, endpoint); - command.addOption(CliStrings.CONNECT__USERNAME, "super-user"); - command.addOption(CliStrings.CONNECT__PASSWORD, "1234567"); } else { endpoint = host + "[" + jmxPort + "]"; command.addOption(CliStrings.CONNECT__JMX_MANAGER, endpoint); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CommandOverHttpSecurityTests.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CommandOverHttpSecurityTests.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CommandOverHttpSecurityTests.java new file mode 100644 index 0000000..7c67065 --- /dev/null +++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/CommandOverHttpSecurityTests.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gemstone.gemfire.management.internal.cli.commands; + +import com.gemstone.gemfire.test.junit.categories.IntegrationTest; +import org.junit.ClassRule; +import org.junit.contrib.java.lang.system.ProvideSystemProperty; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@Category(IntegrationTest.class) + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + ConfigCommandsDUnitTest.class, + DeployCommandsDUnitTest.class, + DiskStoreCommandsDUnitTest.class, + FunctionCommandsDUnitTest.class, + GemfireDataCommandsDUnitTest.class, + GetCommandOnRegionWithCacheLoaderDuringCacheMissDUnitTest.class, + IndexCommandsDUnitTest.class, + ListAndDescribeDiskStoreCommandsDUnitTest.class, + ListIndexCommandDUnitTest.class, + MemberCommandsDUnitTest.class, + MiscellaneousCommandsDUnitTest.class, + MiscellaneousCommandsExportLogsPart1DUnitTest.class, + MiscellaneousCommandsExportLogsPart2DUnitTest.class, + MiscellaneousCommandsExportLogsPart3DUnitTest.class, + MiscellaneousCommandsExportLogsPart4DUnitTest.class, + QueueCommandsDUnitTest.class, + SharedConfigurationCommandsDUnitTest.class, + ShellCommandsDUnitTest.class, + ShowDeadlockDUnitTest.class, + ShowMetricsDUnitTest.class, + ShowStackTraceDUnitTest.class, + UserCommandsDUnitTest.class +}) +public class CommandOverHttpSecurityTests { + @ClassRule + public static ProvideSystemProperty systemProperty = new ProvideSystemProperty(CliCommandTestBase.USE_HTTP_SYSTEM_PROPERTY, "true") + .and("jsonAuthorization", "cacheServer.json"); + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/24cdcbbb/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/ConfigCommandsSecurityDunitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/ConfigCommandsSecurityDunitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/ConfigCommandsSecurityDunitTest.java deleted file mode 100644 index db0e4b7..0000000 --- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/commands/ConfigCommandsSecurityDunitTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gemstone.gemfire.management.internal.cli.commands; - -import com.gemstone.gemfire.management.internal.cli.HeadlessGfsh; - -import java.util.Properties; - -public class ConfigCommandsSecurityDunitTest extends ConfigCommandsDUnitTest { - - public ConfigCommandsSecurityDunitTest(String name) { - super(name); - } - - protected HeadlessGfsh createDefaultSetup(Properties props){ - if (props==null) { - props = new Properties(); - } - props.put("jsonFile", "cacheServer.json"); - - - return super.createDefaultSetup(props); - } -}