You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2015/01/12 09:07:15 UTC

git commit: updated refs/heads/4.5 to b2b4962

Repository: cloudstack
Updated Branches:
  refs/heads/4.5 1e8476d38 -> b2b496288


CLOUDSTACK-8034: Hash user IDs for SAML authentication

The User table's UUID column is restricted to 40 chars only, since we don't
know how long the nameID/userID of a SAML authenticated user will be - the fix
hashes that user ID and takes a substring of length 40 chars. For hashing,
SHA256 is used which returns a 64 char length string.

- Fix tests, add test cases
- Improve checkSAMLUser method
- Use SHA256 one way hashing to create unique UUID for SAML users

Signed-off-by: Rohit Yadav <ro...@shapeblue.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b2b49628
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b2b49628
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b2b49628

Branch: refs/heads/4.5
Commit: b2b496288d164fead2c089fb48319e1988b03ce8
Parents: 1e8476d
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Mon Jan 12 13:33:57 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Mon Jan 12 13:33:57 2015 +0530

----------------------------------------------------------------------
 .../cloudstack/saml/SAML2UserAuthenticator.java |  2 +-
 .../cloudstack/SAML2UserAuthenticatorTest.java  | 26 +++++++++++++++-----
 .../apache/cloudstack/utils/auth/SAMLUtils.java | 18 ++++++++++----
 .../cloudstack/utils/auth/SAMLUtilsTest.java    | 10 ++++++--
 4 files changed, 42 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b2b49628/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2UserAuthenticator.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2UserAuthenticator.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2UserAuthenticator.java
index e623fc2..31a93a4 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2UserAuthenticator.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2UserAuthenticator.java
@@ -48,7 +48,7 @@ public class SAML2UserAuthenticator extends DefaultUserAuthenticator {
             return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
         } else {
             User user = _userDao.getUser(userAccount.getId());
-            if (user != null && SAMLUtils.checkSAMLUserId(user.getUuid()) &&
+            if (user != null && SAMLUtils.checkSAMLUser(user.getUuid(), username) &&
                     requestParameters != null && requestParameters.containsKey(SAMLUtils.SAML_RESPONSE)) {
                 return new Pair<Boolean, ActionOnFailedAuthentication>(true, null);
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b2b49628/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2UserAuthenticatorTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2UserAuthenticatorTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2UserAuthenticatorTest.java
index 29fb496..83792c6 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2UserAuthenticatorTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2UserAuthenticatorTest.java
@@ -73,14 +73,28 @@ public class SAML2UserAuthenticatorTest {
         Mockito.when(userAccountDao.getUserAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(account);
         Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user);
 
+        Pair<Boolean, ActionOnFailedAuthentication> pair;
+        Map<String, Object[]> params = new HashMap<String, Object[]>();
+
         // When there is no SAMLRequest in params
-        Pair<Boolean, ActionOnFailedAuthentication> pair1 = authenticator.authenticate(SAMLUtils.createSAMLId("user1234"), "random", 1l, null);
-        Assert.assertFalse(pair1.first());
+        pair = authenticator.authenticate("someUID", "random", 1l, params);
+        Assert.assertFalse(pair.first());
 
-        // When there is SAMLRequest in params
-        Map<String, Object[]> params = new HashMap<String, Object[]>();
+        // When there is SAMLRequest in params and user is same as the mocked one
         params.put(SAMLUtils.SAML_RESPONSE, new Object[]{});
-        Pair<Boolean, ActionOnFailedAuthentication> pair2 = authenticator.authenticate(SAMLUtils.createSAMLId("user1234"), "random", 1l, params);
-        Assert.assertTrue(pair2.first());
+        pair = authenticator.authenticate("someUID", "random", 1l, params);
+        Assert.assertTrue(pair.first());
+
+        // When there is SAMLRequest in params but username is null
+        pair = authenticator.authenticate(null, "random", 1l, params);
+        Assert.assertFalse(pair.first());
+
+        // When there is SAMLRequest in params but username is empty
+        pair = authenticator.authenticate("", "random", 1l, params);
+        Assert.assertFalse(pair.first());
+
+        // When there is SAMLRequest in params but username is not valid
+        pair = authenticator.authenticate("someOtherUID", "random", 1l, params);
+        Assert.assertFalse(pair.first());
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b2b49628/utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java
----------------------------------------------------------------------
diff --git a/utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java b/utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java
index d129309..dbd2d6f 100644
--- a/utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java
+++ b/utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java
@@ -20,6 +20,7 @@
 package org.apache.cloudstack.utils.auth;
 
 import com.cloud.utils.HttpUtils;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.log4j.Logger;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.x509.X509V1CertificateGenerator;
@@ -96,18 +97,25 @@ public class SAMLUtils {
     public static final Logger s_logger = Logger.getLogger(SAMLUtils.class);
 
     public static final String SAML_RESPONSE = "SAMLResponse";
-    public static final String SAML_NS = "saml://";
+    public static final String SAML_NS = "SAML-";
     public static final String SAML_NAMEID = "SAML_NAMEID";
     public static final String SAML_SESSION = "SAML_SESSION";
     public static final String CERTIFICATE_NAME = "SAMLSP_CERTIFICATE";
 
     public static String createSAMLId(String uid) {
-        String samlUuid = SAML_NS + uid;
-        return samlUuid.length() > 40 ? samlUuid.substring(0, 40) : samlUuid;
+        if (uid == null)  {
+            return null;
+        }
+        String hash = DigestUtils.sha256Hex(uid);
+        String samlUuid = SAML_NS + hash;
+        return samlUuid.substring(0, 40);
     }
 
-    public static Boolean checkSAMLUserId(String uuid) {
-        return uuid.startsWith(SAML_NS);
+    public static boolean checkSAMLUser(String uuid, String username) {
+        if (uuid == null || uuid.isEmpty() || username == null || username.isEmpty()) {
+            return false;
+        }
+        return uuid.startsWith(SAML_NS) && createSAMLId(username).equals(uuid);
     }
 
     public static String generateSecureRandomId() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b2b49628/utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java
----------------------------------------------------------------------
diff --git a/utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java b/utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java
index 85be2ef..bebfd13 100644
--- a/utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java
+++ b/utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java
@@ -34,8 +34,14 @@ public class SAMLUtilsTest extends TestCase {
 
     @Test
     public void testSAMLId() throws Exception {
-        assertTrue(SAMLUtils.checkSAMLUserId(SAMLUtils.createSAMLId("someUID")));
-        assertFalse(SAMLUtils.checkSAMLUserId("randomUID"));
+        assertEquals(SAMLUtils.createSAMLId(null), null);
+        assertEquals(SAMLUtils.createSAMLId("someUserName"), "SAML-305e19dd2581f33fd90b3949298ec8b17de");
+
+        assertTrue(SAMLUtils.checkSAMLUser(SAMLUtils.createSAMLId("someUserName"), "someUserName"));
+        assertFalse(SAMLUtils.checkSAMLUser(SAMLUtils.createSAMLId("someUserName"), "someOtherUserName"));
+        assertFalse(SAMLUtils.checkSAMLUser(SAMLUtils.createSAMLId(null), "someOtherUserName"));
+        assertFalse(SAMLUtils.checkSAMLUser("randomUID", "randomUID"));
+        assertFalse(SAMLUtils.checkSAMLUser(null, null));
     }
 
     @Test