Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 20C5611886 for ; Thu, 28 Aug 2014 17:58:15 +0000 (UTC) Received: (qmail 30087 invoked by uid 500); 28 Aug 2014 17:58:06 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 30009 invoked by uid 500); 28 Aug 2014 17:58:06 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 29130 invoked by uid 99); 28 Aug 2014 17:58:06 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Aug 2014 17:58:06 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id DD6F5A04DED; Thu, 28 Aug 2014 17:58:05 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: bhaisaab@apache.org To: commits@cloudstack.apache.org Date: Thu, 28 Aug 2014 17:58:31 -0000 Message-Id: <6e990887119e49168fcf407583b6da55@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [27/50] git commit: updated refs/heads/master to 97ed5ff saml: Have the plugin use IDP metadata from URL, get values from Config Signed-off-by: Rohit Yadav Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/06e90992 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/06e90992 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/06e90992 Branch: refs/heads/master Commit: 06e909923a604a348c9ff18380a868b96145c6e2 Parents: 1b0f81e Author: Rohit Yadav Authored: Sun Aug 24 17:34:20 2014 +0200 Committer: Rohit Yadav Committed: Thu Aug 28 19:45:24 2014 +0200 ---------------------------------------------------------------------- .../cloudstack/saml2/spring-saml2-context.xml | 2 +- .../command/SAML2LoginAPIAuthenticatorCmd.java | 28 +++- .../cloudstack/saml/SAML2AuthManagerImpl.java | 131 +++++++++++++++++++ .../cloudstack/saml/SAML2AuthServiceImpl.java | 51 -------- 4 files changed, 153 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/06e90992/plugins/user-authenticators/saml2/resources/META-INF/cloudstack/saml2/spring-saml2-context.xml ---------------------------------------------------------------------- diff --git a/plugins/user-authenticators/saml2/resources/META-INF/cloudstack/saml2/spring-saml2-context.xml b/plugins/user-authenticators/saml2/resources/META-INF/cloudstack/saml2/spring-saml2-context.xml index 15e085d..92f89b8 100644 --- a/plugins/user-authenticators/saml2/resources/META-INF/cloudstack/saml2/spring-saml2-context.xml +++ b/plugins/user-authenticators/saml2/resources/META-INF/cloudstack/saml2/spring-saml2-context.xml @@ -29,7 +29,7 @@ - + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/06e90992/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 463df7d..ec3a4d2 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,7 +17,6 @@ package org.apache.cloudstack.api.command; -import org.apache.cloudstack.api.ApiServerService; import com.cloud.api.response.ApiResponseSerializer; import com.cloud.exception.CloudAuthenticationException; import com.cloud.user.Account; @@ -27,6 +26,7 @@ import com.cloud.utils.db.EntityManager; 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; @@ -34,6 +34,7 @@ import org.apache.cloudstack.api.auth.APIAuthenticationType; import org.apache.cloudstack.api.auth.APIAuthenticator; import org.apache.cloudstack.api.response.LoginCmdResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.saml.SAML2AuthManager; import org.apache.cloudstack.utils.auth.SAMLUtils; import org.apache.log4j.Logger; import org.opensaml.DefaultBootstrap; @@ -79,6 +80,8 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent ApiServerService _apiServer; @Inject EntityManager _entityMgr; + @Inject + SAML2AuthManager _samlAuthManager; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -108,13 +111,20 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent throw new ServerApiException(ApiErrorCode.METHOD_NOT_ALLOWED, "This is an authentication api, cannot be used directly"); } - public String buildAuthnRequestUrl(String consumerUrl, String identityProviderUrl) { - String randomId = new BigInteger(130, new SecureRandom()).toString(32); - String spId = "org.apache.cloudstack"; + public String buildAuthnRequestUrl(String idpUrl) { + String randomSecureId = new BigInteger(130, new SecureRandom()).toString(32); + String spId = _samlAuthManager.getServiceProviderId(); + String consumerUrl = _samlAuthManager.getSpSingleSignOnUrl(); + String identityProviderUrl = _samlAuthManager.getIdpSingleSignOnUrl(); + + if (idpUrl != null) { + identityProviderUrl = idpUrl; + } + String redirectUrl = ""; try { DefaultBootstrap.bootstrap(); - AuthnRequest authnRequest = SAMLUtils.buildAuthnRequestObject(randomId, spId, identityProviderUrl, consumerUrl); + AuthnRequest authnRequest = SAMLUtils.buildAuthnRequestObject(randomSecureId, spId, identityProviderUrl, consumerUrl); redirectUrl = identityProviderUrl + "?SAMLRequest=" + SAMLUtils.encodeSAMLRequest(authnRequest); } catch (ConfigurationException | FactoryConfigurationError | MarshallingException | IOException e) { s_logger.error("SAML AuthnRequest message building error: " + e.getMessage()); @@ -137,8 +147,12 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent public String authenticate(final String command, final Map params, final HttpSession session, final String remoteAddress, final String responseType, final StringBuilder auditTrailSb, final HttpServletResponse resp) throws ServerApiException { try { if (!params.containsKey("SAMLResponse")) { - final String[] idps = (String[])params.get("idpurl"); - String redirectUrl = buildAuthnRequestUrl("http://localhost:8080/client/api?command=samlsso", idps[0]); + String idpUrl = null; + final String[] idps = (String[])params.get(ApiConstants.IDP_URL); + if (idps != null && idps.length > 0) { + idpUrl = idps[0]; + } + String redirectUrl = buildAuthnRequestUrl(idpUrl); resp.sendRedirect(redirectUrl); return ""; } else { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/06e90992/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 new file mode 100644 index 0000000..41595b6 --- /dev/null +++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java @@ -0,0 +1,131 @@ +// 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.saml; + +import com.cloud.configuration.Config; +import com.cloud.utils.component.AdapterBase; +import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator; +import org.apache.cloudstack.api.command.SAML2LoginAPIAuthenticatorCmd; +import org.apache.cloudstack.api.command.SAML2LogoutAPIAuthenticatorCmd; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.xml.parse.BasicParserPool; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; + +@Component +@Local(value = {PluggableAPIAuthenticator.class, SAML2AuthManager.class}) +public class SAML2AuthManagerImpl extends AdapterBase implements PluggableAPIAuthenticator, SAML2AuthManager { + private static final Logger s_logger = Logger.getLogger(SAML2AuthManagerImpl.class); + + private String serviceProviderId; + private String spSingleSignOnUrl; + private String spSingleLogOutUrl; + + private String idpSingleSignOnUrl; + private String idpSingleLogOutUrl; + + @Inject + ConfigurationDao _configDao; + + protected SAML2AuthManagerImpl() { + super(); + } + + @Override + public boolean start() { + this.serviceProviderId = _configDao.getValue(Config.SAMLServiceProviderID.key()); + this.spSingleSignOnUrl = _configDao.getValue(Config.SAMLServiceProviderSingleSignOnURL.key()); + this.spSingleLogOutUrl = _configDao.getValue(Config.SAMLServiceProviderSingleLogOutURL.key()); + + String idpMetaDataUrl = _configDao.getValue(Config.SAMLIdentityProviderMetadataURL.key()); + + int tolerance = 30000; + String timeout = _configDao.getValue(Config.SAMLTimeout.key()); + if (timeout != null) { + tolerance = Integer.parseInt(timeout); + } + + try { + HTTPMetadataProvider idpMetaDataProvider = new HTTPMetadataProvider(idpMetaDataUrl, tolerance); + + idpMetaDataProvider.setRequireValidMetadata(true); + idpMetaDataProvider.setParserPool(new BasicParserPool()); + idpMetaDataProvider.initialize(); + + EntityDescriptor idpEntityDescriptor = idpMetaDataProvider.getEntityDescriptor("Some entity id"); + for (SingleSignOnService ssos: idpEntityDescriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { + if (ssos.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + this.idpSingleSignOnUrl = ssos.getLocation(); + } + } + for (SingleLogoutService slos: idpEntityDescriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleLogoutServices()) { + if (slos.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + this.idpSingleLogOutUrl = slos.getLocation(); + } + } + + } catch (MetadataProviderException e) { + s_logger.error("Unable to read SAML2 IDP MetaData URL, error:" + e.getMessage()); + s_logger.error("SAML2 Authentication may be unavailable"); + } + + if (this.idpSingleLogOutUrl == null || this.idpSingleSignOnUrl == null) { + s_logger.error("The current IDP does not support HTTP redirected authentication, SAML based authentication cannot work with this IDP"); + } + + return true; + } + + @Override + public List> getAuthCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(SAML2LoginAPIAuthenticatorCmd.class); + cmdList.add(SAML2LogoutAPIAuthenticatorCmd.class); + return cmdList; + } + + public String getServiceProviderId() { + return serviceProviderId; + } + + public String getIdpSingleSignOnUrl() { + return this.idpSingleSignOnUrl; + } + + public String getIdpSingleLogOutUrl() { + return this.idpSingleLogOutUrl; + } + + public String getSpSingleSignOnUrl() { + return spSingleSignOnUrl; + } + + public String getSpSingleLogOutUrl() { + return spSingleLogOutUrl; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/06e90992/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthServiceImpl.java ---------------------------------------------------------------------- diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthServiceImpl.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthServiceImpl.java deleted file mode 100644 index 44e29ca..0000000 --- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -// 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.saml; - -import com.cloud.utils.component.AdapterBase; -import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator; -import org.apache.cloudstack.api.command.SAML2LoginAPIAuthenticatorCmd; -import org.apache.cloudstack.api.command.SAML2LogoutAPIAuthenticatorCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import java.util.ArrayList; -import java.util.List; - -@Component -@Local(value = PluggableAPIAuthenticator.class) -public class SAML2AuthServiceImpl extends AdapterBase implements PluggableAPIAuthenticator { - private static final Logger s_logger = Logger.getLogger(SAML2AuthServiceImpl.class); - - protected SAML2AuthServiceImpl() { - super(); - } - - @Override - public boolean start() { - return true; - } - - @Override - public List> getAuthCommands() { - List> cmdList = new ArrayList>(); - cmdList.add(SAML2LoginAPIAuthenticatorCmd.class); - cmdList.add(SAML2LogoutAPIAuthenticatorCmd.class); - return cmdList; - } -}