mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
saml: Implement logic to check response against X509 keys
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
47ccce85a1
commit
7687b7311a
@ -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 = "samlslo", description = "SAML Global Log Out API", responseObject = LogoutCmdResponse.class, entityType = {})
|
||||
@ -70,4 +72,8 @@ public class SAML2LogoutAPIAuthenticatorCmd extends BaseCmd implements APIAuthen
|
||||
public APIAuthenticationType getAPIType() {
|
||||
return APIAuthenticationType.LOGOUT_API;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,11 +17,20 @@
|
||||
|
||||
package org.apache.cloudstack.saml;
|
||||
|
||||
public interface SAML2AuthManager {
|
||||
public String getServiceProviderId();
|
||||
public String getSpSingleSignOnUrl();
|
||||
public String getSpSingleLogOutUrl();
|
||||
import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public interface SAML2AuthManager extends PluggableAPIAuthenticator {
|
||||
public String getServiceProviderId();
|
||||
public String getIdentityProviderId();
|
||||
|
||||
public X509Certificate getIdpSigningKey();
|
||||
public X509Certificate getIdpEncryptionKey();
|
||||
|
||||
public String getSpSingleSignOnUrl();
|
||||
public String getIdpSingleSignOnUrl();
|
||||
|
||||
public String getSpSingleLogOutUrl();
|
||||
public String getIdpSingleLogOutUrl();
|
||||
}
|
||||
|
||||
@ -23,32 +23,48 @@ 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.DefaultBootstrap;
|
||||
import org.opensaml.common.xml.SAMLConstants;
|
||||
import org.opensaml.saml2.metadata.EntityDescriptor;
|
||||
import org.opensaml.saml2.metadata.IDPSSODescriptor;
|
||||
import org.opensaml.saml2.metadata.KeyDescriptor;
|
||||
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.ConfigurationException;
|
||||
import org.opensaml.xml.parse.BasicParserPool;
|
||||
import org.opensaml.xml.security.credential.UsageType;
|
||||
import org.opensaml.xml.security.keyinfo.KeyInfoHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.xml.stream.FactoryConfigurationError;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = {PluggableAPIAuthenticator.class, SAML2AuthManager.class})
|
||||
public class SAML2AuthManagerImpl extends AdapterBase implements PluggableAPIAuthenticator, SAML2AuthManager {
|
||||
@Local(value = {SAML2AuthManager.class, PluggableAPIAuthenticator.class})
|
||||
public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManager {
|
||||
private static final Logger s_logger = Logger.getLogger(SAML2AuthManagerImpl.class);
|
||||
|
||||
private String serviceProviderId;
|
||||
private String spSingleSignOnUrl;
|
||||
private String spSingleLogOutUrl;
|
||||
private String identityProviderId;
|
||||
|
||||
private X509Certificate idpSigningKey;
|
||||
private X509Certificate idpEncryptionKey;
|
||||
|
||||
private String spSingleSignOnUrl;
|
||||
private String idpSingleSignOnUrl;
|
||||
|
||||
private String spSingleLogOutUrl;
|
||||
private String idpSingleLogOutUrl;
|
||||
|
||||
private HTTPMetadataProvider idpMetaDataProvider;
|
||||
|
||||
@Inject
|
||||
ConfigurationDao _configDao;
|
||||
|
||||
@ -59,6 +75,8 @@ public class SAML2AuthManagerImpl extends AdapterBase implements PluggableAPIAut
|
||||
@Override
|
||||
public boolean start() {
|
||||
this.serviceProviderId = _configDao.getValue(Config.SAMLServiceProviderID.key());
|
||||
this.identityProviderId = _configDao.getValue(Config.SAMLIdentityProviderID.key());
|
||||
|
||||
this.spSingleSignOnUrl = _configDao.getValue(Config.SAMLServiceProviderSingleSignOnURL.key());
|
||||
this.spSingleLogOutUrl = _configDao.getValue(Config.SAMLServiceProviderSingleLogOutURL.key());
|
||||
|
||||
@ -71,31 +89,54 @@ public class SAML2AuthManagerImpl extends AdapterBase implements PluggableAPIAut
|
||||
}
|
||||
|
||||
try {
|
||||
HTTPMetadataProvider idpMetaDataProvider = new HTTPMetadataProvider(idpMetaDataUrl, tolerance);
|
||||
|
||||
DefaultBootstrap.bootstrap();
|
||||
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();
|
||||
}
|
||||
}
|
||||
EntityDescriptor idpEntityDescriptor = idpMetaDataProvider.getEntityDescriptor(this.identityProviderId);
|
||||
|
||||
IDPSSODescriptor idpssoDescriptor = idpEntityDescriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
|
||||
if (idpssoDescriptor != null) {
|
||||
for (SingleSignOnService ssos: idpssoDescriptor.getSingleSignOnServices()) {
|
||||
if (ssos.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
|
||||
this.idpSingleSignOnUrl = ssos.getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
for (SingleLogoutService slos: idpssoDescriptor.getSingleLogoutServices()) {
|
||||
if (slos.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
|
||||
this.idpSingleLogOutUrl = slos.getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
for (KeyDescriptor kd: idpssoDescriptor.getKeyDescriptors()) {
|
||||
if (kd.getUse() == UsageType.SIGNING) {
|
||||
try {
|
||||
this.idpSigningKey = KeyInfoHelper.getCertificates(kd.getKeyInfo()).get(0);
|
||||
} catch (CertificateException ignored) {
|
||||
}
|
||||
}
|
||||
if (kd.getUse() == UsageType.ENCRYPTION) {
|
||||
try {
|
||||
this.idpEncryptionKey = KeyInfoHelper.getCertificates(kd.getKeyInfo()).get(0);
|
||||
} catch (CertificateException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Provided IDP XML Metadata does not contain IDPSSODescriptor, SAML authentication may not work");
|
||||
}
|
||||
} catch (MetadataProviderException e) {
|
||||
s_logger.error("Unable to read SAML2 IDP MetaData URL, error:" + e.getMessage());
|
||||
s_logger.error("SAML2 Authentication may be unavailable");
|
||||
} catch (ConfigurationException | FactoryConfigurationError e) {
|
||||
s_logger.error("OpenSAML bootstrapping failed: error: " + e.getMessage());
|
||||
}
|
||||
|
||||
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");
|
||||
s_logger.error("SAML based authentication won't work");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -128,4 +169,16 @@ public class SAML2AuthManagerImpl extends AdapterBase implements PluggableAPIAut
|
||||
public String getSpSingleLogOutUrl() {
|
||||
return spSingleLogOutUrl;
|
||||
}
|
||||
|
||||
public String getIdentityProviderId() {
|
||||
return identityProviderId;
|
||||
}
|
||||
|
||||
public X509Certificate getIdpSigningKey() {
|
||||
return idpSigningKey;
|
||||
}
|
||||
|
||||
public X509Certificate getIdpEncryptionKey() {
|
||||
return idpEncryptionKey;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user