/** * blackduck-alert * * Copyright (c) 2020 Synopsys, Inc. * * 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.synopsys.integration.alert.web.security.authentication.saml; import java.io.File; import java.util.List; import java.util.Optional; import java.util.Timer; import java.util.stream.Collectors; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.lang3.StringUtils; import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.xml.parse.ParserPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.saml.metadata.ExtendedMetadata; import org.springframework.security.saml.metadata.ExtendedMetadataDelegate; import org.springframework.security.saml.metadata.MetadataGenerator; import org.springframework.security.saml.metadata.MetadataManager; import com.synopsys.integration.alert.common.exception.AlertConfigurationException; import com.synopsys.integration.alert.common.persistence.model.ConfigurationModel; import com.synopsys.integration.alert.common.persistence.util.FilePersistenceUtil; import com.synopsys.integration.alert.component.authentication.descriptor.AuthenticationDescriptor; public class SAMLManager { public static final Logger logger = LoggerFactory.getLogger(SAMLManager.class); private final ParserPool parserPool; private final ExtendedMetadata extendedMetadata; private final MetadataManager metadataManager; private final MetadataGenerator metadataGenerator; private final FilePersistenceUtil filePersistenceUtil; private final SAMLContext samlContext; public SAMLManager(ParserPool parserPool, ExtendedMetadata extendedMetadata, MetadataManager metadataManager, MetadataGenerator metadataGenerator, FilePersistenceUtil filePersistenceUtil, SAMLContext samlContext) { this.parserPool = parserPool; this.extendedMetadata = extendedMetadata; this.metadataManager = metadataManager; this.metadataGenerator = metadataGenerator; this.filePersistenceUtil = filePersistenceUtil; this.samlContext = samlContext; } public void initializeConfiguration() { logger.info("Initializing SAML identity provider with database configuration."); try { ConfigurationModel currentConfiguration = samlContext.getCurrentConfiguration(); boolean samlEnabled = samlContext.isSAMLEnabled(currentConfiguration); String metadataURL = samlContext.getFieldValueOrEmpty(currentConfiguration, AuthenticationDescriptor.KEY_SAML_METADATA_URL); String entityId = samlContext.getFieldValueOrEmpty(currentConfiguration, AuthenticationDescriptor.KEY_SAML_ENTITY_ID); String entityBaseUrl = samlContext.getFieldValueOrEmpty(currentConfiguration, AuthenticationDescriptor.KEY_SAML_ENTITY_BASE_URL); updateSAMLConfiguration(samlEnabled, metadataURL, entityId, entityBaseUrl); } catch (AlertConfigurationException e) { logger.warn(String.format("Cannot initialize the SAML identity provider. %s", e.getMessage())); } catch (Exception e) { logger.error("Error initializing the SAML identity provider.", e); } } public void updateSAMLConfiguration(boolean samlEnabled, String metadataURL, String entityId, String entityBaseUrl) { try { logger.debug("SAML Config Update."); List<ExtendedMetadataDelegate> currentProviders = metadataManager.getAvailableProviders(); currentProviders.forEach(ExtendedMetadataDelegate::destroy); metadataManager.setProviders(List.of()); metadataManager.setDefaultIDP(null); metadataManager.setHostedSPName(null); metadataManager.afterPropertiesSet(); metadataGenerator.setEntityId(null); metadataGenerator.setEntityBaseURL(null); logger.debug("SAML cleared configuration."); if (samlEnabled) { setupMetadataManager(metadataURL, entityId, entityBaseUrl); } } catch (Exception e) { logger.error("Error updating the SAML identity provider.", e); } } public void setupMetadataManager(String metadataURL, String entityId, String entityBaseUrl) throws MetadataProviderException { logger.debug("SAML Setup MetaData Manager"); logger.debug("SAML - MetadataUrl: {}, EntityID: {}, EntityBaseUrl: {}", metadataURL, entityId, entityBaseUrl); metadataGenerator.setEntityId(entityId); metadataGenerator.setEntityBaseURL(entityBaseUrl); Optional<ExtendedMetadataDelegate> httpProvider = createHttpProvider(metadataURL); Optional<ExtendedMetadataDelegate> fileProvider = createFileProvider(); List<MetadataProvider> providers = List.of(httpProvider, fileProvider).stream() .flatMap(Optional::stream) .collect(Collectors.toList()); metadataManager.setProviders(providers); metadataManager.afterPropertiesSet(); } public Optional<ExtendedMetadataDelegate> createHttpProvider(String metadataUrl) throws MetadataProviderException { if (StringUtils.isBlank(metadataUrl)) { return Optional.empty(); } logger.debug("SAML - Create Http Metadata provider."); // The URL can not end in a '/' because it messes with the paths for saml String correctedMetadataURL = StringUtils.removeEnd(metadataUrl, "/"); Timer backgroundTaskTimer = new Timer(true); HTTPMetadataProvider provider = new HTTPMetadataProvider(backgroundTaskTimer, new HttpClient(), correctedMetadataURL); provider.setParserPool(parserPool); return Optional.of(createDelegate(provider)); } public Optional<ExtendedMetadataDelegate> createFileProvider() throws MetadataProviderException { Timer backgroundTaskTimer = new Timer(true); if (!filePersistenceUtil.uploadFileExists(AuthenticationDescriptor.SAML_METADATA_FILE)) { return Optional.empty(); } logger.debug("SAML - Create File Metadata provider."); File metadataFile = filePersistenceUtil.createUploadsFile(AuthenticationDescriptor.SAML_METADATA_FILE); FilesystemMetadataProvider provider = new FilesystemMetadataProvider(backgroundTaskTimer, metadataFile); provider.setParserPool(parserPool); return Optional.of(createDelegate(provider)); } private ExtendedMetadataDelegate createDelegate(MetadataProvider provider) { ExtendedMetadataDelegate delegate = new ExtendedMetadataDelegate(provider, extendedMetadata); delegate.setMetadataTrustCheck(true); delegate.setMetadataRequireSignature(false); return delegate; } }