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/08/14 08:54:42 UTC
[1/8] git commit: updated refs/heads/master to 869a83f
Repository: cloudstack
Updated Branches:
refs/heads/master 5d29b63cf -> 869a83f8f
CLOUDSTACK-8702: Add/refactor sessionkey checking code to HttpUtils
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit cb7dd7b27dff1408cc41d69152a644c5b8842bfe)
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/89f47ece
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/89f47ece
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/89f47ece
Branch: refs/heads/master
Commit: 89f47ece3d4d3258fe62dbce42da1d126cfd0e7b
Parents: 5d29b63
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Mon Aug 3 14:34:20 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 11:56:55 2015 +0530
----------------------------------------------------------------------
server/src/com/cloud/api/ApiServlet.java | 8 +-------
utils/src/com/cloud/utils/HttpUtils.java | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/89f47ece/server/src/com/cloud/api/ApiServlet.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java
index e30a6ca..4322154 100644
--- a/server/src/com/cloud/api/ApiServlet.java
+++ b/server/src/com/cloud/api/ApiServlet.java
@@ -245,13 +245,7 @@ public class ApiServlet extends HttpServlet {
userId = (Long)session.getAttribute("userid");
final String account = (String) session.getAttribute("account");
final Object accountObj = session.getAttribute("accountobj");
- final String sessionKey = (String) session.getAttribute(ApiConstants.SESSIONKEY);
- final String sessionKeyFromCookie = HttpUtils.findCookie(req.getCookies(), ApiConstants.SESSIONKEY);
- final String[] sessionKeyFromParams = (String[]) params.get(ApiConstants.SESSIONKEY);
- if ((sessionKey == null)
- || (sessionKeyFromParams == null && sessionKeyFromCookie == null)
- || (sessionKeyFromParams != null && !sessionKey.equals(sessionKeyFromParams[0]))
- || (sessionKeyFromCookie != null && !sessionKey.equals(sessionKeyFromCookie))) {
+ if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), ApiConstants.SESSIONKEY)) {
try {
session.invalidate();
} catch (final IllegalStateException ise) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/89f47ece/utils/src/com/cloud/utils/HttpUtils.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/HttpUtils.java b/utils/src/com/cloud/utils/HttpUtils.java
index 6077c44..379b117 100644
--- a/utils/src/com/cloud/utils/HttpUtils.java
+++ b/utils/src/com/cloud/utils/HttpUtils.java
@@ -23,7 +23,9 @@ import org.apache.log4j.Logger;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import java.io.IOException;
+import java.util.Map;
public class HttpUtils {
@@ -89,4 +91,18 @@ public class HttpUtils {
}
}
}
+
+ public static boolean validateSessionKey(final HttpSession session, final Map<String, Object[]> params, final Cookie[] cookies, final String sessionKeyString) {
+ final String sessionKey = (String) session.getAttribute(sessionKeyString);
+ final String sessionKeyFromCookie = HttpUtils.findCookie(cookies, sessionKeyString);
+ final String[] sessionKeyFromParams = (String[]) params.get(sessionKeyString);
+ if ((sessionKey == null)
+ || (sessionKeyFromParams == null && sessionKeyFromCookie == null)
+ || (sessionKeyFromParams != null && !sessionKey.equals(sessionKeyFromParams[0]))
+ || (sessionKeyFromCookie != null && !sessionKey.equals(sessionKeyFromCookie))) {
+ return false;
+ }
+ return true;
+ }
+
}
[2/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
CLOUDSTACK-8701: Allow SAML users to switch accounts
SAML authorized accounts might be across various domains, this allows for
switching of accounts only in case of SAML authenticated user accounts across
other accounts with the same SAML uid/username.
Moves the previous switch account logic to its own ui-custom module
(cherry picked from commit 1065661cd50c8d43bf65644a13d164b96732b011)
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
Conflicts:
plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java
ui/index.jsp
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1ec4d015
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1ec4d015
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1ec4d015
Branch: refs/heads/master
Commit: 1ec4d0155a56cb5d1e2d62a1925b46e4b7050d66
Parents: 89f47ec
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Mon Aug 3 12:36:14 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 11:58:44 2015 +0530
----------------------------------------------------------------------
client/tomcatconf/commands.properties.in | 1 +
.../command/GetServiceProviderMetaDataCmd.java | 2 +-
.../command/ListAndSwitchSAMLAccountCmd.java | 195 +++++++++++++++++++
.../cloudstack/api/command/ListIdpsCmd.java | 2 +-
.../command/SAML2LoginAPIAuthenticatorCmd.java | 35 +---
.../api/response/SamlUserAccountResponse.java | 99 ++++++++++
.../cloudstack/saml/SAML2AuthManagerImpl.java | 2 +
.../cloudstack/saml/SAML2UserAuthenticator.java | 22 +--
.../org/apache/cloudstack/saml/SAMLUtils.java | 18 ++
ui/css/cloudstack3.css | 6 +-
ui/index.jsp | 8 +-
ui/scripts/ui-custom/login.js | 8 +-
ui/scripts/ui-custom/saml.js | 96 +++++++++
13 files changed, 424 insertions(+), 70 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index c32ecc4..aec7516 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -29,6 +29,7 @@ getSPMetadata=15
listIdps=15
authorizeSamlSso=7
listSamlAuthorization=7
+listAndSwitchSamlAccount=15
### Account commands
createAccount=7
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
index 75353f2..a6cefb1 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
@@ -267,7 +267,7 @@ public class GetServiceProviderMetaDataCmd extends BaseCmd implements APIAuthent
}
}
if (_samlAuthManager == null) {
- s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 Login Cmd");
+ s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 getSPMetadata Cmd");
}
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
new file mode 100644
index 0000000..db0d6dc
--- /dev/null
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
@@ -0,0 +1,195 @@
+// 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 org.apache.cloudstack.api.command;
+
+import com.cloud.api.response.ApiResponseSerializer;
+import com.cloud.domain.Domain;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.user.Account;
+import com.cloud.user.User;
+import com.cloud.user.UserAccount;
+import com.cloud.user.UserAccountVO;
+import com.cloud.user.dao.UserAccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.HttpUtils;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ApiServerService;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.auth.APIAuthenticationType;
+import org.apache.cloudstack.api.auth.APIAuthenticator;
+import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.LoginCmdResponse;
+import org.apache.cloudstack.api.response.SamlUserAccountResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.UserResponse;
+import org.apache.cloudstack.saml.SAML2AuthManager;
+import org.apache.cloudstack.saml.SAMLUtils;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@APICommand(name = "listAndSwitchSamlAccount", description = "Lists and switches to other SAML accounts owned by the SAML user", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListAndSwitchSAMLAccountCmd extends BaseCmd implements APIAuthenticator {
+ public static final Logger s_logger = Logger.getLogger(ListAndSwitchSAMLAccountCmd.class.getName());
+ private static final String s_name = "listandswitchsamlaccountresponse";
+
+ @Inject
+ ApiServerService _apiServer;
+
+ @Inject
+ private UserAccountDao _userAccountDao;
+ @Inject
+ private UserDao _userDao;
+ @Inject
+ private DomainDao _domainDao;
+
+ SAML2AuthManager _samlAuthManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.USER_ID, type = CommandType.UUID, entityType = UserResponse.class, required = false, description = "User uuid")
+ private Long userId;
+
+ @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, required = false, description = "Domain uuid")
+ private Long domainId;
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute() {
+ throw new ServerApiException(ApiErrorCode.METHOD_NOT_ALLOWED, "This is an authentication plugin api, cannot be used directly");
+ }
+
+ @Override
+ public String authenticate(final String command, final Map<String, Object[]> params, final HttpSession session, final String remoteAddress, final String responseType, final StringBuilder auditTrailSb, final HttpServletRequest req, final HttpServletResponse resp) throws ServerApiException {
+ if (session == null || session.isNew()) {
+ throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, _apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED.getHttpCode(),
+ "Only authenticated saml users can request this API",
+ params, responseType));
+ }
+
+ if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), ApiConstants.SESSIONKEY)) {
+ throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, _apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED.getHttpCode(),
+ "Unauthorized session, please re-login",
+ params, responseType));
+ }
+
+ final long currentUserId = (Long) session.getAttribute("userid");
+ final UserAccount currentUserAccount = _accountService.getUserAccountById(currentUserId);
+ if (currentUserAccount == null || currentUserAccount.getSource() != User.Source.SAML2) {
+ throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(),
+ "Only authenticated saml users can request this API",
+ params, responseType));
+ }
+
+ String userUuid = null;
+ String domainUuid = null;
+ if (params.containsKey(ApiConstants.USER_ID)) {
+ userUuid = ((String[])params.get(ApiConstants.USER_ID))[0];
+ }
+ if (params.containsKey(ApiConstants.DOMAIN_ID)) {
+ domainUuid = ((String[])params.get(ApiConstants.DOMAIN_ID))[0];
+ }
+
+ if (userUuid != null && domainUuid != null) {
+ final User user = _userDao.findByUuid(userUuid);
+ final Domain domain = _domainDao.findByUuid(domainUuid);
+ final UserAccount nextUserAccount = _accountService.getUserAccountById(user.getId());
+ if (!nextUserAccount.getUsername().equals(currentUserAccount.getUsername())
+ || !nextUserAccount.getExternalEntity().equals(currentUserAccount.getExternalEntity())
+ || (nextUserAccount.getDomainId() != domain.getId())
+ || (nextUserAccount.getSource() != User.Source.SAML2)) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.PARAM_ERROR.getHttpCode(),
+ "User account is not allowed to switch to the requested account",
+ params, responseType));
+ }
+ try {
+ if (_apiServer.verifyUser(nextUserAccount.getId())) {
+ final LoginCmdResponse loginResponse = (LoginCmdResponse) _apiServer.loginUser(session, nextUserAccount.getUsername(), nextUserAccount.getUsername() + nextUserAccount.getSource().toString(),
+ nextUserAccount.getDomainId(), null, remoteAddress, params);
+ SAMLUtils.setupSamlUserCookies(loginResponse, resp);
+ resp.sendRedirect(SAML2AuthManager.SAMLCloudStackRedirectionUrl.value());
+ return ApiResponseSerializer.toSerializedString(loginResponse, responseType);
+ }
+ } catch (final Exception ignored) {
+ }
+ } else {
+ List<UserAccountVO> switchableAccounts = _userAccountDao.getAllUsersByNameAndEntity(currentUserAccount.getUsername(), currentUserAccount.getExternalEntity());
+ if (switchableAccounts != null && switchableAccounts.size() > 0 && currentUserId != User.UID_SYSTEM) {
+ List<SamlUserAccountResponse> accountResponses = new ArrayList<SamlUserAccountResponse>();
+ for (UserAccountVO userAccount: switchableAccounts) {
+ User user = _userDao.getUser(userAccount.getId());
+ Domain domain = _domainService.getDomain(userAccount.getDomainId());
+ SamlUserAccountResponse accountResponse = new SamlUserAccountResponse();
+ accountResponse.setUserId(user.getUuid());
+ accountResponse.setUserName(user.getUsername());
+ accountResponse.setDomainId(domain.getUuid());
+ accountResponse.setDomainName(domain.getName());
+ accountResponse.setAccountName(userAccount.getAccountName());
+ accountResponse.setIdpId(user.getExternalEntity());
+ accountResponses.add(accountResponse);
+ }
+ ListResponse<SamlUserAccountResponse> response = new ListResponse<SamlUserAccountResponse>();
+ response.setResponses(accountResponses);
+ response.setResponseName(getCommandName());
+ return ApiResponseSerializer.toSerializedString(response, responseType);
+ }
+ }
+ throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(),
+ "Unable to switch to requested SAML account. Please make sure your user/account is enabled. Please contact your administrator.",
+ params, responseType));
+ }
+
+ @Override
+ public APIAuthenticationType getAPIType() {
+ return APIAuthenticationType.READONLY_API;
+ }
+
+ @Override
+ public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) {
+ for (PluggableAPIAuthenticator authManager: authenticators) {
+ if (authManager != null && authManager instanceof SAML2AuthManager) {
+ _samlAuthManager = (SAML2AuthManager) authManager;
+ }
+ }
+ if (_samlAuthManager == null) {
+ s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 listAndSwitchSamlAccount Cmd");
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListIdpsCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListIdpsCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListIdpsCmd.java
index ad38704..026a0ca 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListIdpsCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListIdpsCmd.java
@@ -111,4 +111,4 @@ public class ListIdpsCmd extends BaseCmd implements APIAuthenticator {
s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 Login Cmd");
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/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 8e67408..f2fcf59 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
@@ -17,13 +17,11 @@
package org.apache.cloudstack.api.command;
import com.cloud.api.response.ApiResponseSerializer;
-import com.cloud.exception.CloudAuthenticationException;
import com.cloud.user.Account;
import com.cloud.user.DomainManager;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.dao.UserAccountDao;
-import com.cloud.utils.HttpUtils;
import com.cloud.utils.db.EntityManager;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@@ -64,7 +62,6 @@ import org.opensaml.xml.validation.ValidationException;
import org.xml.sax.SAXException;
import javax.inject.Inject;
-import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -197,7 +194,6 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
}
String username = null;
- Long domainId = null;
Issuer issuer = processedSAMLResponse.getIssuer();
SAMLProviderMetadata spMetadata = _samlAuthManager.getSPMetadata();
SAMLProviderMetadata idpMetadata = _samlAuthManager.getIdPMetadata(issuer.getValue());
@@ -206,9 +202,6 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
s_logger.debug("Received SAMLResponse in response to id=" + responseToId);
SAMLTokenVO token = _samlAuthManager.getToken(responseToId);
if (token != null) {
- if (token.getDomainId() != null) {
- domainId = token.getDomainId();
- }
if (!(token.getEntity().equalsIgnoreCase(issuer.getValue()))) {
throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(),
"The SAML response contains Issuer Entity ID that is different from the original SAML request",
@@ -300,17 +293,9 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
UserAccount userAccount = null;
List<UserAccountVO> possibleUserAccounts = _userAccountDao.getAllUsersByNameAndEntity(username, issuer.getValue());
if (possibleUserAccounts != null && possibleUserAccounts.size() > 0) {
- if (possibleUserAccounts.size() == 1) {
- userAccount = possibleUserAccounts.get(0);
- } else if (possibleUserAccounts.size() > 1) {
- if (domainId != null) {
- userAccount = _userAccountDao.getUserAccount(username, domainId);
- } else {
- throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(),
- "You have accounts in multiple domains, please re-login by specifying the domain you want to log into.",
- params, responseType));
- }
- }
+ // By default, log into the first user account
+ // Users can switch to other allowed accounts later
+ userAccount = possibleUserAccounts.get(0);
}
if (userAccount == null || userAccount.getExternalEntity() == null || !_samlAuthManager.isUserAuthorized(userAccount.getId(), issuer.getValue())) {
@@ -324,21 +309,11 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
if (_apiServer.verifyUser(userAccount.getId())) {
LoginCmdResponse loginResponse = (LoginCmdResponse) _apiServer.loginUser(session, userAccount.getUsername(), userAccount.getUsername() + userAccount.getSource().toString(),
userAccount.getDomainId(), null, remoteAddress, params);
- resp.addCookie(new Cookie("userid", URLEncoder.encode(loginResponse.getUserId(), HttpUtils.UTF_8)));
- resp.addCookie(new Cookie("domainid", URLEncoder.encode(loginResponse.getDomainId(), HttpUtils.UTF_8)));
- resp.addCookie(new Cookie("role", URLEncoder.encode(loginResponse.getType(), HttpUtils.UTF_8)));
- resp.addCookie(new Cookie("username", URLEncoder.encode(loginResponse.getUsername(), HttpUtils.UTF_8)));
- resp.addCookie(new Cookie("account", URLEncoder.encode(loginResponse.getAccount(), HttpUtils.UTF_8)));
- String timezone = loginResponse.getTimeZone();
- if (timezone != null) {
- resp.addCookie(new Cookie("timezone", URLEncoder.encode(timezone, HttpUtils.UTF_8)));
- }
- resp.addCookie(new Cookie("userfullname", URLEncoder.encode(loginResponse.getFirstName() + " " + loginResponse.getLastName(), HttpUtils.UTF_8).replace("+", "%20")));
- resp.addHeader("SET-COOKIE", String.format("%s=%s;HttpOnly", ApiConstants.SESSIONKEY, loginResponse.getSessionKey()));
+ SAMLUtils.setupSamlUserCookies(loginResponse, resp);
resp.sendRedirect(SAML2AuthManager.SAMLCloudStackRedirectionUrl.value());
return ApiResponseSerializer.toSerializedString(loginResponse, responseType);
}
- } catch (final CloudAuthenticationException ignored) {
+ } catch (final Exception ignored) {
}
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
new file mode 100644
index 0000000..f0927e3
--- /dev/null
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
@@ -0,0 +1,99 @@
+// 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 org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class SamlUserAccountResponse extends AuthenticationCmdResponse {
+ @SerializedName("userId")
+ @Param(description = "The User Id")
+ private String userId;
+
+ @SerializedName("domainId")
+ @Param(description = "The Domain Id")
+ private String domainId;
+
+ @SerializedName("userName")
+ @Param(description = "The User Name")
+ private String userName;
+
+ @SerializedName("accountName")
+ @Param(description = "The Account Name")
+ private String accountName;
+
+ @SerializedName("domainName")
+ @Param(description = "The Domain Name")
+ private String domainName;
+
+ @SerializedName("idpId")
+ @Param(description = "The IDP ID")
+ private String idpId;
+
+ public SamlUserAccountResponse() {
+ super();
+ setObjectName("samluseraccount");
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public void setAccountName(String accountName) {
+ this.accountName = accountName;
+ }
+
+ public String getDomainName() {
+ return domainName;
+ }
+
+ public void setDomainName(String domainName) {
+ this.domainName = domainName;
+ }
+
+ public String getIdpId() {
+ return idpId;
+ }
+
+ public void setIdpId(String idpId) {
+ this.idpId = idpId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/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 b1449c1..ff644f3 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
@@ -26,6 +26,7 @@ import com.cloud.utils.component.AdapterBase;
import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
import org.apache.cloudstack.api.command.AuthorizeSAMLSSOCmd;
import org.apache.cloudstack.api.command.GetServiceProviderMetaDataCmd;
+import org.apache.cloudstack.api.command.ListAndSwitchSAMLAccountCmd;
import org.apache.cloudstack.api.command.ListIdpsCmd;
import org.apache.cloudstack.api.command.ListSamlAuthorizationCmd;
import org.apache.cloudstack.api.command.SAML2LoginAPIAuthenticatorCmd;
@@ -506,6 +507,7 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage
cmdList.add(SAML2LogoutAPIAuthenticatorCmd.class);
cmdList.add(GetServiceProviderMetaDataCmd.class);
cmdList.add(ListIdpsCmd.class);
+ cmdList.add(ListAndSwitchSAMLAccountCmd.class);
return cmdList;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/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 5c8a390..65a7959 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
@@ -23,18 +23,9 @@ import com.cloud.user.dao.UserDao;
import com.cloud.utils.Pair;
import org.apache.cxf.common.util.StringUtils;
import org.apache.log4j.Logger;
-import org.opensaml.DefaultBootstrap;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.xml.ConfigurationException;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.xml.sax.SAXException;
import javax.ejb.Local;
import javax.inject.Inject;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.FactoryConfigurationError;
-import java.io.IOException;
import java.util.Map;
@Local(value = {UserAuthenticator.class})
@@ -63,18 +54,7 @@ public class SAML2UserAuthenticator extends DefaultUserAuthenticator {
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
} else {
User user = _userDao.getUser(userAccount.getId());
- if (user != null && requestParameters != null && requestParameters.containsKey(SAMLPluginConstants.SAML_RESPONSE)) {
- final String samlResponse = ((String[])requestParameters.get(SAMLPluginConstants.SAML_RESPONSE))[0];
- Response responseObject = null;
- try {
- DefaultBootstrap.bootstrap();
- responseObject = SAMLUtils.decodeSAMLResponse(samlResponse);
- } catch (ConfigurationException | FactoryConfigurationError | ParserConfigurationException | SAXException | IOException | UnmarshallingException e) {
- return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
- }
- if (!responseObject.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
- return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
- }
+ if (user != null && user.getSource() == User.Source.SAML2 && user.getExternalEntity() != null) {
return new Pair<Boolean, ActionOnFailedAuthentication>(true, null);
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
index 77714a1..ec6b2c1 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
@@ -20,6 +20,8 @@
package org.apache.cloudstack.saml;
import com.cloud.utils.HttpUtils;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.response.LoginCmdResponse;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V1CertificateGenerator;
@@ -62,6 +64,8 @@ import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -352,4 +356,18 @@ public class SAMLUtils {
return certGen.generate(keyPair.getPrivate(), "BC");
}
+ public static void setupSamlUserCookies(final LoginCmdResponse loginResponse, final HttpServletResponse resp) throws IOException {
+ resp.addCookie(new Cookie("userid", URLEncoder.encode(loginResponse.getUserId(), HttpUtils.UTF_8)));
+ resp.addCookie(new Cookie("domainid", URLEncoder.encode(loginResponse.getDomainId(), HttpUtils.UTF_8)));
+ resp.addCookie(new Cookie("role", URLEncoder.encode(loginResponse.getType(), HttpUtils.UTF_8)));
+ resp.addCookie(new Cookie("username", URLEncoder.encode(loginResponse.getUsername(), HttpUtils.UTF_8)));
+ resp.addCookie(new Cookie("account", URLEncoder.encode(loginResponse.getAccount(), HttpUtils.UTF_8)));
+ String timezone = loginResponse.getTimeZone();
+ if (timezone != null) {
+ resp.addCookie(new Cookie("timezone", URLEncoder.encode(timezone, HttpUtils.UTF_8)));
+ }
+ resp.addCookie(new Cookie("userfullname", URLEncoder.encode(loginResponse.getFirstName() + " " + loginResponse.getLastName(), HttpUtils.UTF_8).replace("+", "%20")));
+ resp.addHeader("SET-COOKIE", String.format("%s=%s;HttpOnly", ApiConstants.SESSIONKEY, loginResponse.getSessionKey()));
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index 2bcd5e5..60ac9ca 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -9657,7 +9657,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
}
/*** View switcher (drop-down)*/
-.project-switcher {
+.project-switcher, .domain-switcher {
float: left;
width: 223px;
padding: 9px 17px 0 19px;
@@ -9668,7 +9668,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
border-radius: 4px;
}
-.project-switcher label {
+.project-switcher label, .domain-switcher label {
top: 29px;
color: #FFFFFF;
font-size: 13px;
@@ -9677,7 +9677,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
margin-top: 5px;
}
-.project-switcher select {
+.project-switcher select, .domain-switcher select {
width: 70%;
float: left;
margin-top: 0px;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/ui/index.jsp
----------------------------------------------------------------------
diff --git a/ui/index.jsp b/ui/index.jsp
index e062799..0100744 100644
--- a/ui/index.jsp
+++ b/ui/index.jsp
@@ -75,13 +75,6 @@
</div>
</div>
- <div id="saml-login">
- <div class="field domain">
- <label for="saml-domain"><fmt:message key="label.domain"/></label>
- <input id="saml-domain" type="text" name="saml-domain" />
- </div>
- </div>
-
<div id="login-submit">
<!-- Submit (login) -->
<input id="login-submit" type="submit" value="<fmt:message key="label.login"/>" />
@@ -1841,6 +1834,7 @@
<script type="text/javascript" src="scripts/docs.js"></script>
<script type="text/javascript" src="scripts/vm_snapshots.js"></script>
<script type="text/javascript" src="scripts/ui-custom/projectSelect.js"></script>
+ <script type="text/javascript" src="scripts/ui-custom/saml.js"></script>
<!-- Plugin/module API -->
<script type="text/javascript" src="scripts/ui-custom/pluginListing.js"></script>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/ui/scripts/ui-custom/login.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/login.js b/ui/scripts/ui-custom/login.js
index e112958..5825529 100644
--- a/ui/scripts/ui-custom/login.js
+++ b/ui/scripts/ui-custom/login.js
@@ -122,8 +122,7 @@
} else if (selectedLogin === 'saml') {
// SAML
args.samlLoginAction({
- data: {'idpid': $login.find('#login-options').find(':selected').val(),
- 'domain': $login.find('#saml-domain').val()}
+ data: {'idpid': $login.find('#login-options').find(':selected').val()}
});
}
return false;
@@ -133,16 +132,13 @@
var toggleLoginView = function (selectedOption) {
$login.find('#login-submit').show();
if (selectedOption === '') {
- $login.find('#saml-login').hide();
$login.find('#cloudstack-login').hide();
$login.find('#login-submit').hide();
selectedLogin = 'none';
} else if (selectedOption === 'cloudstack-login') {
- $login.find('#saml-login').hide();
$login.find('#cloudstack-login').show();
selectedLogin = 'cloudstack';
} else {
- $login.find('#saml-login').show();
$login.find('#cloudstack-login').hide();
selectedLogin = 'saml';
}
@@ -160,14 +156,12 @@
$login.find('#login-dropdown').hide();
$login.find('#login-submit').show();
$login.find('#cloudstack-login').show();
- $login.find('#saml-login').hide();
// If any IdP servers were set, SAML is enabled
if (g_idpList && g_idpList.length > 0) {
$login.find('#login-dropdown').show();
$login.find('#login-submit').hide();
$login.find('#cloudstack-login').hide();
- $login.find('#saml-login').hide();
$login.find('#login-options')
.append($('<option>', {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1ec4d015/ui/scripts/ui-custom/saml.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/saml.js b/ui/scripts/ui-custom/saml.js
new file mode 100644
index 0000000..391e7f8
--- /dev/null
+++ b/ui/scripts/ui-custom/saml.js
@@ -0,0 +1,96 @@
+// 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.
+
+(function($, cloudStack) {
+ $(window).bind('cloudStack.ready', function() {
+ var showSamlDomainSwitcher = false;
+ if (g_idpList) {
+ showSamlDomainSwitcher = true;
+ }
+ if (!showSamlDomainSwitcher) {
+ return;
+ }
+
+ var $label = $('<label>').html('Domain:');
+ var $header = $('#header .controls');
+ var $domainSwitcher = $('<div>').addClass('domain-switcher');
+ var $domainSelect = $('<select>');
+ $domainSwitcher.append($label, $domainSelect);
+
+ var switchAccount = function(userId, domainId) {
+ var toReload = true;
+ $.ajax({
+ url: createURL('listAndSwitchSamlAccount'),
+ type: 'POST',
+ async: false,
+ data: {
+ userid: userId,
+ domainid: domainId
+ },
+ success: function(data, textStatus) {
+ document.location.reload(true);
+ },
+ error: function(data) {
+ cloudStack.dialog.notice({
+ message: parseXMLHttpResponse(data)
+ });
+ if (data.status !== 200) {
+ toReload = false;
+ }
+ },
+ complete: function() {
+ if (toReload) {
+ document.location.reload(true);
+ }
+ toReload = true;
+ }
+ });
+ };
+
+ $domainSelect.change(function() {
+ var selectedOption = $domainSelect.val();
+ var userId = selectedOption.split('/')[0];
+ var domainId = selectedOption.split('/')[1];
+ switchAccount(userId, domainId);
+ });
+
+ $.ajax({
+ url: createURL('listAndSwitchSamlAccount'),
+ success: function(json) {
+ var accounts = json.listandswitchsamlaccountresponse.samluseraccount;
+ if (accounts.length < 2) {
+ return;
+ };
+ $domainSelect.empty();
+ for (var i = 0; i < accounts.length; i++) {
+ var option = $('<option>');
+ option.data("userId", accounts[i].userId);
+ option.data("domainId", accounts[i].domainId);
+ option.val(accounts[i].userId + '/' + accounts[i].domainId);
+ option.html(accounts[i].accountName + "/" + accounts[i].domainName);
+ option.appendTo($domainSelect);
+ }
+ var currentAccountDomain = g_userid + '/' + g_domainid;
+ $domainSelect.find('option[value="' + currentAccountDomain + '"]').attr("selected", "selected");
+ $domainSwitcher.insertAfter($header.find('.region-switcher'));
+ },
+ error: function(data) {
+ // if call fails, the logged in user in not a SAML authenticated user
+ }
+ });
+ });
+}(jQuery, cloudStack));
[7/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
CLOUDSTACK-8701: Add unit test for SAML2AuthManagerImpl
(cherry picked from commit 5f06ef77d8275602a45285c64854314d5ec9dbf5)
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
This closes #650
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a3e6942e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a3e6942e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a3e6942e
Branch: refs/heads/master
Commit: a3e6942e854230980e976294fa0686b85b6dd803
Parents: 25ccf41
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Aug 14 11:44:47 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 12:15:47 2015 +0530
----------------------------------------------------------------------
.../cloudstack/SAML2AuthManagerImplTest.java | 174 +++++++++++++++++++
1 file changed, 174 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3e6942e/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2AuthManagerImplTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2AuthManagerImplTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2AuthManagerImplTest.java
new file mode 100644
index 0000000..b06a137
--- /dev/null
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAML2AuthManagerImplTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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 org.apache.cloudstack;
+
+import com.cloud.user.DomainManager;
+import com.cloud.user.User;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.UserDao;
+import junit.framework.TestCase;
+import org.apache.cloudstack.framework.security.keystore.KeystoreDao;
+import org.apache.cloudstack.saml.SAML2AuthManagerImpl;
+import org.apache.cloudstack.saml.SAMLTokenDao;
+import org.apache.cloudstack.saml.SAMLTokenVO;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.lang.reflect.Field;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SAML2AuthManagerImplTest extends TestCase {
+ @Mock
+ private KeystoreDao ksDao;
+
+ @Mock
+ private SAMLTokenDao samlTokenDao;
+
+ @Mock
+ private UserDao userDao;
+
+ @Mock
+ DomainManager domainMgr;
+
+ SAML2AuthManagerImpl saml2AuthManager;
+
+ @Override
+ @Before
+ public void setUp() throws NoSuchFieldException, IllegalAccessException {
+ saml2AuthManager = Mockito.spy(new SAML2AuthManagerImpl());
+
+ Field ksDaoField = SAML2AuthManagerImpl.class.getDeclaredField("_ksDao");
+ ksDaoField.setAccessible(true);
+ ksDaoField.set(saml2AuthManager, ksDao);
+
+ Field samlTokenDaoField = SAML2AuthManagerImpl.class.getDeclaredField("_samlTokenDao");
+ samlTokenDaoField.setAccessible(true);
+ samlTokenDaoField.set(saml2AuthManager, samlTokenDao);
+
+ Field userDaoField = SAML2AuthManagerImpl.class.getDeclaredField("_userDao");
+ userDaoField.setAccessible(true);
+ userDaoField.set(saml2AuthManager, userDao);
+
+ Field domainMgrField = SAML2AuthManagerImpl.class.getDeclaredField("_domainMgr");
+ domainMgrField.setAccessible(true);
+ domainMgrField.set(saml2AuthManager, domainMgr);
+
+ // enable the plugin
+ Mockito.doReturn(true).when(saml2AuthManager).isSAMLPluginEnabled();
+ }
+
+ @Test
+ public void testIsUserAuthorized() {
+ final String entityID = "some IDP ID";
+
+ // Test unauthorized user
+ UserVO user = new UserVO(200L);
+ user.setUsername("someuser");
+ user.setSource(User.Source.UNKNOWN);
+ user.setExternalEntity(entityID);
+ Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user);
+ assertFalse(saml2AuthManager.isUserAuthorized(user.getId(), "someID"));
+
+ // Test authorized user with wrong IDP
+ user.setSource(User.Source.SAML2);
+ Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user);
+ assertFalse(saml2AuthManager.isUserAuthorized(user.getId(), "someID"));
+
+ // Test authorized user with wrong IDP
+ user.setSource(User.Source.SAML2);
+ Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user);
+ assertTrue(saml2AuthManager.isUserAuthorized(user.getId(), entityID));
+ }
+
+ @Test
+ public void testAuthorizeUser() {
+ // Test invalid user
+ Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(null);
+ assertFalse(saml2AuthManager.authorizeUser(1L, "someID", true));
+
+ // Test valid user
+ UserVO user = new UserVO(200L);
+ user.setUsername("someuser");
+ Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user);
+ assertTrue(saml2AuthManager.authorizeUser(1L, "someID", true));
+ Mockito.verify(userDao, Mockito.atLeastOnce()).update(Mockito.anyLong(), Mockito.any(user.getClass()));
+ }
+
+
+
+ @Test
+ public void testSaveToken() {
+ // duplicate token test
+ Mockito.when(samlTokenDao.findByUuid(Mockito.anyString())).thenReturn(new SAMLTokenVO());
+ saml2AuthManager.saveToken("someAuthnID", null, "https://idp.bhaisaab.org/profile/shibboleth");
+ Mockito.verify(samlTokenDao, Mockito.times(0)).persist(Mockito.any(SAMLTokenVO.class));
+
+ // valid test
+ Mockito.when(samlTokenDao.findByUuid(Mockito.anyString())).thenReturn(null);
+ saml2AuthManager.saveToken("someAuthnID", null, "https://idp.bhaisaab.org/profile/shibboleth");
+ Mockito.verify(samlTokenDao, Mockito.times(1)).persist(Mockito.any(SAMLTokenVO.class));
+ }
+
+ @Test
+ public void testGetToken() {
+ SAMLTokenVO randomToken = new SAMLTokenVO("uuid", 1L, "someIDPDI");
+ Mockito.when(samlTokenDao.findByUuid(Mockito.anyString())).thenReturn(randomToken);
+ assertEquals(saml2AuthManager.getToken("someAuthnID"), randomToken);
+ }
+
+ @Test
+ public void testExpireToken() {
+ saml2AuthManager.expireTokens();
+ Mockito.verify(samlTokenDao, Mockito.atLeast(1)).expireTokens();
+ }
+
+ @Test
+ public void testPluginEnabled() {
+ assertTrue(saml2AuthManager.isSAMLPluginEnabled());
+ }
+
+ @Test
+ public void testPluginComponentName() {
+ assertEquals(saml2AuthManager.getConfigComponentName(), "SAML2-PLUGIN");
+ }
+
+ @Test
+ public void testGetCommands() {
+ // Plugin enabled
+ assertTrue(saml2AuthManager.getCommands().size() > 0);
+ assertTrue(saml2AuthManager.getAuthCommands().size() > 0);
+
+ // Plugin disabled
+ Mockito.doReturn(false).when(saml2AuthManager).isSAMLPluginEnabled();
+ assertTrue(saml2AuthManager.getCommands().size() == 0);
+ assertTrue(saml2AuthManager.getAuthCommands().size() == 0);
+ // Re-enable the plugin
+ Mockito.doReturn(true).when(saml2AuthManager).isSAMLPluginEnabled();
+ }
+
+ @Test
+ public void testConfigKeys() {
+ assertTrue(saml2AuthManager.getConfigKeys().length > 0);
+ }
+}
[6/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
CLOUDSTACK-8701: Add listandswitchsamlaccount API test and add boundary checks
- Adds unit test for ListAndSwitchSAMLAccountCmd
- Checks and logs in user only if they are enabled
- If saml user switches to a locked account, send appropriate error message
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit b30977911dbfb1eae86d53ff1b848c5812b68c07)
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/25ccf412
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/25ccf412
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/25ccf412
Branch: refs/heads/master
Commit: 25ccf4126d4729c1361855eaeef8e58acdebc70f
Parents: fcbee60
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Wed Aug 12 14:04:08 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 12:00:04 2015 +0530
----------------------------------------------------------------------
.../command/ListAndSwitchSAMLAccountCmd.java | 14 +-
.../command/SAML2LoginAPIAuthenticatorCmd.java | 31 +--
.../ListAndSwitchSAMLAccountCmdTest.java | 201 +++++++++++++++++++
3 files changed, 231 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25ccf412/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
index db0d6dc..80aee1b 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
@@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.CloudAuthenticationException;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
@@ -50,6 +51,7 @@ import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -131,7 +133,14 @@ public class ListAndSwitchSAMLAccountCmd extends BaseCmd implements APIAuthentic
final User user = _userDao.findByUuid(userUuid);
final Domain domain = _domainDao.findByUuid(domainUuid);
final UserAccount nextUserAccount = _accountService.getUserAccountById(user.getId());
- if (!nextUserAccount.getUsername().equals(currentUserAccount.getUsername())
+ if (nextUserAccount != null && !nextUserAccount.getAccountState().equals(Account.State.enabled.toString())) {
+ throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.PARAM_ERROR.getHttpCode(),
+ "The requested user account is locked and cannot be switched to, please contact your administrator.",
+ params, responseType));
+ }
+ if (nextUserAccount == null
+ || !nextUserAccount.getAccountState().equals(Account.State.enabled.toString())
+ || !nextUserAccount.getUsername().equals(currentUserAccount.getUsername())
|| !nextUserAccount.getExternalEntity().equals(currentUserAccount.getExternalEntity())
|| (nextUserAccount.getDomainId() != domain.getId())
|| (nextUserAccount.getSource() != User.Source.SAML2)) {
@@ -147,7 +156,8 @@ public class ListAndSwitchSAMLAccountCmd extends BaseCmd implements APIAuthentic
resp.sendRedirect(SAML2AuthManager.SAMLCloudStackRedirectionUrl.value());
return ApiResponseSerializer.toSerializedString(loginResponse, responseType);
}
- } catch (final Exception ignored) {
+ } catch (CloudAuthenticationException | IOException exception) {
+ s_logger.debug("Failed to switch to request SAML user account due to: " + exception.getMessage());
}
} else {
List<UserAccountVO> switchableAccounts = _userAccountDao.getAllUsersByNameAndEntity(currentUserAccount.getUsername(), currentUserAccount.getExternalEntity());
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25ccf412/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 f2fcf59..7a1b83c 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
@@ -17,6 +17,7 @@
package org.apache.cloudstack.api.command;
import com.cloud.api.response.ApiResponseSerializer;
+import com.cloud.exception.CloudAuthenticationException;
import com.cloud.user.Account;
import com.cloud.user.DomainManager;
import com.cloud.user.UserAccount;
@@ -293,28 +294,32 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
UserAccount userAccount = null;
List<UserAccountVO> possibleUserAccounts = _userAccountDao.getAllUsersByNameAndEntity(username, issuer.getValue());
if (possibleUserAccounts != null && possibleUserAccounts.size() > 0) {
- // By default, log into the first user account
+ // Log into the first enabled user account
// Users can switch to other allowed accounts later
- userAccount = possibleUserAccounts.get(0);
+ for (UserAccountVO possibleUserAccount: possibleUserAccounts) {
+ if (possibleUserAccount.getAccountState().equals(Account.State.enabled.toString())) {
+ userAccount = possibleUserAccount;
+ break;
+ }
+ }
}
if (userAccount == null || userAccount.getExternalEntity() == null || !_samlAuthManager.isUserAuthorized(userAccount.getId(), issuer.getValue())) {
throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(),
- "Your authenticated user is not authorized, please contact your administrator",
+ "Your authenticated user is not authorized for SAML Single Sign-On, please contact your administrator",
params, responseType));
}
- if (userAccount != null) {
- try {
- if (_apiServer.verifyUser(userAccount.getId())) {
- LoginCmdResponse loginResponse = (LoginCmdResponse) _apiServer.loginUser(session, userAccount.getUsername(), userAccount.getUsername() + userAccount.getSource().toString(),
- userAccount.getDomainId(), null, remoteAddress, params);
- SAMLUtils.setupSamlUserCookies(loginResponse, resp);
- resp.sendRedirect(SAML2AuthManager.SAMLCloudStackRedirectionUrl.value());
- return ApiResponseSerializer.toSerializedString(loginResponse, responseType);
- }
- } catch (final Exception ignored) {
+ try {
+ if (_apiServer.verifyUser(userAccount.getId())) {
+ LoginCmdResponse loginResponse = (LoginCmdResponse) _apiServer.loginUser(session, userAccount.getUsername(), userAccount.getUsername() + userAccount.getSource().toString(),
+ userAccount.getDomainId(), null, remoteAddress, params);
+ SAMLUtils.setupSamlUserCookies(loginResponse, resp);
+ resp.sendRedirect(SAML2AuthManager.SAMLCloudStackRedirectionUrl.value());
+ return ApiResponseSerializer.toSerializedString(loginResponse, responseType);
}
+ } catch (CloudAuthenticationException | IOException exception) {
+ s_logger.debug("SAML Login failed to log in the user due to: " + exception.getMessage());
}
}
} catch (IOException e) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25ccf412/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
new file mode 100644
index 0000000..1423243
--- /dev/null
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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 org.apache.cloudstack.api.command;
+
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.user.UserAccountVO;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.UserAccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.HttpUtils;
+import junit.framework.TestCase;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ApiServerService;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.auth.APIAuthenticationType;
+import org.apache.cloudstack.api.response.LoginCmdResponse;
+import org.apache.cloudstack.saml.SAML2AuthManager;
+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;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
+ @Mock
+ ApiServerService apiServer;
+
+ @Mock
+ SAML2AuthManager samlAuthManager;
+
+ @Mock
+ AccountService accountService;
+
+ @Mock
+ UserAccountDao userAccountDao;
+
+ @Mock
+ UserDao userDao;
+
+ @Mock
+ DomainDao domainDao;
+
+ @Mock
+ HttpSession session;
+
+ @Mock
+ HttpServletResponse resp;
+
+ @Mock
+ HttpServletRequest req;
+
+ @Test
+ public void testListAndSwitchSAMLAccountCmd() throws Exception {
+ // Setup
+ final Map<String, Object[]> params = new HashMap<String, Object[]>();
+ final String sessionKeyValue = "someSessionIDValue";
+ Mockito.when(session.getAttribute(ApiConstants.SESSIONKEY)).thenReturn(sessionKeyValue);
+ Mockito.when(session.getAttribute("userid")).thenReturn(2L);
+ params.put(ApiConstants.USER_ID, new String[]{"2"});
+ params.put(ApiConstants.DOMAIN_ID, new String[]{"1"});
+ Mockito.when(userDao.findByUuid(Mockito.anyString())).thenReturn(new UserVO(2L));
+ Mockito.when(domainDao.findByUuid(Mockito.anyString())).thenReturn(new DomainVO());
+
+ // Mock/field setup
+ ListAndSwitchSAMLAccountCmd cmd = new ListAndSwitchSAMLAccountCmd();
+ Field apiServerField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_apiServer");
+ apiServerField.setAccessible(true);
+ apiServerField.set(cmd, apiServer);
+
+ Field managerField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_samlAuthManager");
+ managerField.setAccessible(true);
+ managerField.set(cmd, samlAuthManager);
+
+ Field accountServiceField = BaseCmd.class.getDeclaredField("_accountService");
+ accountServiceField.setAccessible(true);
+ accountServiceField.set(cmd, accountService);
+
+ Field userAccountDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_userAccountDao");
+ userAccountDaoField.setAccessible(true);
+ userAccountDaoField.set(cmd, userAccountDao);
+
+ Field userDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_userDao");
+ userDaoField.setAccessible(true);
+ userDaoField.set(cmd, userDao);
+
+ Field domainDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_domainDao");
+ domainDaoField.setAccessible(true);
+ domainDaoField.set(cmd, domainDao);
+
+ // invalid session test
+ try {
+ cmd.authenticate("command", params, null, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ } catch (ServerApiException exception) {
+ assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
+ } finally {
+ Mockito.verify(accountService, Mockito.times(0)).getUserAccountById(Mockito.anyLong());
+ }
+
+ // invalid sessionkey value test
+ params.put(ApiConstants.SESSIONKEY, new String[]{"someOtherValue"});
+ try {
+ Mockito.when(session.isNew()).thenReturn(false);
+ cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ } catch (ServerApiException exception) {
+ assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
+ } finally {
+ Mockito.verify(accountService, Mockito.times(0)).getUserAccountById(Mockito.anyLong());
+ }
+
+ // valid sessionkey value test
+ params.put(ApiConstants.SESSIONKEY, new String[]{sessionKeyValue});
+ try {
+ cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ } catch (ServerApiException exception) {
+ assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
+ } finally {
+ Mockito.verify(accountService, Mockito.times(1)).getUserAccountById(Mockito.anyLong());
+ }
+
+ // valid sessionkey, invalid useraccount type (non-saml) value test
+ UserAccountVO mockedUserAccount = new UserAccountVO();
+ mockedUserAccount.setId(2L);
+ mockedUserAccount.setAccountState(Account.State.enabled.toString());
+ mockedUserAccount.setUsername("someUsername");
+ mockedUserAccount.setExternalEntity("some IDP ID");
+ mockedUserAccount.setDomainId(0L);
+ mockedUserAccount.setSource(User.Source.UNKNOWN);
+ Mockito.when(accountService.getUserAccountById(Mockito.anyLong())).thenReturn(mockedUserAccount);
+ try {
+ cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ } catch (ServerApiException exception) {
+ assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
+ } finally {
+ // accountService should have been called twice by now, for this case and the case above
+ Mockito.verify(accountService, Mockito.times(2)).getUserAccountById(Mockito.anyLong());
+ }
+
+ // all valid test
+ mockedUserAccount.setSource(User.Source.SAML2);
+ Mockito.when(accountService.getUserAccountById(Mockito.anyLong())).thenReturn(mockedUserAccount);
+ Mockito.when(apiServer.verifyUser(Mockito.anyLong())).thenReturn(true);
+ LoginCmdResponse loginCmdResponse = new LoginCmdResponse();
+ loginCmdResponse.setUserId("1");
+ loginCmdResponse.setDomainId("1");
+ loginCmdResponse.setType("1");
+ loginCmdResponse.setUsername("userName");
+ loginCmdResponse.setAccount("someAccount");
+ loginCmdResponse.setFirstName("firstName");
+ loginCmdResponse.setLastName("lastName");
+ loginCmdResponse.setSessionKey("newSessionKeyString");
+ Mockito.when(apiServer.loginUser(Mockito.any(HttpSession.class), Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())).thenReturn(loginCmdResponse);
+ try {
+ cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ } catch (ServerApiException exception) {
+ fail("SAML list and switch account API failed to pass for all valid data: " + exception.getMessage());
+ } finally {
+ // accountService should have been called 4 times by now, for this case twice and 2 for cases above
+ Mockito.verify(accountService, Mockito.times(4)).getUserAccountById(Mockito.anyLong());
+ Mockito.verify(resp, Mockito.times(1)).sendRedirect(Mockito.anyString());
+ }
+ }
+
+ @Test
+ public void testGetAPIType() {
+ Assert.assertTrue(new ListAndSwitchSAMLAccountCmd().getAPIType() == APIAuthenticationType.READONLY_API);
+ }
+
+}
[8/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
plugins: fix test case, interface usage and checkstyle import issue
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/869a83f8
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/869a83f8
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/869a83f8
Branch: refs/heads/master
Commit: 869a83f8f8d8a69f2029c3219bad180965adcb1c
Parents: a3e6942
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Aug 14 12:16:09 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 12:23:50 2015 +0530
----------------------------------------------------------------------
.../kvm/resource/LibvirtComputingResourceTest.java | 4 ++--
.../api/command/ListAndSwitchSAMLAccountCmd.java | 3 ++-
.../api/command/SAML2LoginAPIAuthenticatorCmd.java | 2 --
.../api/command/ListAndSwitchSAMLAccountCmdTest.java | 13 +++++++------
4 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/869a83f8/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
index 42ebf86..1651299 100644
--- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
+++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
@@ -1246,7 +1246,7 @@ public class LibvirtComputingResourceTest {
when(conn.domainLookupByName(vmName)).thenReturn(dm);
when(libvirtComputingResource.getPrivateIp()).thenReturn("127.0.0.1");
- when(dm.getXMLDesc(0)).thenReturn("host_domain");
+ when(dm.getXMLDesc(8)).thenReturn("host_domain");
when(dm.isPersistent()).thenReturn(1);
doNothing().when(dm).undefine();
@@ -1274,7 +1274,7 @@ public class LibvirtComputingResourceTest {
verify(libvirtComputingResource, times(1)).getDisks(conn, vmName);
try {
verify(conn, times(1)).domainLookupByName(vmName);
- verify(dm, times(1)).getXMLDesc(0);
+ verify(dm, times(1)).getXMLDesc(8);
} catch (final LibvirtException e) {
fail(e.getMessage());
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/869a83f8/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
index 80aee1b..2fdf6a1 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
@@ -52,6 +52,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
+import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -99,7 +100,7 @@ public class ListAndSwitchSAMLAccountCmd extends BaseCmd implements APIAuthentic
}
@Override
- public String authenticate(final String command, final Map<String, Object[]> params, final HttpSession session, final String remoteAddress, final String responseType, final StringBuilder auditTrailSb, final HttpServletRequest req, final HttpServletResponse resp) throws ServerApiException {
+ public String authenticate(final String command, final Map<String, Object[]> params, final HttpSession session, InetAddress remoteAddress, final String responseType, final StringBuilder auditTrailSb, final HttpServletRequest req, final HttpServletResponse resp) throws ServerApiException {
if (session == null || session.isNew()) {
throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, _apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED.getHttpCode(),
"Only authenticated saml users can request this API",
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/869a83f8/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 7a1b83c..41005ab 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
@@ -70,8 +70,6 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.FactoryConfigurationError;
import java.io.IOException;
import java.net.InetAddress;
-import java.net.URLEncoder;
-
import java.util.List;
import java.util.Map;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/869a83f8/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
index 1423243..8985a0f 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
@@ -49,6 +49,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
+import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
@@ -121,7 +122,7 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
// invalid session test
try {
- cmd.authenticate("command", params, null, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ cmd.authenticate("command", params, null, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
} finally {
@@ -132,7 +133,7 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
params.put(ApiConstants.SESSIONKEY, new String[]{"someOtherValue"});
try {
Mockito.when(session.isNew()).thenReturn(false);
- cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
} finally {
@@ -142,7 +143,7 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
// valid sessionkey value test
params.put(ApiConstants.SESSIONKEY, new String[]{sessionKeyValue});
try {
- cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
} finally {
@@ -159,7 +160,7 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
mockedUserAccount.setSource(User.Source.UNKNOWN);
Mockito.when(accountService.getUserAccountById(Mockito.anyLong())).thenReturn(mockedUserAccount);
try {
- cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
} finally {
@@ -181,9 +182,9 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
loginCmdResponse.setLastName("lastName");
loginCmdResponse.setSessionKey("newSessionKeyString");
Mockito.when(apiServer.loginUser(Mockito.any(HttpSession.class), Mockito.anyString(), Mockito.anyString(),
- Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())).thenReturn(loginCmdResponse);
+ Mockito.anyLong(), Mockito.anyString(), Mockito.any(InetAddress.class), Mockito.anyMap())).thenReturn(loginCmdResponse);
try {
- cmd.authenticate("command", params, session, "random", HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+ cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
fail("SAML list and switch account API failed to pass for all valid data: " + exception.getMessage());
} finally {
[3/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
CLOUDSTACK-8701: Add administrative contact block as per SAML IDP expectations
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit 1e3e67451489789949e1b50e1f0732bcba0596b5)
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/da72ba6e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/da72ba6e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/da72ba6e
Branch: refs/heads/master
Commit: da72ba6e1b95ab867c1ee88f7dac3efb0051e10d
Parents: 1ec4d01
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Sun Aug 9 00:13:51 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 11:59:16 2015 +0530
----------------------------------------------------------------------
.../api/command/GetServiceProviderMetaDataCmd.java | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/da72ba6e/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
index a6cefb1..89e3f31 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/GetServiceProviderMetaDataCmd.java
@@ -206,16 +206,28 @@ public class GetServiceProviderMetaDataCmd extends BaseCmd implements APIAuthent
spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor);
- ContactPerson contactPerson = new ContactPersonBuilder().buildObject();
+ // Add technical contact
GivenName givenName = new GivenNameBuilder().buildObject();
givenName.setName(spMetadata.getContactPersonName());
EmailAddress emailAddress = new EmailAddressBuilder().buildObject();
emailAddress.setAddress(spMetadata.getContactPersonEmail());
+ ContactPerson contactPerson = new ContactPersonBuilder().buildObject();
contactPerson.setType(ContactPersonTypeEnumeration.TECHNICAL);
contactPerson.setGivenName(givenName);
contactPerson.getEmailAddresses().add(emailAddress);
spEntityDescriptor.getContactPersons().add(contactPerson);
+ // Add administrative/support contact
+ GivenName givenNameAdmin = new GivenNameBuilder().buildObject();
+ givenNameAdmin.setName(spMetadata.getContactPersonName());
+ EmailAddress emailAddressAdmin = new EmailAddressBuilder().buildObject();
+ emailAddressAdmin.setAddress(spMetadata.getContactPersonEmail());
+ ContactPerson contactPersonAdmin = new ContactPersonBuilder().buildObject();
+ contactPersonAdmin.setType(ContactPersonTypeEnumeration.ADMINISTRATIVE);
+ contactPersonAdmin.setGivenName(givenNameAdmin);
+ contactPersonAdmin.getEmailAddresses().add(emailAddressAdmin);
+ spEntityDescriptor.getContactPersons().add(contactPersonAdmin);
+
Organization organization = new OrganizationBuilder().buildObject();
OrganizationName organizationName = new OrganizationNameBuilder().buildObject();
organizationName.setName(new LocalizedString(spMetadata.getOrganizationName(), Locale.getDefault().getLanguage()));
[5/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
engine: fix accountState setter name
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit 3c9d1fdf5de5b9bcf62a1f2bfbfbcf458a0f31b6)
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/fcbee609
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/fcbee609
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/fcbee609
Branch: refs/heads/master
Commit: fcbee609b4a4b134b4472b6c53d3e4b980932578
Parents: 1d190fd
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Wed Aug 12 14:03:17 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 11:59:47 2015 +0530
----------------------------------------------------------------------
engine/schema/src/com/cloud/user/UserAccountVO.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fcbee609/engine/schema/src/com/cloud/user/UserAccountVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/user/UserAccountVO.java b/engine/schema/src/com/cloud/user/UserAccountVO.java
index 80ee873..5ce0eb7 100644
--- a/engine/schema/src/com/cloud/user/UserAccountVO.java
+++ b/engine/schema/src/com/cloud/user/UserAccountVO.java
@@ -251,7 +251,7 @@ public class UserAccountVO implements UserAccount, InternalIdentity {
return accountState;
}
- public void setAccountDisabled(String accountState) {
+ public void setAccountState(String accountState) {
this.accountState = accountState;
}
[4/8] git commit: updated refs/heads/master to 869a83f
Posted by bh...@apache.org.
utils: add HttpUtils test
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit 0fcd9cad1e4a687c275095d6e27bdfb3eff4add8)
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/1d190fd0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1d190fd0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1d190fd0
Branch: refs/heads/master
Commit: 1d190fd0bb637bde14454fa5d4b4def1b4d0fe6a
Parents: da72ba6
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Wed Aug 12 14:02:57 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Aug 14 11:59:31 2015 +0530
----------------------------------------------------------------------
utils/src/com/cloud/utils/HttpUtils.java | 32 +++++---
utils/test/com/cloud/utils/HttpUtilsTest.java | 94 ++++++++++++++++++++++
2 files changed, 113 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1d190fd0/utils/src/com/cloud/utils/HttpUtils.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/HttpUtils.java b/utils/src/com/cloud/utils/HttpUtils.java
index 379b117..d2e844a 100644
--- a/utils/src/com/cloud/utils/HttpUtils.java
+++ b/utils/src/com/cloud/utils/HttpUtils.java
@@ -52,18 +52,6 @@ public class HttpUtils {
}
}
- public static String findCookie(final Cookie[] cookies, final String key) {
- if (cookies == null || key == null || key.isEmpty()) {
- return null;
- }
- for (Cookie cookie: cookies) {
- if (cookie != null && cookie.getName().equals(key)) {
- return cookie.getValue();
- }
- }
- return null;
- }
-
public static void writeHttpResponse(final HttpServletResponse resp, final String response,
final Integer responseCode, final String responseType, final String jsonContentType) {
try {
@@ -92,10 +80,28 @@ public class HttpUtils {
}
}
+ public static String findCookie(final Cookie[] cookies, final String key) {
+ if (cookies == null || key == null || key.isEmpty()) {
+ return null;
+ }
+ for (Cookie cookie: cookies) {
+ if (cookie != null && cookie.getName().equals(key)) {
+ return cookie.getValue();
+ }
+ }
+ return null;
+ }
+
public static boolean validateSessionKey(final HttpSession session, final Map<String, Object[]> params, final Cookie[] cookies, final String sessionKeyString) {
+ if (session == null || sessionKeyString == null) {
+ return false;
+ }
final String sessionKey = (String) session.getAttribute(sessionKeyString);
final String sessionKeyFromCookie = HttpUtils.findCookie(cookies, sessionKeyString);
- final String[] sessionKeyFromParams = (String[]) params.get(sessionKeyString);
+ String[] sessionKeyFromParams = null;
+ if (params != null) {
+ sessionKeyFromParams = (String[]) params.get(sessionKeyString);
+ }
if ((sessionKey == null)
|| (sessionKeyFromParams == null && sessionKeyFromCookie == null)
|| (sessionKeyFromParams != null && !sessionKey.equals(sessionKeyFromParams[0]))
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1d190fd0/utils/test/com/cloud/utils/HttpUtilsTest.java
----------------------------------------------------------------------
diff --git a/utils/test/com/cloud/utils/HttpUtilsTest.java b/utils/test/com/cloud/utils/HttpUtilsTest.java
new file mode 100644
index 0000000..e10a5a3
--- /dev/null
+++ b/utils/test/com/cloud/utils/HttpUtilsTest.java
@@ -0,0 +1,94 @@
+//
+// 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.cloud.utils;
+
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpSession;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpSession;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class HttpUtilsTest {
+
+ @Test
+ public void findCookieTest() {
+ Cookie[] cookies = null;
+ String cookieName = null;
+
+ // null test
+ assertNull(HttpUtils.findCookie(cookies, cookieName));
+ cookieName = "";
+ assertNull(HttpUtils.findCookie(cookies, cookieName));
+
+ // value test
+ cookieName = "daakuBandar";
+ cookies = new Cookie[]{new Cookie(cookieName, "someValue")};
+ assertNull(HttpUtils.findCookie(cookies, "aalasiLangur"));
+ assertNotNull(HttpUtils.findCookie(cookies, cookieName));
+ }
+
+ @Test
+ public void validateSessionKeyTest() {
+ HttpSession session = null;
+ Map<String, Object[]> params = null;
+ String sessionKeyString = null;
+ Cookie[] cookies = null;
+ final String sessionKeyValue = "randomUniqueSessionID";
+
+ // session and sessionKeyString null test
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+ sessionKeyString = "sessionkey";
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+
+ // param and cookie null test
+ session = new MockHttpSession();
+ session.setAttribute(sessionKeyString, sessionKeyValue);
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+
+ // param null, cookies not null test
+ params = null;
+ cookies = new Cookie[]{new Cookie(sessionKeyString, sessionKeyValue)};
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, "randomString"));
+ assertTrue(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+
+ // param not null, cookies null test
+ params = new HashMap<String, Object[]>();
+ params.put(sessionKeyString, new String[]{"randomString"});
+ cookies = null;
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+ params.put(sessionKeyString, new String[]{sessionKeyValue});
+ assertTrue(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+
+ // both param and cookies not null test
+ params = new HashMap<String, Object[]>();
+ cookies = new Cookie[]{new Cookie(sessionKeyString, sessionKeyValue)};
+ params.put(sessionKeyString, new String[]{"incorrectValue"});
+ assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+ params.put(sessionKeyString, new String[]{sessionKeyValue});
+ assertTrue(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString));
+ }
+}