GEODE-77: Implement Authenticator interface in class GMSAuthenticator with unit 
tests.


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

Branch: refs/heads/feature/GEODE-77
Commit: 0a70d5140277b366be4d0b9607a5e68936837c2f
Parents: 52f8ce6
Author: Qihong Chen <qc...@pivotal.io>
Authored: Thu Aug 13 09:55:33 2015 -0700
Committer: Qihong Chen <qc...@pivotal.io>
Committed: Thu Aug 13 09:55:33 2015 -0700

----------------------------------------------------------------------
 .../internal/InternalDistributedSystem.java     |    1 +
 .../internal/membership/gms/Services.java       |   22 +-
 .../membership/gms/auth/GMSAuthenticator.java   |  155 +-
 .../gms/interfaces/Authenticator.java           |    2 +-
 .../membership/gms/membership/GMSJoinLeave.java | 2356 +++++++++---------
 .../gemfire/internal/i18n/LocalizedStrings.java |    9 +-
 .../gms/auth/GMSAuthenticatorJUnitTest.java     |  300 +++
 7 files changed, 1651 insertions(+), 1194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/0a70d514/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java
----------------------------------------------------------------------
diff --git 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java
 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java
index d03f558..8a4e20a 100644
--- 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java
+++ 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java
@@ -564,6 +564,7 @@ public final class InternalDistributedSystem
       this.securityLogWriter.fine("SecurityLogWriter is created.");
     }
     
+    Services.setLogWriter(this.logWriter);
     Services.setSecurityLogWriter(this.securityLogWriter);
 
     this.clock = new DSClock(this.isLoner);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/0a70d514/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/Services.java
----------------------------------------------------------------------
diff --git 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/Services.java
 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/Services.java
index 79830b9..8a27cf0 100755
--- 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/Services.java
+++ 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/Services.java
@@ -36,6 +36,7 @@ public class Services {
 
   private static final ThreadGroup threadGroup = 
LoggingThreadGroup.createThreadGroup("Membership", logger); 
   
+  private static InternalLogWriter staticLogWriter;
   private static InternalLogWriter staticSecurityLogWriter;
 
   final private Manager manager;
@@ -48,6 +49,7 @@ public class Services {
   final private DMStats stats;
   final private Stopper cancelCriterion;
 
+  private InternalLogWriter logWriter;
   private InternalLogWriter securityLogWriter;
   
   private Timer timer = new Timer("Membership Timer", true);
@@ -95,6 +97,8 @@ public class Services {
     // TODO fix this so that IDS doesn't know about Services
     securityLogWriter = staticSecurityLogWriter;
     staticSecurityLogWriter = null;
+    logWriter = staticLogWriter;
+    staticLogWriter = null;
     this.auth.init(this);
     this.messenger.init(this);
     this.manager.init(this);
@@ -154,12 +158,20 @@ public class Services {
     this.manager.stop();
     this.timer.cancel();
   }
-  
-  public static void setSecurityLogWriter(InternalLogWriter writer) {
-    staticSecurityLogWriter = writer;
+
+  public static void setLogWriter(InternalLogWriter writer) {
+    staticLogWriter = writer;
   }
-  
-  public LogWriter getSecurityLogWriter() {
+
+  public static void setSecurityLogWriter(InternalLogWriter securityWriter) {
+    staticSecurityLogWriter = securityWriter;
+  }
+
+  public InternalLogWriter getLogWriter() {
+    return this.logWriter;
+  }
+
+  public InternalLogWriter getSecurityLogWriter() {
     return this.securityLogWriter;
   }
   

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/0a70d514/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/auth/GMSAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/auth/GMSAuthenticator.java
 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/auth/GMSAuthenticator.java
index c008171..7e7072d 100755
--- 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/auth/GMSAuthenticator.java
+++ 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/auth/GMSAuthenticator.java
@@ -1,17 +1,42 @@
 package com.gemstone.gemfire.distributed.internal.membership.gms.auth;
 
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.distributed.DistributedMember;
 import 
com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
 import com.gemstone.gemfire.distributed.internal.membership.NetView;
 import com.gemstone.gemfire.distributed.internal.membership.gms.Services;
 import 
com.gemstone.gemfire.distributed.internal.membership.gms.interfaces.Authenticator;
+import com.gemstone.gemfire.internal.ClassLoadUtil;
+import com.gemstone.gemfire.internal.logging.InternalLogWriter;
+import com.gemstone.gemfire.security.AuthInitialize;
 import com.gemstone.gemfire.security.AuthenticationFailedException;
+import com.gemstone.gemfire.security.AuthenticationRequiredException;
+import com.gemstone.gemfire.security.GemFireSecurityException;
+
+import java.lang.reflect.Method;
+import java.security.Principal;
+import java.util.Properties;
+import java.util.Set;
+
+// static messages
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.HandShake_AUTHENTICATOR_INSTANCE_COULD_NOT_BE_OBTAINED;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.HandShake_FAILED_TO_ACQUIRE_AUTHENTICATOR_OBJECT;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.HandShake_FAILED_TO_ACQUIRE_AUTHINITIALIZE_METHOD_0;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.AUTH_PEER_AUTHENTICATION_FAILED_WITH_EXCEPTION;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.AUTH_PEER_AUTHENTICATION_FAILED;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.AUTH_PEER_AUTHENTICATION_MISSING_CREDENTIALS;
+import static 
com.gemstone.gemfire.internal.i18n.LocalizedStrings.AUTH_FAILED_TO_ACQUIRE_AUTHINITIALIZE_INSTANCE;
+import static 
com.gemstone.gemfire.distributed.internal.DistributionConfig.SECURITY_PEER_AUTH_INIT_NAME;
+import static 
com.gemstone.gemfire.distributed.internal.DistributionConfig.SECURITY_PEER_AUTHENTICATOR_NAME;
+
 
 public class GMSAuthenticator implements Authenticator {
 
+  private Services services;
+
   @Override
   public void init(Services s) {
-    // TODO Auto-generated method stub
-
+    this.services = s;
   }
 
   @Override
@@ -62,17 +87,129 @@ public class GMSAuthenticator implements Authenticator {
 
   }
 
+  /**
+   * Authenticate peer member with authenticator class defined by property
+   * "security-peer-authenticator".
+   * @param member the member to be authenticated
+   * @param credentials the credentials used in authentication
+   * @return null if authentication succeed (including no authenticator case),
+   *         otherwise, return failure message
+   * @throws AuthenticationFailedException
+   *         this will be removed since return string is used for failure
+   */
   @Override
-  public String authenticate(InternalDistributedMember m, Object credentials)
-      throws AuthenticationFailedException {
-    // TODO Auto-generated method stub
-    return null;
+  public String authenticate(InternalDistributedMember member, Object 
credentials)
+    throws AuthenticationFailedException {
+    return authenticate(member, credentials, securityProps, 
services.getJoinLeave().getMemberID());
+  }
+
+  // for unit test
+  /* package */ String authenticate(
+      DistributedMember member, Object credentials, Properties secProps, 
DistributedMember localMember)
+    throws AuthenticationFailedException {
+
+    String authMethod = secProps.getProperty(SECURITY_PEER_AUTHENTICATOR_NAME);
+    if (authMethod == null || authMethod.length() == 0) {
+      return null;
+    }
+
+    InternalLogWriter securityLogWriter = services.getSecurityLogWriter();
+    String failMsg = null;
+    if (credentials != null) {
+      try {
+        invokeAuthenticator(authMethod, member, credentials);
+      } catch (Exception ex) {
+        securityLogWriter.warning(
+            AUTH_PEER_AUTHENTICATION_FAILED_WITH_EXCEPTION,
+          new Object[] {member, authMethod, ex.getLocalizedMessage()}, ex);
+        failMsg = 
AUTH_PEER_AUTHENTICATION_FAILED.toLocalizedString(localMember);
+      }
+    } else { // No credentials - need to send failure message
+      securityLogWriter.warning(
+          AUTH_PEER_AUTHENTICATION_MISSING_CREDENTIALS, new Object[] {member, 
authMethod});
+      failMsg = 
AUTH_PEER_AUTHENTICATION_MISSING_CREDENTIALS.toLocalizedString(member, 
authMethod);
+    }
+    return failMsg;
   }
 
+  /* package */ Principal invokeAuthenticator(String authMethod, 
DistributedMember member, Object credentials)
+    throws AuthenticationFailedException {
+    com.gemstone.gemfire.security.Authenticator auth = null;
+    try {
+      Method getter = ClassLoadUtil.methodFromName(authMethod);
+      auth = (com.gemstone.gemfire.security.Authenticator) getter.invoke(null, 
(Object[]) null);
+      if (auth == null)
+        throw new AuthenticationFailedException(
+          
HandShake_AUTHENTICATOR_INSTANCE_COULD_NOT_BE_OBTAINED.toLocalizedString());
+
+      LogWriter logWriter = services.getLogWriter();
+      LogWriter securityLogWriter = services.getSecurityLogWriter();
+      auth.init(securityProps, logWriter, securityLogWriter);
+      return auth.authenticate((Properties) credentials, member);
+    } catch (GemFireSecurityException gse) {
+      throw gse;
+    } catch (Exception ex) {
+      throw new AuthenticationFailedException(
+        HandShake_FAILED_TO_ACQUIRE_AUTHENTICATOR_OBJECT.toLocalizedString(), 
ex);
+    } finally {
+      if (auth != null) auth.close();
+    }
+  }
+
+  /**
+   * Get credential object for the given GemFire distributed member
+   * @param member the target distributed member
+   * @return the credential object
+   */
   @Override
-  public Object getCredentials() {
-    // TODO Auto-generated method stub
-    return null;
+  public Object getCredentials(InternalDistributedMember member) {
+    return getCredentials(member, securityProps);
+  }
+
+  // for unit test
+  /* package */ Properties getCredentials(DistributedMember member, Properties 
secProps) {
+    Properties credentials = null;
+    String authMethod = secProps.getProperty(SECURITY_PEER_AUTH_INIT_NAME);
+    try {
+      if (authMethod != null && authMethod.length() > 0) {
+        Method getter = ClassLoadUtil.methodFromName(authMethod);
+        AuthInitialize auth = (AuthInitialize)getter.invoke(null, (Object[]) 
null);
+        if (auth == null)
+          throw new AuthenticationRequiredException(
+            
AUTH_FAILED_TO_ACQUIRE_AUTHINITIALIZE_INSTANCE.toLocalizedString(authMethod));
+
+        try {
+          LogWriter logWriter = services.getLogWriter();
+          LogWriter securityLogWriter = services.getSecurityLogWriter();
+          auth.init(logWriter, securityLogWriter);
+          credentials = auth.getCredentials(secProps, member, true);
+        } finally {
+          auth.close();
+        }
+      }
+    } catch (GemFireSecurityException gse) {
+      throw gse;
+    } catch (Exception ex) {
+      throw new AuthenticationRequiredException(
+        
HandShake_FAILED_TO_ACQUIRE_AUTHINITIALIZE_METHOD_0.toLocalizedString(authMethod),
 ex);
+    }
+    return credentials;
+  }
+
+  private final static String secPrefix =  "gemfire.sys.security-";
+  private final static int gemfireSysPrefixLen = "gemfire.sys.".length();
+  private Properties securityProps = getSecurityProps();
+
+  Properties getSecurityProps() {
+    Properties props = new Properties();
+    Set keys = System.getProperties().keySet();
+    for (Object key: keys) {
+      String propKey = (String) key;
+      if (propKey.startsWith(secPrefix)) {
+        props.setProperty(propKey.substring(gemfireSysPrefixLen), 
System.getProperty(propKey));
+      }
+    }
+    return props;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/0a70d514/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/interfaces/Authenticator.java
----------------------------------------------------------------------
diff --git 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/interfaces/Authenticator.java
 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/interfaces/Authenticator.java
index fa45ff3..596b265 100755
--- 
a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/interfaces/Authenticator.java
+++ 
b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/interfaces/Authenticator.java
@@ -7,5 +7,5 @@ public interface Authenticator extends Service {
 
   String authenticate(InternalDistributedMember m, Object credentials) throws 
AuthenticationFailedException;
 
-  Object getCredentials();
+  Object getCredentials(InternalDistributedMember m);
 }

Reply via email to