/******************************************************************************* *******************************************************************************/ package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; import java.io.File; import java.net.MalformedURLException; import java.util.Timer; import javax.net.ssl.SSLHandshakeException; import org.apache.commons.httpclient.HttpClient; import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.xml.parse.ParserPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.impl.utils.FileUtils; import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; /** * @author tlenz * */ public abstract class SimpleMetadataProvider implements MetadataProvider{ private static final Logger log = LoggerFactory.getLogger(SimpleMetadataProvider.class); private static final String URI_PREFIX_HTTP = "http:"; private static final String URI_PREFIX_HTTPS = "https:"; private static final String URI_PREFIX_FILE = "file:"; @Autowired protected IConfiguration authConfig; /** * Create a single SAML2 metadata provider * * @param metadataLocation where the metadata should be loaded, but never null. If the location starts with http(s):, than a http * based metadata provider is used. If the location starts with file:, than a filesystem based metadata provider is used * @param filter Filters, which should be used to validate the metadata * @param IdForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh operations * @param httpClient Apache commons 3.x http client * * @return SAML2 Metadata Provider, or null if the metadata provider can not initialized */ protected MetadataProvider createNewSimpleMetadataProvider(String metadataLocation, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) { if (metadataLocation.startsWith(URI_PREFIX_HTTP) || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { if (httpClient != null) return createNewHTTPMetaDataProvider(metadataLocation, filter, IdForLogging, timer, pool, httpClient); else { log.warn("Can not load http(s) based SAML2 metadata without a HTTP client"); return null; } } else { String absoluteMetadataLocation; try { absoluteMetadataLocation = FileUtils.makeAbsoluteURL( metadataLocation, authConfig.getConfigurationRootDirectory()); if (absoluteMetadataLocation.startsWith(URI_PREFIX_FILE)) { File metadataFile = new File(absoluteMetadataLocation); if (metadataFile.exists()) return createNewFileSystemMetaDataProvider(metadataFile, filter, IdForLogging, timer, pool); else { log.warn("SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist"); return null; } } } catch (MalformedURLException e) { log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e); } } log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); return null; } /** * Create a single SAML2 filesystem based metadata provider * * @param metadataFile File, where the metadata should be loaded * @param filter Filters, which should be used to validate the metadata * @param IdForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh operations * @param pool * * @return SAML2 Metadata Provider */ private MetadataProvider createNewFileSystemMetaDataProvider(File metadataFile, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool) { FilesystemMetadataProvider fileSystemProvider = null; try { fileSystemProvider = new FilesystemMetadataProvider(timer, metadataFile); fileSystemProvider.setParserPool(pool); fileSystemProvider.setRequireValidMetadata(true); fileSystemProvider.setMinRefreshDelay(1000*60*15); //15 minutes fileSystemProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours //httpProvider.setRefreshDelayFactor(0.1F); fileSystemProvider.setMetadataFilter(filter); fileSystemProvider.initialize(); fileSystemProvider.setRequireValidMetadata(true); return fileSystemProvider; } catch (Exception e) { log.warn( "Failed to load Metadata file for " + IdForLogging + "[ " + "File: " + metadataFile.getAbsolutePath() + " Msg: " + e.getMessage() + " ]", e); log.warn("Can not initialize SAML2 metadata provider from filesystem: " + metadataFile.getAbsolutePath() + " Reason: " + e.getMessage(), e); if (fileSystemProvider != null) fileSystemProvider.destroy(); } return null; } /** * Create a single SAML2 HTTP metadata provider * * @param metadataURL URL, where the metadata should be loaded * @param filter Filters, which should be used to validate the metadata * @param IdForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh operations * @param pool * * @return SAML2 Metadata Provider */ private MetadataProvider createNewHTTPMetaDataProvider(String metadataURL, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) { HTTPMetadataProvider httpProvider = null; try { httpProvider = new HTTPMetadataProvider(timer, httpClient, metadataURL); httpProvider.setParserPool(pool); httpProvider.setRequireValidMetadata(true); httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours //httpProvider.setRefreshDelayFactor(0.1F); httpProvider.setMetadataFilter(filter); httpProvider.initialize(); httpProvider.setRequireValidMetadata(true); return httpProvider; } catch (Throwable e) { if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { log.warn("SSL-Server certificate for metadata " + metadataURL + " not trusted.", e); } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { log.warn("Signature verification for metadata" + metadataURL + " FAILED.", e); } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { log.warn("Schema validation for metadata " + metadataURL + " FAILED.", e); } log.warn( "Failed to load Metadata file for " + IdForLogging + "[ " + e.getMessage() + " ]", e); if (httpProvider != null) { log.debug("Destroy failed Metadata provider"); httpProvider.destroy(); } // if (timer != null) { // log.debug("Destroy Timer."); // timer.cancel(); // } } return null; } }