You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2016/03/17 23:10:49 UTC
incubator-geode git commit: GEODE-17: Integrated Security Related
Changes for Pulse and Refactor interface
Repository: incubator-geode
Updated Branches:
refs/heads/feature/GEODE-17-2 d4ef0a247 -> 386ace7c8
GEODE-17: Integrated Security Related Changes for Pulse and Refactor interface
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/386ace7c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/386ace7c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/386ace7c
Branch: refs/heads/feature/GEODE-17-2
Commit: 386ace7c8936d3e02d0e11cb0849cf9829608674
Parents: d4ef0a2
Author: Jinmei Liao <ji...@pivotal.io>
Authored: Thu Mar 17 15:09:22 2016 -0700
Committer: Jinmei Liao <ji...@pivotal.io>
Committed: Thu Mar 17 15:10:24 2016 -0700
----------------------------------------------------------------------
.../management/internal/ManagementAgent.java | 10 +-
.../security/ManagementInterceptor.java | 20 +--
.../gemfire/security/AccessControl.java | 8 +-
.../gemfire/security/Authenticator.java | 19 ++-
.../tools/pulse/internal/PulseAppListener.java | 70 ++++++--
.../internal/controllers/PulseController.java | 13 +-
.../tools/pulse/internal/data/Cluster.java | 9 +
.../pulse/internal/data/JMXDataUpdater.java | 168 ++++++++++---------
.../pulse/internal/data/PulseConstants.java | 17 ++
.../tools/pulse/internal/data/Repository.java | 19 ++-
.../security/GemFireAuthentication.java | 156 +++++++++++++++++
.../security/GemFireAuthenticationProvider.java | 85 ++++++++++
.../pulse/internal/security/LogoutHandler.java | 55 ++++++
geode-pulse/src/main/resources/pulse.properties | 12 +-
.../src/main/webapp/WEB-INF/spring-security.xml | 59 ++++---
.../gemfire/tools/pulse/tests/PulseTest.java | 2 +
.../gemfire/tools/pulse/tests/Server.java | 39 ++++-
17 files changed, 608 insertions(+), 153 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/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 8075938..a36da80 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
@@ -16,6 +16,7 @@
*/
package com.gemstone.gemfire.management.internal;
+import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
@@ -191,6 +192,10 @@ public class ManagementAgent {
if (logger.isDebugEnabled()) {
logger.debug(message);
}
+
+ if (isCustomAuthorizer()){
+ System.setProperty("spring.profiles.active", "pulse.authentication.gemfire");
+ }
}
// Find developer REST WAR file
@@ -385,8 +390,9 @@ public class ManagementAgent {
final HashMap<String, Object> env = new HashMap<String, Object>();
ManagementInterceptor securityInterceptor = null;
+ Cache cache = CacheFactory.getAnyInstance();
if (isCustomAuthenticator()) {
- securityInterceptor = new ManagementInterceptor((GemFireCacheImpl)CacheFactory.getAnyInstance());
+ securityInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getSecurityProperties());
env.put(JMXConnectorServer.AUTHENTICATOR, securityInterceptor);
}
else {
@@ -462,7 +468,7 @@ public class ManagementAgent {
if (isCustomAuthorizer()) {
if(securityInterceptor==null){
- securityInterceptor = new ManagementInterceptor((GemFireCacheImpl)CacheFactory.getAnyInstance());
+ securityInterceptor = new ManagementInterceptor(cache.getDistributedSystem().getSecurityProperties());
}
MBeanServerWrapper mBeanServerWrapper = new MBeanServerWrapper(securityInterceptor);
cs.setMBeanServerForwarder(mBeanServerWrapper);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
index 0a736a9..446ec10 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/security/ManagementInterceptor.java
@@ -17,8 +17,6 @@
package com.gemstone.gemfire.management.internal.security;
import com.gemstone.gemfire.GemFireConfigException;
-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;
@@ -67,17 +65,16 @@ public class ManagementInterceptor implements JMXAuthenticator{
public static final String OBJECT_NAME_ACCESSCONTROL = "GemFire:service=AccessControl,type=Distributed";
private static final Logger logger = LogManager.getLogger(ManagementInterceptor.class);
- private Cache cache;
+// private Cache cache;
private String authzFactoryName;
private String postAuthzFactoryName;
private String authenticatorFactoryName;
private ConcurrentMap<Principal, AccessControl> cachedAuthZCallback;
private ConcurrentMap<Principal, AccessControl> cachedPostAuthZCallback;
+ private Properties sysProps = null;
- public ManagementInterceptor(Cache gemFireCacheImpl) {
- this.cache = gemFireCacheImpl;
- DistributedSystem system = cache.getDistributedSystem();
- Properties sysProps = system.getProperties();
+ public ManagementInterceptor(Properties sysProps) {
+ this.sysProps = sysProps;
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);
@@ -138,8 +135,7 @@ public class ManagementInterceptor implements JMXAuthenticator{
}
try {
- Principal principal = getAuthenticator(cache.getDistributedSystem().getSecurityProperties()).authenticate(pr,
- cache.getDistributedSystem().getDistributedMember());
+ Principal principal = getAuthenticator(sysProps).authenticate(pr);
return new Subject(true, Collections.singleton(new JMXPrincipal(principal.getName())), Collections.EMPTY_SET,
Collections.EMPTY_SET);
} catch (AuthenticationFailedException e) {
@@ -187,7 +183,7 @@ public class ManagementInterceptor implements JMXAuthenticator{
try {
Method authzMethod = ClassLoadUtil.methodFromName(authzFactoryName);
AccessControl authzCallback = (AccessControl) authzMethod.invoke(null, (Object[]) null);
- authzCallback.init(principal, null, cache);
+ authzCallback.init(principal, null);
cachedAuthZCallback.put(principal, authzCallback);
return authzCallback;
} catch (Exception ex) {
@@ -202,7 +198,7 @@ public class ManagementInterceptor implements JMXAuthenticator{
try {
Method authzMethod = ClassLoadUtil.methodFromName(postAuthzFactoryName);
AccessControl postAuthzCallback = (AccessControl) authzMethod.invoke(null, (Object[]) null);
- postAuthzCallback.init(principal, null, cache);
+ postAuthzCallback.init(principal, null);
cachedPostAuthZCallback.put(principal, postAuthzCallback);
return postAuthzCallback;
} catch (Exception ex) {
@@ -227,7 +223,7 @@ public class ManagementInterceptor implements JMXAuthenticator{
throw new AuthenticationFailedException(
LocalizedStrings.HandShake_AUTHENTICATOR_INSTANCE_COULD_NOT_BE_OBTAINED.toLocalizedString());
}
- auth.init(gfSecurityProperties, this.cache.getLogger(), this.cache.getSecurityLogger());
+ auth.init(gfSecurityProperties);
return auth;
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-core/src/main/java/com/gemstone/gemfire/security/AccessControl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/AccessControl.java b/geode-core/src/main/java/com/gemstone/gemfire/security/AccessControl.java
index 214d8f0..349ba76 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/security/AccessControl.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/AccessControl.java
@@ -17,12 +17,14 @@
package com.gemstone.gemfire.security;
-import java.security.Principal;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheCallback;
+import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.operations.OperationContext;
import com.gemstone.gemfire.distributed.DistributedMember;
+import java.security.Principal;
+
/**
* Specifies the interface to authorize operations at the cache or region level
* for clients or servers. Implementations should register name of the static
@@ -68,6 +70,10 @@ public interface AccessControl extends CacheCallback {
public void init(Principal principal, DistributedMember remoteMember,
Cache cache) throws NotAuthorizedException;
+ default public void init(Principal principal, DistributedMember remoteMember) throws NotAuthorizedException {
+ init(principal, remoteMember, CacheFactory.getAnyInstance());
+ }
+
/**
* Check if the given operation is allowed for the cache/region.
*
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-core/src/main/java/com/gemstone/gemfire/security/Authenticator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/Authenticator.java b/geode-core/src/main/java/com/gemstone/gemfire/security/Authenticator.java
index dcf3e7c..4f9b6f2 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/security/Authenticator.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/Authenticator.java
@@ -17,14 +17,16 @@
package com.gemstone.gemfire.security;
-import java.util.Properties;
-import java.security.Principal;
-
import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheCallback;
+import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.DistributedSystem;
+import java.security.Principal;
+import java.util.Properties;
+
/**
* Specifies the mechanism to verify credentials for a client or peer.
* Implementations should register name of the static creation function as the
@@ -63,6 +65,11 @@ public interface Authenticator extends CacheCallback {
public void init(Properties securityProps, LogWriter systemLogger,
LogWriter securityLogger) throws AuthenticationFailedException;
+ default public void init(Properties securityProps) throws AuthenticationFailedException{
+ Cache cache = CacheFactory.getAnyInstance();
+ init(securityProps, cache.getLogger(), cache.getSecurityLogger());
+ }
+
/**
* Verify the credentials provided in the properties for the client/peer as
* specified in member ID and returns the principal associated with the
@@ -84,4 +91,10 @@ public interface Authenticator extends CacheCallback {
public Principal authenticate(Properties props, DistributedMember member)
throws AuthenticationFailedException;
+ default public Principal authenticate(Properties props)
+ throws AuthenticationFailedException{
+ DistributedMember member = CacheFactory.getAnyInstance().getDistributedSystem().getDistributedMember();
+ return authenticate(props, member);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/PulseAppListener.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/PulseAppListener.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/PulseAppListener.java
index 784caed..1732005 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/PulseAppListener.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/PulseAppListener.java
@@ -19,6 +19,17 @@
package com.vmware.gemfire.tools.pulse.internal;
+import com.vmware.gemfire.tools.pulse.internal.controllers.PulseController;
+import com.vmware.gemfire.tools.pulse.internal.data.PulseConfig;
+import com.vmware.gemfire.tools.pulse.internal.data.PulseConstants;
+import com.vmware.gemfire.tools.pulse.internal.data.Repository;
+import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
+import com.vmware.gemfire.tools.pulse.internal.util.StringUtils;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -30,22 +41,12 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map.Entry;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
-import java.util.Map.Entry;
import java.util.logging.Level;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import com.vmware.gemfire.tools.pulse.internal.controllers.PulseController;
-import com.vmware.gemfire.tools.pulse.internal.data.PulseConfig;
-import com.vmware.gemfire.tools.pulse.internal.data.PulseConstants;
-import com.vmware.gemfire.tools.pulse.internal.data.Repository;
-import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
-import com.vmware.gemfire.tools.pulse.internal.util.StringUtils;
-
/**
* This class is used for checking the application running mode i.e. Embedded or
* not
@@ -74,6 +75,11 @@ public class PulseAppListener implements ServletContextListener {
private boolean sysPulseUseSSLLocator;
private boolean sysPulseUseSSLManager;
+
+ //This property determines if pulse webApp login is authenticated against
+ //GemFire integrated security or custom spring-security config provided
+ //in pulse-authentication-custom.xml
+ private boolean useGemFireCredentials;
@Override
public void contextDestroyed(ServletContextEvent event) {
@@ -90,7 +96,7 @@ public class PulseAppListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
-
+
messagesToBeLogged = messagesToBeLogged
.concat(formatLogString(resourceBundle
.getString("LOG_MSG_CONTEXT_INITIALIZED")));
@@ -189,10 +195,11 @@ public class PulseAppListener implements ServletContextListener {
loadJMXUserDetails();
// Load locator and/or manager details
loadLocatorManagerDetails();
-
+
+ useGemFireCredentials = areWeUsingGemFireSecurityProfile(event);
}
-
- // Set user details in repository
+
+ // Set user details in repository
repository.setJmxUserName(jmxUserName);
repository.setJmxUserPassword(jmxUserPassword);
@@ -205,7 +212,40 @@ public class PulseAppListener implements ServletContextListener {
initializeSSL();
repository.setUseSSLLocator(sysPulseUseSSLLocator);
repository.setUseSSLManager(sysPulseUseSSLManager);
+
+ repository.setUseGemFireCredentials(useGemFireCredentials);
+
+ }
+ /**
+ * Return true if pulse is configure to authenticate using gemfire
+ * integrated security
+ *
+ * @param event
+ * @return
+ */
+ private boolean areWeUsingGemFireSecurityProfile(ServletContextEvent event) {
+ String profile = null;
+ WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
+ if (ctx.getEnvironment() != null) {
+ String[] profiles = ctx.getEnvironment().getActiveProfiles();
+ if (profiles != null && profiles.length > 0) {
+ StringBuilder sb = new StringBuilder();
+ for (String p : profiles)
+ sb.append(p).append(",");
+ LOGGER.info("#SpringProfilesConfigured : " + sb.toString());
+ profile = ctx.getEnvironment().getActiveProfiles()[0];
+ LOGGER.info("#First Profile : " + profile);
+ } else {
+ LOGGER.info("No SpringProfileConfigured using default spring profile");
+ return false;
+ }
+ }
+ if (PulseConstants.APPLICATION_PROPERTY_PULSE_SEC_PROFILE_GEMFIRE.equals(profile)) {
+ LOGGER.info("Using gemfire integrated security profile");
+ return true;
+ }
+ return false;
}
// Function to load pulse version details from properties file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/controllers/PulseController.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/controllers/PulseController.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/controllers/PulseController.java
index 22be468..957340d 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/controllers/PulseController.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/controllers/PulseController.java
@@ -40,7 +40,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
@@ -148,17 +147,25 @@ public class PulseController {
return null != request.getUserPrincipal();
}
+ /* Not used replaced by SpringSecurity Logout tag with LogoutHandler
@RequestMapping(value = "/clusterLogout", method = RequestMethod.GET)
public void clusterLogout(HttpServletRequest request,
HttpServletResponse response) throws IOException {
+ PulseLogWriter LOGGER = PulseLogWriter.getLogger();
+ LOGGER.info("Inside #clusterLogout...");
+ if(Repository.get().isUseGemFireCredentials()) {
+ GemFireAuthentication authentication = (GemFireAuthentication) SecurityContextHolder.getContext()
+ .getAuthentication();
+ authentication.getJmxc().close();
+ LOGGER.info("Closing GemFireAuthentication JMX Connection...");
+ }
HttpSession session = request.getSession(false);
if (session != null) {
-
// End session and redirect
session.invalidate();
}
response.sendRedirect("../Login.html");
- }
+ }*/
@RequestMapping(value = "/pulseVersion", method = RequestMethod.GET)
public void pulseVersion(HttpServletRequest request,
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Cluster.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Cluster.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Cluster.java
index 5390794..ce075bd 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Cluster.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Cluster.java
@@ -54,6 +54,7 @@ import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.remote.JMXConnector;
/**
* Class Cluster This class is the Data Model for the data used for the Pulse
* Web UI.
@@ -2899,6 +2900,14 @@ public class Cluster extends Thread {
public boolean deleteQueryById(String userId, String queryId) {
return this.getDataBrowser().deleteQueryById(userId, queryId);
}
+
+ public JMXConnector connectToGemFire(String user, String password) {
+ if(this.updater instanceof JMXDataUpdater) {
+ return ((JMXDataUpdater) this.updater).getJMXConnection(user, password, false);
+ } else {
+ return null;
+ }
+ }
/**
* inner class for creating Mock Data
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/JMXDataUpdater.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/JMXDataUpdater.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/JMXDataUpdater.java
index 71dfa61..7e068ad 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/JMXDataUpdater.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/JMXDataUpdater.java
@@ -145,56 +145,91 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
}
- private JMXConnector getJMXConnection() {
- JMXConnector connection = null;
- // Reference to repository
- Repository repository = Repository.get();
- try {
+ private JmxManagerInfo getManagerInfoFromLocator(Repository repository) {
- String jmxSerURL = "";
+ try {
+ String locatorHost = repository.getJmxHost();
+ int locatorPort = Integer.parseInt(repository.getJmxPort());
if (LOGGER.infoEnabled()) {
- LOGGER.info(resourceBundle.getString("LOG_MSG_USE_LOCATOR_VALUE") + ":"
- + repository.getJmxUseLocator());
+ LOGGER.info(resourceBundle.getString("LOG_MSG_HOST") + " : " + locatorHost + " & "
+ + resourceBundle.getString("LOG_MSG_PORT") + " : " + locatorPort);
}
- if (repository.getJmxUseLocator()) {
+ InetAddress inetAddr = InetAddress.getByName(locatorHost);
+
+ if ((inetAddr instanceof Inet4Address) || (inetAddr instanceof Inet6Address)) {
- String locatorHost = repository.getJmxHost();
- int locatorPort = Integer.parseInt(repository.getJmxPort());
+ if (inetAddr instanceof Inet4Address) {
+ if (LOGGER.infoEnabled()) {
+ LOGGER.info(resourceBundle.getString("LOG_MSG_LOCATOR_IPV4_ADDRESS") + " - " + inetAddr.toString());
+ }
+ } else {
+ if (LOGGER.infoEnabled()) {
+ LOGGER.info(resourceBundle.getString("LOG_MSG_LOCATOR_IPV6_ADDRESS") + " - " + inetAddr.toString());
+ }
+ }
+
+ JmxManagerInfo jmxManagerInfo = JmxManagerFinder.askLocatorForJmxManager(inetAddr, locatorPort, 15000,
+ repository.isUseSSLLocator());
+ if (jmxManagerInfo.port == 0) {
+ if (LOGGER.infoEnabled()) {
+ LOGGER.info(resourceBundle.getString("LOG_MSG_LOCATOR_COULD_NOT_FIND_MANAGER"));
+ }
+ }
+ return jmxManagerInfo;
+ } else {
+ // Locator has Invalid locator Address
if (LOGGER.infoEnabled()) {
- LOGGER.info(resourceBundle.getString("LOG_MSG_HOST") + " : "
- + locatorHost + " & " + resourceBundle.getString("LOG_MSG_PORT")
- + " : " + locatorPort);
+ LOGGER.info(resourceBundle.getString("LOG_MSG_LOCATOR_BAD_ADDRESS"));
}
+ cluster.setConnectionErrorMsg(resourceBundle.getString("LOG_MSG_JMX_CONNECTION_BAD_ADDRESS"));
+ // update message to display on UI
+ cluster.setConnectionErrorMsg(resourceBundle
+ .getString("LOG_MSG_JMX_CONNECTION_BAD_ADDRESS"));
+ return null;
+ }
+ } catch (IOException e) {
+ StringWriter swBuffer = new StringWriter();
+ PrintWriter prtWriter = new PrintWriter(swBuffer);
+ e.printStackTrace(prtWriter);
+ LOGGER.severe("Exception Details : " + swBuffer.toString() + "\n");
+ }
+ return null;
+ }
- InetAddress inetAddr = InetAddress.getByName(locatorHost);
+ /**
+ * Default connection is Pulse which uses configured userName and password
+ * @return
+ */
+ public JMXConnector getJMXConnection() {
+ return getJMXConnection(this.userName, this.userPassword, true);
+ }
- if ((inetAddr instanceof Inet4Address)
- || (inetAddr instanceof Inet6Address)) {
+ /**
+ * Get connection for given userName and password. This is used for DataBrowser
+ * queries which has to be fired using credentials provided at pulse login page
+ *
+ * @param user jmxUser name
+ * @param password password
+ * @return
+ */
+ public JMXConnector getJMXConnection(String user, String password, final boolean registerURL) {
+ JMXConnector connection = null;
+ // Reference to repository
+ Repository repository = Repository.get();
+ try {
- if (inetAddr instanceof Inet4Address) {
- // Locator has IPv4 Address
- if (LOGGER.infoEnabled()) {
- LOGGER.info(resourceBundle
- .getString("LOG_MSG_LOCATOR_IPV4_ADDRESS")
- + " - "
- + inetAddr.toString());
- }
- } else {
- // Locator has IPv6 Address
- if (LOGGER.infoEnabled()) {
- LOGGER.info(resourceBundle
- .getString("LOG_MSG_LOCATOR_IPV6_ADDRESS")
- + " - "
- + inetAddr.toString());
- }
- }
+ String jmxSerURL = "";
- JmxManagerInfo jmxManagerInfo = JmxManagerFinder
- .askLocatorForJmxManager(inetAddr, locatorPort, 15000,
- repository.isUseSSLLocator());
+ if (LOGGER.infoEnabled()) {
+ LOGGER.info(resourceBundle.getString("LOG_MSG_USE_LOCATOR_VALUE") + ":"
+ + repository.getJmxUseLocator());
+ }
+
+ if (repository.getJmxUseLocator()) {
+ JmxManagerInfo jmxManagerInfo = getManagerInfoFromLocator(repository);
if (jmxManagerInfo.port == 0) {
if (LOGGER.infoEnabled()) {
@@ -221,28 +256,6 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
jmxSerURL = formJMXServiceURLString(jmxManagerInfo.host,
String.valueOf(jmxManagerInfo.port));
}
-
- } /*
- * else if (inetAddr instanceof Inet6Address) { // Locator has IPv6
- * Address if(LOGGER.infoEnabled()){
- * LOGGER.info(resourceBundle.getString
- * ("LOG_MSG_LOCATOR_IPV6_ADDRESS")); } // update message to display
- * on UI cluster.setConnectionErrorMsg(resourceBundle.getString(
- * "LOG_MSG_JMX_CONNECTION_IPv6_ADDRESS"));
- *
- * }
- */else {
- // Locator has Invalid locator Address
- if (LOGGER.infoEnabled()) {
- LOGGER
- .info(resourceBundle.getString("LOG_MSG_LOCATOR_BAD_ADDRESS"));
- }
- // update message to display on UI
- cluster.setConnectionErrorMsg(resourceBundle
- .getString("LOG_MSG_JMX_CONNECTION_BAD_ADDRESS"));
-
- }
-
} else {
if (LOGGER.infoEnabled()) {
LOGGER.info(resourceBundle.getString("LOG_MSG_HOST") + " : "
@@ -254,11 +267,8 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
if (StringUtils.isNotNullNotEmptyNotWhiteSpace(jmxSerURL)) {
JMXServiceURL url = new JMXServiceURL(jmxSerURL);
-
- // String[] creds = {"controlRole", "R&D"};
- String[] creds = { this.userName, this.userPassword };
+ String[] creds = { user, password };
Map<String, Object> env = new HashMap<String, Object>();
-
env.put(JMXConnector.CREDENTIALS, creds);
if (repository.isUseSSLManager()) {
@@ -266,20 +276,19 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
env.put("com.sun.jndi.rmi.factory.socket",
new SslRMIClientSocketFactory());
}
-
+ LOGGER.info("Connecting to jmxURL : " + jmxSerURL);
connection = JMXConnectorFactory.connect(url, env);
// Register Pulse URL if not already present in the JMX Manager
- registerPulseUrlToManager(connection);
+ if(registerURL)
+ registerPulseUrlToManager(connection);
}
} catch (Exception e) {
if (e instanceof UnknownHostException) {
- // update message to display on UI
cluster.setConnectionErrorMsg(resourceBundle
.getString("LOG_MSG_JMX_CONNECTION_UNKNOWN_HOST"));
}
- // write errors
StringWriter swBuffer = new StringWriter();
PrintWriter prtWriter = new PrintWriter(swBuffer);
e.printStackTrace(prtWriter);
@@ -294,7 +303,6 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
this.conn = null;
}
}
-
return connection;
}
@@ -1222,12 +1230,12 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
if (cmd.containsKey(PulseConstants.COMPOSITE_DATA_KEY_CONNECTED)){
client.setConnected((Boolean) cmd.get(PulseConstants.COMPOSITE_DATA_KEY_CONNECTED));
}
- if (cmd.containsKey(PulseConstants.COMPOSITE_DATA_KEY_CLIENTCQCOUNT)){
- client.setClientCQCount((Integer) cmd.get(PulseConstants.COMPOSITE_DATA_KEY_CLIENTCQCOUNT));
- }
- if (cmd.containsKey(PulseConstants.COMPOSITE_DATA_KEY_SUBSCRIPTIONENABLED)){
- client.setSubscriptionEnabled((Boolean) cmd.get(PulseConstants.COMPOSITE_DATA_KEY_SUBSCRIPTIONENABLED));
- }
+ if (cmd.containsKey(PulseConstants.COMPOSITE_DATA_KEY_CLIENTCQCOUNT)){
+ client.setClientCQCount((Integer) cmd.get(PulseConstants.COMPOSITE_DATA_KEY_CLIENTCQCOUNT));
+ }
+ if (cmd.containsKey(PulseConstants.COMPOSITE_DATA_KEY_SUBSCRIPTIONENABLED)){
+ client.setSubscriptionEnabled((Boolean) cmd.get(PulseConstants.COMPOSITE_DATA_KEY_SUBSCRIPTIONENABLED));
+ }
memberClientsHM.put(client.getId(), client);
}
existingMember.updateMemberClientsHMap(memberClientsHM);
@@ -1602,7 +1610,7 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
LOGGER.warning(infe);
} catch (ReflectionException re) {
LOGGER.warning(re);
- }
+ }
}
private static boolean isQuoted(String value) {
@@ -2184,6 +2192,11 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
Cluster.Member member = cluster.getMembersHMap().get(memberName);
+ //Following attributes are not present in 9.0
+ //"Members"
+ //"EmptyNodes"
+ //"SystemRegionEntryCount"
+ //"MemberCount"
AttributeList attributeList = this.mbs.getAttributes(mbeanName,
PulseConstants.REGION_MBEAN_ATTRIBUTES);
@@ -2301,7 +2314,7 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
region.setDiskSynchronous(false);
//LOGGER.warning("Some of the Pulse elements are not available currently. There might be a GemFire upgrade going on.");
}
-
+
// Remove deleted regions from member's regions list
for (Iterator<String> it = cluster.getDeletedRegions().iterator(); it
@@ -2316,7 +2329,7 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
LOGGER.warning(infe);
} catch (ReflectionException re) {
LOGGER.warning(re);
- }
+ }
}
/**
@@ -2450,5 +2463,4 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
return gemfireVersion;
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/PulseConstants.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/PulseConstants.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/PulseConstants.java
index c2999f8..b06d2e5 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/PulseConstants.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/PulseConstants.java
@@ -101,6 +101,9 @@ public class PulseConstants {
public static final String APPLICATION_PROPERTY_PULSE_LOGLEVEL = "pulse.Log-Level";
public static final String APPLICATION_PROPERTY_PULSE_LOGAPPEND = "pulse.Log-Append";
public static final String APPLICATION_PROPERTY_PULSE_PRODUCTSUPPORT = "pulse.product";
+ public static final String APPLICATION_PROPERTY_PULSE_SEC_PROFILE_GEMFIRE = "pulse.authentication.gemfire";
+ public static final String APPLICATION_PROPERTY_PULSE_SEC_PROFILE_DEFAULT = "pulse.authentication.default";
+ public static final String APPLICATION_PROPERTY_PULSE_SPRING_PROFILE_KEY = "spring.profiles.default";
// STRING FLAGS
public static final String STRING_FLAG_TRUE = "true";
@@ -124,6 +127,7 @@ public class PulseConstants {
public static final String OBJECT_NAME_TABLE_AGGREGATE_PATTERN = OBJECT_DOMAIN_NAME_SQLFIRE + ":service=Table,type=Aggregate,table=";
public static final String OBJECT_NAME_REGION_ON_MEMBER_REGION = OBJECT_DOMAIN_NAME_GEMFIRE + ":service=Region,name=";
public static final String OBJECT_NAME_REGION_ON_MEMBER_MEMBER = ",type=Member,member=";
+ public static final String OBJECT_NAME_ACCESSCONTROL_MBEAN = "GemFire:service=AccessControl,type=Distributed";
public static final String MBEAN_KEY_PROPERTY_SERVICE = "service";
public static final String MBEAN_KEY_PROPERTY_SERVICE_VALUE_REGION = "Region";
@@ -314,6 +318,11 @@ public class PulseConstants {
public static final String PRODUCT_NAME_GEMFIRE = "gemfire"; // For GemFire
public static final String PRODUCT_NAME_SQLFIRE = "gemfirexd"; // For SQLFire
+ //Following attributes are not present in 9.0
+ //"Members"
+ //"EmptyNodes"
+ //"SystemRegionEntryCount"
+ //"MemberCount"
public static final String[] REGION_MBEAN_ATTRIBUTES = {
MBEAN_ATTRIBUTE_MEMBERS, MBEAN_ATTRIBUTE_FULLPATH,
MBEAN_ATTRIBUTE_DISKREADSRATE, MBEAN_ATTRIBUTE_DISKWRITESRATE,
@@ -403,6 +412,14 @@ public class PulseConstants {
public static final String[] SF_TABLE_MBEAN_ATTRIBUTES = {
MBEAN_ATTRIBUTE_ENTRYSIZE, MBEAN_ATTRIBUTE_NUMBEROFROWS };
+
+ public static final String PULSE_ROLES[] = {
+ "PULSE_DASHBOARD",
+ "PULSE_DATABROWSER",
+ "PULSE_WEBGFSH",
+ "PULSE_ADMIN_V1",
+ "PULSE_ADMIN_V2"
+ };
// SSL Related attributes
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Repository.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Repository.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Repository.java
index 0dee7da..a11167e 100644
--- a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Repository.java
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/data/Repository.java
@@ -19,14 +19,14 @@
package com.vmware.gemfire.tools.pulse.internal.data;
+import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
+
import java.net.ConnectException;
import java.util.HashMap;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Map;
+import java.util.ResourceBundle;
/**
* A Singleton instance of the memory cache for clusters.
@@ -47,6 +47,7 @@ public class Repository {
private Boolean isEmbeddedMode;
private boolean useSSLLocator = false;
private boolean useSSLManager = false;
+ private boolean useGemFireCredentials = false;
private String pulseWebAppUrl;
@@ -212,4 +213,14 @@ public class Repository {
return this.resourceBundle;
}
+ public boolean isUseGemFireCredentials() {
+ return useGemFireCredentials;
+ }
+
+ public void setUseGemFireCredentials(boolean useGemFireCredentials) {
+ this.useGemFireCredentials = useGemFireCredentials;
+ }
+
+
+
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthentication.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthentication.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthentication.java
new file mode 100644
index 0000000..99dcc15
--- /dev/null
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthentication.java
@@ -0,0 +1,156 @@
+/*
+ * 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.vmware.gemfire.tools.pulse.internal.security;
+
+import com.vmware.gemfire.tools.pulse.internal.data.PulseConstants;
+import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServerConnection;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.remote.JMXConnector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Spring security authentication object for GemFire
+ *
+ * To use GemFire Integrated Security Model set Spring Application Profile to pulse.authentication.gemfire
+ *
+ * 1. Authentication :
+ * 1.a GemFire profile creates JMX connection with given credentials at the login time.
+ * 1.b Successful connect is considered as Successful Authentication for Pulse WebApp
+ *
+ *
+ * 2. Authorization :
+ * 2.a Using newly created authenticated connection AccessControlMXBean is called to get authentication
+ * levels. See @See {@link #populateAuthorities(JMXConnector)}. This sets Spring Security Authorities
+ * 2.b DataBrowser end-points are required to be authorized against Spring Granted Authority
+ * @See spring-security.xml
+ * 2.c When executing Data-Browser query, user-level jmx connection is used so at to put access-control
+ * over the resources query is accessing.
+ * @See #com.vmware.gemfire.tools.pulse.internal.data.JMXDataUpdater#executeQuery
+ *
+ * 3. Connection Management - Spring Security LogoutHandler closes session level connection
+ *
+ * TODO : Better model would be to maintain background connection map for Databrowser instead
+ * of each web session creating rmi connection and map user to correct entry in the connection map
+ *
+ * @author Tushar Khairnar
+ * @since version 9.0
+ */
+public class GemFireAuthentication extends UsernamePasswordAuthenticationToken {
+
+ private final static PulseLogWriter LOGGER = PulseLogWriter.getLogger();
+
+ private JMXConnector jmxc=null;
+
+ public GemFireAuthentication(Object principal, Object credentials, Collection<GrantedAuthority> list, JMXConnector jmxc) {
+ super(principal, credentials, list);
+ this.jmxc = jmxc;
+ }
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
+
+ public void closeJMXConnection(){
+ try {
+ jmxc.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MBeanServerConnection getRemoteMBeanServer() {
+ try {
+ return jmxc.getMBeanServerConnection();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static boolean authorize(String role){
+ try {
+ GemFireAuthentication authentication = (GemFireAuthentication) SecurityContextHolder
+ .getContext().getAuthentication();
+ MBeanServerConnection mbeanServer = authentication
+ .getRemoteMBeanServer();
+ LOGGER.fine("#GemFireAuthentication : Checking for role="+role);
+ ObjectName name = new ObjectName(PulseConstants.OBJECT_NAME_ACCESSCONTROL_MBEAN);
+ Object[] params = new Object[] {role};
+ String[] signature = new String[] {String.class.getCanonicalName()};
+ Boolean result = (Boolean)mbeanServer.invoke(name, "authorize", params, signature);
+ return result;
+ } catch (MalformedObjectNameException e) {
+ throw new RuntimeException(e);
+ } catch (InstanceNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (MBeanException e) {
+ throw new RuntimeException(e);
+ } catch (ReflectionException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static ArrayList<GrantedAuthority> populateAuthorities(JMXConnector jmxc) {
+ ObjectName name;
+ try {
+ name = new ObjectName(PulseConstants.OBJECT_NAME_ACCESSCONTROL_MBEAN);
+ MBeanServerConnection mbeanServer = jmxc.getMBeanServerConnection();
+ ArrayList<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+ authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
+ for(String role : PulseConstants.PULSE_ROLES){
+ Object[] params = new Object[] {role};
+ String[] signature = new String[] {String.class.getCanonicalName()};
+ boolean result = (Boolean)mbeanServer.invoke(name, "authorize", params, signature);
+ if(result){
+ //spring sec require ROLE_ prefix
+ authorities.add(new SimpleGrantedAuthority("ROLE_"+role));
+ }
+ }
+ return authorities;
+ } catch (MalformedObjectNameException e) {
+ throw new RuntimeException(e);
+ } catch (InstanceNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (MBeanException e) {
+ throw new RuntimeException(e);
+ } catch (ReflectionException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public JMXConnector getJmxc() {
+ return jmxc;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthenticationProvider.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthenticationProvider.java
new file mode 100644
index 0000000..d98bba8
--- /dev/null
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/GemFireAuthenticationProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.vmware.gemfire.tools.pulse.internal.security;
+
+import com.vmware.gemfire.tools.pulse.internal.data.Repository;
+import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+
+import javax.management.remote.JMXConnector;
+import java.util.Collection;
+
+/**
+ * Spring security AuthenticationProvider for GemFire. It connects to
+ * gemfire manager using given credentials. Successful connect is treated
+ * as successful authentication and web user is authenticated
+ *
+ * @author Tushar Khairnar
+ * @since version 9.0
+ */
+public class GemFireAuthenticationProvider implements AuthenticationProvider {
+
+ private final static PulseLogWriter LOGGER = PulseLogWriter.getLogger();
+
+ public GemFireAuthenticationProvider(){
+ System.out.println("here");
+ }
+
+ @Override
+ public Authentication authenticate(Authentication authentication)
+ throws AuthenticationException {
+
+ if (authentication instanceof GemFireAuthentication) {
+ GemFireAuthentication gemAuth = (GemFireAuthentication) authentication;
+ LOGGER.fine("GemAuthentication is connected? = "
+ + gemAuth.getJmxc());
+ if(gemAuth.getJmxc()!=null && gemAuth.isAuthenticated())
+ return gemAuth;
+ }
+
+ String name = authentication.getName();
+ String password = authentication.getCredentials().toString();
+
+ try {
+ LOGGER.fine("Connecting to GemFire with user=" + name);
+ JMXConnector jmxc = Repository.get().getCluster().connectToGemFire(name, password);
+ if(jmxc!=null) {
+ Collection<GrantedAuthority> list = GemFireAuthentication.populateAuthorities(jmxc);
+ GemFireAuthentication auth = new GemFireAuthentication(
+ authentication.getPrincipal(),
+ authentication.getCredentials(), list, jmxc);
+ LOGGER.fine("For user " + name + " authList="+ list);
+ return auth;
+ } else
+ throw new AuthenticationServiceException("JMX Connection unavailable");
+ } catch (Exception e) {
+ throw new BadCredentialsException("Error connecting to GemFire JMX Server", e);
+ }
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return authentication.equals(UsernamePasswordAuthenticationToken.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/LogoutHandler.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/LogoutHandler.java b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/LogoutHandler.java
new file mode 100644
index 0000000..a70925d
--- /dev/null
+++ b/geode-pulse/src/main/java/com/vmware/gemfire/tools/pulse/internal/security/LogoutHandler.java
@@ -0,0 +1,55 @@
+/*
+ * 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.vmware.gemfire.tools.pulse.internal.security;
+
+import com.vmware.gemfire.tools.pulse.internal.data.Repository;
+import com.vmware.gemfire.tools.pulse.internal.log.PulseLogWriter;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Handler is used to close jmx connection maintained at user-level
+ * @author tushark
+ *
+ */
+public class LogoutHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
+
+ public LogoutHandler(String defaultTargetURL) {
+ this.setDefaultTargetUrl(defaultTargetURL);
+ }
+
+ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+ throws IOException, ServletException {
+ PulseLogWriter LOGGER = PulseLogWriter.getLogger();
+ LOGGER.fine("Invoked #LogoutHandler ...");
+ if (Repository.get().isUseGemFireCredentials()) {
+ GemFireAuthentication gemauthentication = (GemFireAuthentication) authentication;
+ if(gemauthentication!=null) {
+ gemauthentication.getJmxc().close();
+ LOGGER.info("#LogoutHandler : Closing GemFireAuthentication JMX Connection...");
+ }
+ }
+ super.onLogoutSuccess(request, response, authentication);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/resources/pulse.properties
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/resources/pulse.properties b/geode-pulse/src/main/resources/pulse.properties
index 439e4b8..878bc68 100644
--- a/geode-pulse/src/main/resources/pulse.properties
+++ b/geode-pulse/src/main/resources/pulse.properties
@@ -21,11 +21,9 @@
#Tue, 09 Oct 2012 16:39:00
# JMX Locator/Manager Properties
-#pulse.useLocator=true
-#pulse.host=SachinK.clarice.com
-#pulse.useLocator=true
-#pulse.host=pnq-pratik.vmware.com
-#pulse.port=10334
+pulse.useLocator=false
+pulse.host=localhost
+pulse.port=1099
pulse.useLocator=false
pulse.host=localhost
@@ -35,8 +33,8 @@ pulse.port=9999
#pulse.useSSL.manager=true
# JMX User Properties
-pulse.jmxUserName=controlRole
-pulse.jmxUserPassword=R&D
+pulse.jmxUserName=admin
+pulse.jmxUserPassword=admin
# Logging Configurations Properties
pulse.Log-File-Name=PULSELOG
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml b/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
index 85de9f1..5ff1f31 100644
--- a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
+++ b/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
@@ -26,32 +26,41 @@
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <http auto-config="true">
+ <http auto-config="true" use-expressions="true">
<!-- Can be invoked w/o auth -->
- <intercept-url pattern="/Login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
- <intercept-url pattern="/pulse/pulseVersion" access="IS_AUTHENTICATED_ANONYMOUSLY" />
- <intercept-url pattern="/pulse/authenticateUser" access="IS_AUTHENTICATED_ANONYMOUSLY" />
- <intercept-url pattern="/pulse/pulseProductSupport" access="IS_AUTHENTICATED_ANONYMOUSLY" />
+ <intercept-url pattern="/Login.html" access="permitAll" />
+ <intercept-url pattern="/pulse/pulseVersion" access="permitAll" />
+ <intercept-url pattern="/pulse/authenticateUser" access="permitAll" />
+ <intercept-url pattern="/pulse/pulseProductSupport" access="permitAll" />
<!-- Can be invoked w/o auth -->
+ <!-- Restricted urls -->
+ <intercept-url pattern="/DataBrowser.html" access="hasRole('ROLE_PULSE_DASHBOARD') and hasRole('ROLE_PULSE_DATABROWSER')" />
+ <intercept-url pattern="/clusterDetail.html" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <intercept-url pattern="/MemberDetails.html" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <intercept-url pattern="/regionDetail.html" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <intercept-url pattern="/pulse/*" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <intercept-url pattern="/clearAlerts" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <intercept-url pattern="/acknowledgeAlert" access="hasRole('ROLE_PULSE_DASHBOARD')" />
+ <!-- /dataBrowserRegions, /dataBrowserQuery, /dataBrowserQueryHistory, /dataBrowserExport -->
+ <intercept-url pattern="/dataBrowser*" access="hasRole('ROLE_PULSE_DASHBOARD') and hasRole('ROLE_PULSE_DATABROWSER')" />
+ <intercept-url pattern="/getQueryStatisticsGridModel/*" access="hasRole('ROLE_PULSE_DASHBOARD') and hasRole('ROLE_PULSE_DATABROWSER')" />
+
<!-- Restricted urls -->
- <!-- Hide Data Browser tab for Pulse-Cheetah Release -->
- <!-- <intercept-url pattern="/DataBrowser.html" access="ROLE_RESTRICTED" /> -->
- <!-- Restricted urls -->
-
- <!-- Can be invoked only with auth -->
- <intercept-url pattern="/*.html" access="ROLE_USER,ROLE_GEMFIRETESTING,ROLE_PULSEUSER" />
- <intercept-url pattern="/pulse/*" access="ROLE_USER,ROLE_GEMFIRETESTING,ROLE_PULSEUSER" />
- <!-- Can be invoked only with auth -->
-
<form-login login-page="/Login.html"
authentication-failure-handler-ref="authenticationFailureHandler"
default-target-url="/clusterDetail.html" />
-
- <logout logout-url="/pulse/clusterLogout" logout-success-url="/Login.html" />
+
+ <logout logout-url="/pulse/clusterLogout" success-handler-ref="customLogoutSuccessHandler"/>
+
</http>
+ <beans:bean name="customLogoutSuccessHandler"
+ class="com.vmware.gemfire.tools.pulse.internal.security.LogoutHandler">
+ <beans:constructor-arg value="/Login.html"/>
+ </beans:bean>
+
<beans:bean id="authenticationFailureHandler"
class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="exceptionMappings">
@@ -63,21 +72,33 @@
</beans:props>
</beans:property>
</beans:bean>
+
+ <beans:bean id="gemAuthenticationProvider"
+ class="com.vmware.gemfire.tools.pulse.internal.security.GemFireAuthenticationProvider">
+ </beans:bean>
- <!-- Default user authentication based on in-memory user service -->
+
+ <!-- Default user authentication -->
<beans:beans profile="pulse.authentication.default">
<authentication-manager>
<authentication-provider>
<user-service>
- <user name="admin" password="admin" authorities="ROLE_USER" />
+ <user name="admin" password="admin" authorities="ROLE_USER,ROLE_PULSE_DASHBOARD,ROLE_PULSE_DATABROWSER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
+
+ <!-- Default user authentication based on gemfire integrated security -->
+ <beans:beans profile="pulse.authentication.gemfire">
+ <authentication-manager alias="authenticationManager">
+ <authentication-provider ref="gemAuthenticationProvider"/>
+ </authentication-manager>
+ </beans:beans>
<!-- Custom user authentication specified externally -->
<beans:beans profile="pulse.authentication.custom">
<beans:import resource="classpath:pulse-authentication-custom.xml" />
</beans:beans>
-
+
</beans:beans>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/PulseTest.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/PulseTest.java b/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/PulseTest.java
index c5ece20..d65d893 100644
--- a/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/PulseTest.java
+++ b/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/PulseTest.java
@@ -137,6 +137,8 @@ public class PulseTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
+ System.setProperty("spring.profiles.active", "pulse.authentication.gemfire");
+
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
jmxPropertiesFile = classLoader.getResource("test.properties").getPath();
path = getPulseWarPath();
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/386ace7c/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/Server.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/Server.java b/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/Server.java
index 02c7e3a..d84d0df 100644
--- a/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/Server.java
+++ b/geode-pulse/src/test/java/com/vmware/gemfire/tools/pulse/tests/Server.java
@@ -18,14 +18,12 @@
*/
package com.vmware.gemfire.tools.pulse.tests;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.management.internal.security.JSONAuthorization;
+import com.gemstone.gemfire.management.internal.security.MBeanServerWrapper;
+import com.gemstone.gemfire.management.internal.security.ManagementInterceptor;
import com.vmware.gemfire.tools.pulse.internal.data.PulseConstants;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Set;
+import org.json.JSONException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
@@ -37,6 +35,13 @@ import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Properties;
+import java.util.Set;
public class Server {
private static final String DEFAULT_HOST = "127.0.0.1"; //"localhost"
@@ -46,8 +51,20 @@ public class Server {
private final JMXConnectorServer cs;
private String propFile = null;
- public Server(int port, String properties) throws IOException {
+ public Server(int port, String properties, boolean secure) throws IOException, JSONException {
+ Properties props = new Properties();
+ props.put(DistributionConfig.SECURITY_CLIENT_AUTHENTICATOR_NAME, JSONAuthorization.class.getName() + ".create");
+ props.put(DistributionConfig.SECURITY_CLIENT_ACCESSOR_NAME, JSONAuthorization.class.getName() + ".create");
+ JSONAuthorization.setUpWithJsonFile("cacheServer.json");
+ ManagementInterceptor interceptor = new ManagementInterceptor(props);
+ MBeanServerWrapper wrapper = new MBeanServerWrapper(interceptor);
+
+ if(secure){
+ //System.setProperty(JMXConnectorServer.AUTHENTICATOR, interceptor);
+ }
+
try {
+
java.rmi.registry.LocateRegistry.createRegistry(port);
System.out.println("RMI registry ready.");
} catch (Exception e) {
@@ -60,6 +77,10 @@ public class Server {
url = new JMXServiceURL(formJMXServiceURLString(DEFAULT_HOST, "" + port));
cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ if(secure) {
+ cs.setMBeanServerForwarder(wrapper);
+ }
+
cs.start();
loadMBeans();
@@ -242,7 +263,7 @@ public class Server {
throws MalformedObjectNameException {
Server s = null;
try {
- s = new Server(port, properties);
+ s = new Server(port, properties, true);
} catch (Exception e) {
e.printStackTrace();
return null;