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/06/12 13:48:51 UTC

[1/2] git commit: updated refs/heads/saml-production-grade to ba8b9da

Repository: cloudstack
Updated Branches:
  refs/heads/saml-production-grade f9667b666 -> ba8b9da30 (forced update)


CLOUDSTACK-8539: Add metadata refresh timer task and token expiring

- Fix domain path and save it to saml_tokens
- Expire hour old saml tokens
- Refresh metadata based on timer task
- Fix unit tests

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/f971ac98
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f971ac98
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f971ac98

Branch: refs/heads/saml-production-grade
Commit: f971ac98fddeebd25c9c4408c0e1adfca2439b30
Parents: 138da3c
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Jun 12 14:38:40 2015 +0300
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Jun 12 14:48:35 2015 +0300

----------------------------------------------------------------------
 .../command/SAML2LoginAPIAuthenticatorCmd.java  | 26 ++++-----
 .../cloudstack/saml/SAML2AuthManager.java       |  8 +--
 .../cloudstack/saml/SAML2AuthManagerImpl.java   | 57 ++++++++++++++++----
 .../cloudstack/saml/SAMLPluginConstants.java    |  2 +
 .../cloudstack/saml/SAMLTokenDaoImpl.java       | 20 ++++---
 .../GetServiceProviderMetaDataCmdTest.java      | 16 +++++-
 .../org/apache/cloudstack/SAMLUtilsTest.java    |  1 -
 .../SAML2LoginAPIAuthenticatorCmdTest.java      | 25 +++++++--
 8 files changed, 113 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java
index 0d935ff..60d4050 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java
@@ -18,7 +18,6 @@
 package org.apache.cloudstack.api.command;
 
 import com.cloud.api.response.ApiResponseSerializer;
-import com.cloud.domain.Domain;
 import com.cloud.exception.CloudAuthenticationException;
 import com.cloud.user.Account;
 import com.cloud.user.DomainManager;
@@ -153,6 +152,17 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
                     domainPath = ((String[])params.get(ApiConstants.DOMAIN))[0];
                 }
 
+                if (domainPath != null && !domainPath.isEmpty()) {
+                    if (!domainPath.startsWith("/")) {
+                        domainPath = "/" + domainPath;
+                    }
+                    if (!domainPath.endsWith("/")) {
+                        domainPath = domainPath + "/";
+                    }
+                } else {
+                    domainPath = SAML2AuthManager.SAMLDefaultDomainPath.value();
+                }
+
                 SAMLProviderMetadata spMetadata = _samlAuthManager.getSPMetadata();
                 SAMLProviderMetadata idpMetadata = _samlAuthManager.getIdPMetadata(idpId);
                 if (idpMetadata == null) {
@@ -186,22 +196,8 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
                             params, responseType));
                 }
 
-                String defaultDomainString = SAML2AuthManager.SAMLDefaultDomain.value();
                 String username = null;
                 Long domainId = null;
-                Domain domain = _domainMgr.getDomain(defaultDomainString);
-                if (domain != null) {
-                    domainId = domain.getId();
-                } else {
-                    try {
-                        domainId = Long.parseLong(defaultDomainString);
-                    } catch (NumberFormatException ignore) {
-                    }
-                }
-                if (domainId == null) {
-                    s_logger.error("The default domain ID for SAML users is not set correct, it should be a UUID. ROOT domain will be used.");
-                }
-
                 Issuer issuer = processedSAMLResponse.getIssuer();
                 SAMLProviderMetadata spMetadata = _samlAuthManager.getSPMetadata();
                 SAMLProviderMetadata idpMetadata = _samlAuthManager.getIdPMetadata(issuer.getValue());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManager.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManager.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManager.java
index 164050f..e4397dd 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManager.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManager.java
@@ -55,8 +55,8 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableSe
     public static final ConfigKey<String> SAMLUserAttributeName = new ConfigKey<String>("Advanced", String.class, "saml2.user.attribute", "uid",
             "Attribute name to be looked for in SAML response that will contain the username", true);
 
-    public static final ConfigKey<String> SAMLDefaultDomain = new ConfigKey<String>("Advanced", String.class, "saml2.default.domainid", "1",
-            "The default domain UUID to use if domain information is not found while authenticating users", true);
+    public static final ConfigKey<String> SAMLDefaultDomainPath = new ConfigKey<String>("Advanced", String.class, "saml2.default.domainpath", "/",
+            "The default domain path to use if no domain information is provided on request", true);
 
     public static final ConfigKey<String> SAMLIdentityProviderMetadataURL = new ConfigKey<String>("Advanced", String.class, "saml2.idp.metadata.url", "https://openidp.feide.no/simplesaml/saml2/idp/metadata.php",
             "SAML2 Identity Provider Metadata XML Url", true);
@@ -67,8 +67,8 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableSe
     public static final ConfigKey<String> SAMLSignatureAlgorithm = new ConfigKey<String>("Advanced", String.class, "saml2.sigalg", "SHA1",
             "The algorithm to use to when signing a SAML request. Default is SHA1, allowed algorithms: SHA1, SHA256, SHA384, SHA512", true);
 
-    public static final ConfigKey<Integer> SAMLTimeout = new ConfigKey<Integer>("Advanced", Integer.class, "saml2.timeout", "30000",
-            "SAML2 IDP Metadata Downloading and parsing etc. activity timeout in milliseconds", true);
+    public static final ConfigKey<Integer> SAMLTimeout = new ConfigKey<Integer>("Advanced", Integer.class, "saml2.timeout", "1800",
+            "SAML2 IDP Metadata refresh interval in seconds, minimum value is set to 300", true);
 
     public SAMLProviderMetadata getSPMetadata();
     public SAMLProviderMetadata getIdPMetadata(String entityId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
index b1890e8..146e7a9 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
@@ -33,6 +33,7 @@ import org.apache.cloudstack.framework.config.Configurable;
 import org.apache.cloudstack.framework.security.keystore.KeystoreDao;
 import org.apache.cloudstack.framework.security.keystore.KeystoreVO;
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.httpclient.HttpClient;
 import org.apache.log4j.Logger;
 import org.opensaml.DefaultBootstrap;
 import org.opensaml.common.xml.SAMLConstants;
@@ -80,6 +81,8 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
 
 @Component
 @Local(value = {SAML2AuthManager.class, PluggableAPIAuthenticator.class})
@@ -92,7 +95,9 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage
     private String idpSingleSignOnUrl;
     private String idpSingleLogOutUrl;
 
-    private HTTPMetadataProvider idpMetaDataProvider;
+    private Timer _timer;
+    private int _refreshInterval = SAMLPluginConstants.SAML_REFRESH_INTERVAL;
+    private HTTPMetadataProvider _idpMetaDataProvider;
 
     @Inject
     private KeystoreDao _ksDao;
@@ -117,6 +122,14 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage
         return super.start();
     }
 
+    @Override
+    public boolean stop() {
+        if (_timer != null) {
+            _timer.cancel();
+        }
+        return super.stop();
+    }
+
     private boolean initSP() {
         KeystoreVO keyStoreVO = _ksDao.findByName(SAMLPluginConstants.SAMLSP_KEYPAIR);
         if (keyStoreVO == null) {
@@ -313,22 +326,44 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage
         }
     }
 
+    class MetadataRefreshTask extends TimerTask {
+        @Override
+        public void run() {
+            if (_idpMetaDataProvider == null) {
+                return;
+            }
+            s_logger.debug("Starting SAML IDP Metadata Refresh Task");
+            Map <String, SAMLProviderMetadata> metadataMap = new HashMap<String, SAMLProviderMetadata>();
+            try {
+                discoverAndAddIdp(_idpMetaDataProvider.getMetadata(), metadataMap);
+                _idpMetadataMap = metadataMap;
+                expireTokens();
+                s_logger.debug("Finished refreshing SAML Metadata and expiring old auth tokens");
+            } catch (MetadataProviderException e) {
+                s_logger.warn("SAML Metadata Refresh task failed with exception: " + e.getMessage());
+            }
+
+        }
+    }
+
     private boolean setup() {
         if (!initSP()) {
             s_logger.error("SAML Plugin failed to initialize, please fix the configuration and restart management server");
             return false;
         }
-        String idpMetaDataUrl = SAMLIdentityProviderMetadataURL.value();
-        int tolerance = 30000;
-        tolerance = SAMLTimeout.value();
+        _timer = new Timer();
+        final HttpClient client = new HttpClient();
+        final String idpMetaDataUrl = SAMLIdentityProviderMetadataURL.value();
+        if (SAMLTimeout.value() != null && SAMLTimeout.value() > SAMLPluginConstants.SAML_REFRESH_INTERVAL) {
+            _refreshInterval = SAMLTimeout.value();
+        }
         try {
             DefaultBootstrap.bootstrap();
-            idpMetaDataProvider = new HTTPMetadataProvider(idpMetaDataUrl, tolerance);
-            idpMetaDataProvider.setRequireValidMetadata(true);
-            idpMetaDataProvider.setParserPool(new BasicParserPool());
-            idpMetaDataProvider.initialize();
-            _idpMetadataMap.clear();
-            discoverAndAddIdp(idpMetaDataProvider.getMetadata(), _idpMetadataMap);
+            _idpMetaDataProvider = new HTTPMetadataProvider(_timer, client, idpMetaDataUrl);
+            _idpMetaDataProvider.setRequireValidMetadata(true);
+            _idpMetaDataProvider.setParserPool(new BasicParserPool());
+            _idpMetaDataProvider.initialize();
+            _timer.scheduleAtFixedRate(new MetadataRefreshTask(), 0, _refreshInterval * 1000);
         } catch (MetadataProviderException e) {
             s_logger.error("Unable to read SAML2 IDP MetaData URL, error:" + e.getMessage());
             s_logger.error("SAML2 Authentication may be unavailable");
@@ -464,7 +499,7 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage
                 SAMLServiceProviderOrgName, SAMLServiceProviderOrgUrl,
                 SAMLServiceProviderSingleSignOnURL, SAMLServiceProviderSingleLogOutURL,
                 SAMLCloudStackRedirectionUrl, SAMLUserAttributeName,
-                SAMLDefaultDomain,
+                SAMLDefaultDomainPath,
                 SAMLIdentityProviderMetadataURL, SAMLDefaultIdentityProviderId,
                 SAMLSignatureAlgorithm, SAMLTimeout};
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLPluginConstants.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLPluginConstants.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLPluginConstants.java
index b61e405..dfd8447 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLPluginConstants.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLPluginConstants.java
@@ -19,6 +19,8 @@
 package org.apache.cloudstack.saml;
 
 public class SAMLPluginConstants {
+    public static final int SAML_REFRESH_INTERVAL = 300;
+
     public static final String SAML_RESPONSE = "SAMLResponse";
     public static final String SAML_IDPID = "SAML_IDPID";
     public static final String SAML_SESSIONID = "SAML_SESSIONID";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLTokenDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLTokenDaoImpl.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLTokenDaoImpl.java
index d6fb938..eb106d9 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLTokenDaoImpl.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLTokenDaoImpl.java
@@ -18,10 +18,12 @@ package org.apache.cloudstack.saml;
 
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.exception.CloudRuntimeException;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.PostConstruct;
 import javax.ejb.Local;
+import java.sql.PreparedStatement;
 
 @DB
 @Component
@@ -32,12 +34,18 @@ public class SAMLTokenDaoImpl extends GenericDaoBase<SAMLTokenVO, Long> implemen
         super();
     }
 
-    @PostConstruct
-    protected void init() {
-    }
-
     @Override
     public void expireTokens() {
-        // TODO: implement delete all from token where timestamp is older than certain thresholds
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+        try {
+            txn.start();
+            String sql = "DELETE FROM `saml_token` WHERE `created` < (NOW() - INTERVAL 1 HOUR)";
+            PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql);
+            pstmt.executeUpdate();
+            txn.commit();
+        } catch (Exception e) {
+            txn.rollback();
+            throw new CloudRuntimeException("Unable to flush old SAML tokens due to exception", e);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
index 32d0fba..5b4d552 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
@@ -24,11 +24,13 @@ import org.apache.cloudstack.api.ApiServerService;
 import org.apache.cloudstack.api.auth.APIAuthenticationType;
 import org.apache.cloudstack.api.command.GetServiceProviderMetaDataCmd;
 import org.apache.cloudstack.saml.SAML2AuthManager;
+import org.apache.cloudstack.saml.SAMLProviderMetadata;
 import org.apache.cloudstack.saml.SAMLUtils;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 
 import javax.servlet.http.HttpServletRequest;
@@ -36,6 +38,7 @@ import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import java.lang.reflect.Field;
 import java.security.InvalidKeyException;
+import java.security.KeyPair;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.SignatureException;
@@ -75,7 +78,18 @@ public class GetServiceProviderMetaDataCmdTest {
 
         String spId = "someSPID";
         String url = "someUrl";
-        X509Certificate cert = SAMLUtils.generateRandomX509Certificate(SAMLUtils.generateRandomKeyPair());
+        KeyPair kp = SAMLUtils.generateRandomKeyPair();
+        X509Certificate cert = SAMLUtils.generateRandomX509Certificate(kp);
+
+        SAMLProviderMetadata providerMetadata = new SAMLProviderMetadata();
+        providerMetadata.setEntityId("random");
+        providerMetadata.setSigningCertificate(cert);
+        providerMetadata.setEncryptionCertificate(cert);
+        providerMetadata.setKeyPair(kp);
+        providerMetadata.setSsoUrl("http://test.local");
+        providerMetadata.setSloUrl("http://test.local");
+
+        Mockito.when(samlAuthManager.getSPMetadata()).thenReturn(providerMetadata);
 
         String result = cmd.authenticate("command", null, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
         Assert.assertTrue(result.contains("md:EntityDescriptor"));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
index a55704d..0f68e76 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
@@ -56,7 +56,6 @@ public class SAMLUtilsTest extends TestCase {
         LogoutRequest req = SAMLUtils.buildLogoutRequest(logoutUrl, spId);
         assertEquals(req.getDestination(), logoutUrl);
         assertEquals(req.getIssuer().getValue(), spId);
-        assertEquals(req.getSessionIndexes().get(0).getSessionIndex(), sessionIndex);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f971ac98/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
index c2d4960..00455b9 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
@@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.auth.APIAuthenticationType;
 import org.apache.cloudstack.saml.SAML2AuthManager;
 import org.apache.cloudstack.saml.SAMLPluginConstants;
+import org.apache.cloudstack.saml.SAMLProviderMetadata;
 import org.apache.cloudstack.saml.SAMLUtils;
 import org.joda.time.DateTime;
 import org.junit.Assert;
@@ -43,6 +44,7 @@ import org.opensaml.common.SAMLVersion;
 import org.opensaml.saml2.core.Assertion;
 import org.opensaml.saml2.core.AttributeStatement;
 import org.opensaml.saml2.core.AuthnStatement;
+import org.opensaml.saml2.core.Issuer;
 import org.opensaml.saml2.core.NameID;
 import org.opensaml.saml2.core.NameIDType;
 import org.opensaml.saml2.core.Response;
@@ -52,6 +54,7 @@ import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.core.impl.AssertionBuilder;
 import org.opensaml.saml2.core.impl.AttributeStatementBuilder;
 import org.opensaml.saml2.core.impl.AuthnStatementBuilder;
+import org.opensaml.saml2.core.impl.IssuerBuilder;
 import org.opensaml.saml2.core.impl.NameIDBuilder;
 import org.opensaml.saml2.core.impl.ResponseBuilder;
 import org.opensaml.saml2.core.impl.StatusBuilder;
@@ -62,6 +65,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import java.lang.reflect.Field;
+import java.security.KeyPair;
 import java.security.cert.X509Certificate;
 import java.util.HashMap;
 import java.util.Map;
@@ -101,6 +105,9 @@ public class SAML2LoginAPIAuthenticatorCmdTest {
         samlMessage.setID("foo");
         samlMessage.setVersion(SAMLVersion.VERSION_20);
         samlMessage.setIssueInstant(new DateTime(0));
+        Issuer issuer = new IssuerBuilder().buildObject();
+        issuer.setValue("MockedIssuer");
+        samlMessage.setIssuer(issuer);
         Status status = new StatusBuilder().buildObject();
         StatusCode statusCode = new StatusCodeBuilder().buildObject();
         statusCode.setValue(StatusCode.SUCCESS_URI);
@@ -148,7 +155,16 @@ public class SAML2LoginAPIAuthenticatorCmdTest {
 
         String spId = "someSPID";
         String url = "someUrl";
-        X509Certificate cert = SAMLUtils.generateRandomX509Certificate(SAMLUtils.generateRandomKeyPair());
+        KeyPair kp = SAMLUtils.generateRandomKeyPair();
+        X509Certificate cert = SAMLUtils.generateRandomX509Certificate(kp);
+
+        SAMLProviderMetadata providerMetadata = new SAMLProviderMetadata();
+        providerMetadata.setEntityId("random");
+        providerMetadata.setSigningCertificate(cert);
+        providerMetadata.setEncryptionCertificate(cert);
+        providerMetadata.setKeyPair(kp);
+        providerMetadata.setSsoUrl("http://test.local");
+        providerMetadata.setSloUrl("http://test.local");
 
         Mockito.when(session.getAttribute(Mockito.anyString())).thenReturn(null);
 
@@ -158,6 +174,8 @@ public class SAML2LoginAPIAuthenticatorCmdTest {
         user.setId(1000L);
         Mockito.when(userAccountDao.getUserAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(user);
         Mockito.when(apiServer.verifyUser(Mockito.anyLong())).thenReturn(false);
+        Mockito.when(samlAuthManager.getSPMetadata()).thenReturn(providerMetadata);
+        Mockito.when(samlAuthManager.getIdPMetadata(Mockito.anyString())).thenReturn(providerMetadata);
 
         Map<String, Object[]> params = new HashMap<String, Object[]>();
 
@@ -172,9 +190,8 @@ public class SAML2LoginAPIAuthenticatorCmdTest {
             cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
         } catch (ServerApiException ignored) {
         }
-        //Mockito.verify(domainMgr, Mockito.times(1)).getDomain(Mockito.anyString());
-        //Mockito.verify(userAccountDao, Mockito.times(1)).getUserAccount(Mockito.anyString(), Mockito.anyLong());
-        //Mockito.verify(apiServer, Mockito.times(1)).verifyUser(Mockito.anyLong());
+        Mockito.verify(userAccountDao, Mockito.times(0)).getUserAccount(Mockito.anyString(), Mockito.anyLong());
+        Mockito.verify(apiServer, Mockito.times(0)).verifyUser(Mockito.anyLong());
     }
 
     @Test


[2/2] git commit: updated refs/heads/saml-production-grade to ba8b9da

Posted by bh...@apache.org.
UI: in progress

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/ba8b9da3
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ba8b9da3
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ba8b9da3

Branch: refs/heads/saml-production-grade
Commit: ba8b9da302ce1685bb692f4f271252a7e32854a4
Parents: f971ac9
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Wed Jun 10 14:48:12 2015 +0300
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Jun 12 14:48:36 2015 +0300

----------------------------------------------------------------------
 ui/scripts/accountsWizard.js           | 28 +++++++++++++++++++++++++++-
 ui/scripts/docs.js                     |  8 ++++++++
 ui/scripts/sharedFunctions.js          |  1 +
 ui/scripts/ui-custom/accountsWizard.js |  5 +++++
 ui/scripts/ui-custom/login.js          |  1 +
 5 files changed, 42 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ba8b9da3/ui/scripts/accountsWizard.js
----------------------------------------------------------------------
diff --git a/ui/scripts/accountsWizard.js b/ui/scripts/accountsWizard.js
index 82e7eab..3747876 100644
--- a/ui/scripts/accountsWizard.js
+++ b/ui/scripts/accountsWizard.js
@@ -162,8 +162,34 @@
                 validation: {
                     required: false
                 }
+            },
+            samlEnable: {
+                label: 'label.saml.enable',
+                docID: 'helpSamlEnable',
+                isBoolean: true,
+                validation: {
+                    required: false
+                }
+            },
+            samlEntity: {
+                label: 'label.saml.entity',
+                docID: 'helpSamlEntity',
+                validation: {
+                    required: false
+                },
+                select: function(args) {
+                    var items = [];
+                    $(g_idpList).each(function() {
+                        items.push({
+                            id: this.id,
+                            description: this.orgName
+                        });
+                    });
+                    args.response.success({
+                        data: items
+                    });
+                }
             }
-
         },
 
         action: function(args) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ba8b9da3/ui/scripts/docs.js
----------------------------------------------------------------------
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index d38bcf7..ed94ccc 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -1247,6 +1247,14 @@ cloudStack.docs = {
         desc: 'The group name from which you want to import LDAP users',
         externalLink: ''
     },
+    helpSamlEnable: {
+        desc: 'Enable SAML Single Sign On for the user(s)',
+        externalLink: ''
+    },
+    helpSamlEntity: {
+        desc: 'Choose the SAML Identity Provider Entity ID with which you want to enable the Single Sign On for the user(s)',
+        externalLink: ''
+    },
     helpVpcOfferingName: {
         desc: 'Any desired name for the VPC offering',
         externalLink: ''

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ba8b9da3/ui/scripts/sharedFunctions.js
----------------------------------------------------------------------
diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js
index 1e1514b..75860dc 100644
--- a/ui/scripts/sharedFunctions.js
+++ b/ui/scripts/sharedFunctions.js
@@ -32,6 +32,7 @@ var g_regionsecondaryenabled = null;
 var g_userPublicTemplateEnabled = "true";
 var g_cloudstackversion = null;
 var g_queryAsyncJobResultInterval = 3000;
+var g_idpList = null;
 
 //keyboard keycode
 var keycode_Enter = 13;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ba8b9da3/ui/scripts/ui-custom/accountsWizard.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/accountsWizard.js b/ui/scripts/ui-custom/accountsWizard.js
index 3259227..cfbe930 100644
--- a/ui/scripts/ui-custom/accountsWizard.js
+++ b/ui/scripts/ui-custom/accountsWizard.js
@@ -271,6 +271,11 @@
                     delete args.informationNotInLdap.ldapGroupName;
                 }
 
+                if (g_idpList == null) {
+                    delete args.informationNotInLdap.samlEnable;
+                    delete args.informationNotInLdap.samlEntity;
+                }
+
                 var informationNotInLdap = cloudStack.dialog.createForm({
                     context: context,
                     noDialog: true,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ba8b9da3/ui/scripts/ui-custom/login.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/login.js b/ui/scripts/ui-custom/login.js
index 7f32e13..0c4c6fc 100644
--- a/ui/scripts/ui-custom/login.js
+++ b/ui/scripts/ui-custom/login.js
@@ -144,6 +144,7 @@
                 var idpList = data.listidpsresponse.idp.sort(function (a, b) {
                     return a.orgName.localeCompare(b.orgName);
                 });
+                g_idpList = idpList;
                 if (idpList.length > 1) {
                     $login.find('#saml-idps')
                         .append($('<option>', {