api: add method to pass on api authenticators to cmd classes Signed-off-by: Rohit Yadav <rohit.ya...@shapeblue.com>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/47ccce85 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/47ccce85 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/47ccce85 Branch: refs/heads/master Commit: 47ccce85a12ef4932b67359e20c2fba7c192ff1c Parents: 8e6cb04 Author: Rohit Yadav <rohit.ya...@shapeblue.com> Authored: Sun Aug 24 20:47:43 2014 +0200 Committer: Rohit Yadav <rohit.ya...@shapeblue.com> Committed: Thu Aug 28 19:45:24 2014 +0200 ---------------------------------------------------------------------- .../cloudstack/api/auth/APIAuthenticator.java | 4 +++ .../command/SAML2LoginAPIAuthenticatorCmd.java | 38 +++++++++++++++++--- .../api/auth/APIAuthenticationManagerImpl.java | 1 + .../auth/DefaultLoginAPIAuthenticatorCmd.java | 6 ++++ .../auth/DefaultLogoutAPIAuthenticatorCmd.java | 6 ++++ server/src/com/cloud/configuration/Config.java | 2 +- 6 files changed, 51 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/api/src/org/apache/cloudstack/api/auth/APIAuthenticator.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/auth/APIAuthenticator.java b/api/src/org/apache/cloudstack/api/auth/APIAuthenticator.java index b008f00..67fa1d8 100644 --- a/api/src/org/apache/cloudstack/api/auth/APIAuthenticator.java +++ b/api/src/org/apache/cloudstack/api/auth/APIAuthenticator.java @@ -20,6 +20,7 @@ import org.apache.cloudstack.api.ServerApiException; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.util.List; import java.util.Map; /* @@ -36,5 +37,8 @@ public interface APIAuthenticator { public String authenticate(String command, Map<String, Object[]> params, HttpSession session, String remoteAddress, String responseType, StringBuilder auditTrailSb, final HttpServletResponse resp) throws ServerApiException; + public APIAuthenticationType getAPIType(); + + public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/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 ec3a4d2..88acfe1 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 @@ -32,6 +32,7 @@ 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.LoginCmdResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.saml.SAML2AuthManager; @@ -49,7 +50,10 @@ import org.opensaml.saml2.core.StatusCode; import org.opensaml.xml.ConfigurationException; import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.io.UnmarshallingException; +import org.opensaml.xml.security.x509.BasicX509Credential; import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureValidator; +import org.opensaml.xml.validation.ValidationException; import org.xml.sax.SAXException; import javax.inject.Inject; @@ -80,7 +84,7 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent ApiServerService _apiServer; @Inject EntityManager _entityMgr; - @Inject + SAML2AuthManager _samlAuthManager; ///////////////////////////////////////////////////// @@ -135,9 +139,10 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent public Response processSAMLResponse(String responseMessage) { Response responseObject = null; try { + DefaultBootstrap.bootstrap(); responseObject = SAMLUtils.decodeSAMLResponse(responseMessage); - } catch (ConfigurationException | ParserConfigurationException | SAXException | IOException | UnmarshallingException e) { + } catch (ConfigurationException | FactoryConfigurationError | ParserConfigurationException | SAXException | IOException | UnmarshallingException e) { s_logger.error("SAMLResponse processing error: " + e.getMessage()); } return responseObject; @@ -165,9 +170,20 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent params, responseType)); } - Signature sig = processedSAMLResponse.getSignature(); - //SignatureValidator validator = new SignatureValidator(credential); - //validator.validate(sig); + if (_samlAuthManager.getIdpSigningKey() != null) { + Signature sig = processedSAMLResponse.getSignature(); + BasicX509Credential credential = new BasicX509Credential(); + credential.setEntityCertificate(_samlAuthManager.getIdpSigningKey()); + SignatureValidator validator = new SignatureValidator(credential); + try { + validator.validate(sig); + } catch (ValidationException e) { + s_logger.error("SAML Response's signature failed to be validated by IDP signing key:" + e.getMessage()); + throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), + "SAML Response's signature failed to be validated by IDP signing key", + params, responseType)); + } + } String uniqueUserId = null; String accountName = "admin"; //GET from config, try, fail @@ -251,4 +267,16 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent public APIAuthenticationType getAPIType() { return APIAuthenticationType.LOGIN_API; } + + @Override + public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) { + for (PluggableAPIAuthenticator authManager: authenticators) { + if (authManager instanceof SAML2AuthManager) { + _samlAuthManager = (SAML2AuthManager) authManager; + } + } + if (_samlAuthManager == null) { + s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 Login Cmd"); + } + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/server/src/com/cloud/api/auth/APIAuthenticationManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/auth/APIAuthenticationManagerImpl.java b/server/src/com/cloud/api/auth/APIAuthenticationManagerImpl.java index 790b6d9..24ccbeb 100644 --- a/server/src/com/cloud/api/auth/APIAuthenticationManagerImpl.java +++ b/server/src/com/cloud/api/auth/APIAuthenticationManagerImpl.java @@ -81,6 +81,7 @@ public class APIAuthenticationManagerImpl extends ManagerBase implements APIAuth try { apiAuthenticator = (APIAuthenticator) s_authenticators.get(name).newInstance(); apiAuthenticator = ComponentContext.inject(apiAuthenticator); + apiAuthenticator.setAuthenticators(_apiAuthenticators); } catch (InstantiationException | IllegalAccessException e) { if (s_logger.isDebugEnabled()) { s_logger.debug("APIAuthenticationManagerImpl::getAPIAuthenticator failed: " + e.getMessage()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/server/src/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java b/server/src/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java index 2fb3f56..fa23abd 100644 --- a/server/src/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java +++ b/server/src/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java @@ -28,12 +28,14 @@ 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.LoginCmdResponse; import org.apache.log4j.Logger; import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.util.List; import java.util.Map; @APICommand(name = "login", description = "Logs a user into the CloudStack. A successful login attempt will generate a JSESSIONID cookie value that can be passed in subsequent Query command calls until the \"logout\" command has been issued or the session has expired.", requestHasSensitiveInfo = true, responseObject = LoginCmdResponse.class, entityType = {}) @@ -172,4 +174,8 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthe public APIAuthenticationType getAPIType() { return APIAuthenticationType.LOGIN_API; } + + @Override + public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) { + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/server/src/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java b/server/src/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java index 999cefd..ee7936a 100644 --- a/server/src/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java +++ b/server/src/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java @@ -24,11 +24,13 @@ import org.apache.cloudstack.api.BaseCmd; 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.LogoutCmdResponse; import org.apache.log4j.Logger; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.util.List; import java.util.Map; @APICommand(name = "logout", description = "Logs out the user", responseObject = LogoutCmdResponse.class, entityType = {}) @@ -70,4 +72,8 @@ public class DefaultLogoutAPIAuthenticatorCmd extends BaseCmd implements APIAuth public APIAuthenticationType getAPIType() { return APIAuthenticationType.LOGOUT_API; } + + @Override + public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) { + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/47ccce85/server/src/com/cloud/configuration/Config.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index b2fb85f..de4aaed 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -1384,7 +1384,7 @@ public enum Config { ManagementServer.class, String.class, "saml2.sp.id", - "Apache CloudStack", + "org.apache.cloudstack", "SAML2 Service Provider Identifier String", null), SAMLServiceProviderSingleSignOnURL(