diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata')
3 files changed, 339 insertions, 327 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java index 3fc675e9..8a20b932 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java @@ -27,12 +27,17 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.naming.ConfigurationException; +import at.gv.egiz.components.spring.api.IDestroyableObject; +import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; + import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.opensaml.core.criterion.EntityIdCriterion; @@ -43,11 +48,6 @@ import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver; import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import at.gv.egiz.components.spring.api.IDestroyableObject; -import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; -import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements; import net.shibboleth.utilities.java.support.component.IdentifiedComponent; @@ -55,10 +55,13 @@ import net.shibboleth.utilities.java.support.resolver.CriteriaSet; import net.shibboleth.utilities.java.support.resolver.ResolverException; @Slf4j -public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, IRefreshableMetadataProvider, +public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, + IRefreshableMetadataProvider, IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver { - - @Nonnull @NonnullElements private final List<MetadataResolver> internalResolvers; + + @Nonnull + @NonnullElements + private final List<MetadataResolver> internalResolvers; private DateTime lastRefeshTimestamp; private boolean lastRefeshSuccessful; private static Object mutex = new Object(); @@ -72,7 +75,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } - /* * (non-Javadoc) * @@ -104,8 +106,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } - - @Override public synchronized boolean refreshMetadataProvider(final String entityId) { try { @@ -130,7 +130,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec // check if MetadataProvider is actually loaded final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl); if (loadedResover instanceof RefreshableMetadataResolver) { - ((RefreshableMetadataResolver)loadedResover).refresh(); + ((RefreshableMetadataResolver) loadedResover).refresh(); log.info("SAML2 metadata for service provider: " + entityId + " is refreshed."); return true; @@ -162,30 +162,29 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec * */ public void internalDestroy() { - log.info("Destroying chained metadata resolvers ..."); + log.info("Destroying chained metadata resolvers ..."); - for (final MetadataResolver resolver : internalResolvers) { - destroyMetadataResolver(resolver); - } + for (final MetadataResolver resolver : internalResolvers) { + destroyMetadataResolver(resolver); + } - internalResolvers.clear(); + internalResolvers.clear(); } - /** {@inheritDoc} */ - @Override + @Override public final MetadataFilter getMetadataFilter() { - log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), - MetadataFilter.class.getName()); - return null; + log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), + MetadataFilter.class.getName()); + return null; } - /** {@inheritDoc} */ - @Override + @Override public final void setMetadataFilter(final MetadataFilter newFilter) { log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), MetadataFilter.class.getName()); - throw new UnsupportedOperationException("Metadata filters are not supported on AbstractChainingMetadataProvider"); + throw new UnsupportedOperationException( + "Metadata filters are not supported on AbstractChainingMetadataProvider"); } /* @@ -221,17 +220,17 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } @Override - @Nullable + @Nullable public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException { for (final MetadataResolver resolver : internalResolvers) { try { - final EntityDescriptor descriptors = resolver.resolveSingle(criteria); - if (descriptors != null) { - return descriptors; - } + final EntityDescriptor descriptors = resolver.resolveSingle(criteria); + if (descriptors != null) { + return descriptors; + } } catch (final ResolverException e) { - continue; + continue; } @@ -242,87 +241,90 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } @Override - @Nonnull - public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) throws ResolverException { - for (final MetadataResolver resolver : internalResolvers) { - try { - final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); - if (descriptors != null && descriptors.iterator().hasNext()) { - return descriptors; - - } - - } catch (final ResolverException e) { - continue; - - } + @Nonnull + public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) + throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + try { + final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); + if (descriptors != null && descriptors.iterator().hasNext()) { + return descriptors; + + } + + } catch (final ResolverException e) { + continue; + } + } - return Collections.emptyList(); + return Collections.emptyList(); } - + @Override public final void clear() throws ResolverException { - for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof ClearableMetadataResolver) { - ((ClearableMetadataResolver) resolver).clear(); - } + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof ClearableMetadataResolver) { + ((ClearableMetadataResolver) resolver).clear(); } + } } @Override public final void clear(String entityID) throws ResolverException { - for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof ClearableMetadataResolver) { - ((ClearableMetadataResolver) resolver).clear(entityID); - } + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof ClearableMetadataResolver) { + ((ClearableMetadataResolver) resolver).clear(entityID); } + } } - @Override final public void refresh() throws ResolverException { - this.lastRefeshSuccessful = false; - for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof RefreshableMetadataResolver) { - ((RefreshableMetadataResolver) resolver).refresh(); - - } + @Override + public final void refresh() throws ResolverException { + this.lastRefeshSuccessful = false; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + ((RefreshableMetadataResolver) resolver).refresh(); + } - - this.lastRefeshTimestamp = DateTime.now(); - this.lastRefeshSuccessful = true; + } + + this.lastRefeshTimestamp = DateTime.now(); + this.lastRefeshSuccessful = true; } @Override - @Nullable public DateTime getLastUpdate() { - DateTime ret = null; - for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof RefreshableMetadataResolver) { - final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate(); - if (ret == null || ret.isBefore(lastUpdate)) { - ret = lastUpdate; - } - } + @Nullable + public DateTime getLastUpdate() { + DateTime ret = null; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate(); + if (ret == null || ret.isBefore(lastUpdate)) { + ret = lastUpdate; + } } - - return ret; + } + + return ret; } @Override - @Nullable final public DateTime getLastRefresh() { - DateTime ret = null; - for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof RefreshableMetadataResolver) { - final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh(); - if (ret == null || ret.isBefore(lastRefresh)) { - ret = lastRefresh; - } - } + @Nullable + public final DateTime getLastRefresh() { + DateTime ret = null; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh(); + if (ret == null || ret.isBefore(lastRefresh)) { + ret = lastRefresh; + } } - - return ret; + } + + return ret; } - - + /** * Get the URL to metadata for a specific entityID. * @@ -354,103 +356,92 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec protected abstract List<String> getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException; - /** * Get a Id for this metadata provider. - * + * * @return */ @Nonnull protected abstract String getMetadataProviderId(); - + protected final MetadataResolver getMetadataResolver() { log.warn("{} does NOT support 'getMetadataResolver'", AbstractChainingMetadataProvider.class.getName()); return null; - + } - + private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() { final Map<String, MetadataResolver> loadedproviders = new HashMap<>(); // make a Map of all actually loaded HTTPMetadataProvider for (final MetadataResolver resolver : internalResolvers) { - if (resolver instanceof IdentifiedComponent) { - loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver); - - } else { - final String uuid = UUID.randomUUID().toString(); - loadedproviders.put(uuid, resolver); - log.debug("MetadatenResolver is not of type: {}. Mark it with id: {}", - IdentifiedComponent.class.getSimpleName(), uuid); + loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver); - } } return loadedproviders; } private void addAndRemoveMetadataProvider() throws EaafConfigurationException { - log.info("EAAF chaining metadata resolver starting internal managment task .... "); + log.info("EAAF chaining metadata resolver starting internal managment task .... "); + + /* + * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider + * (UnsupportedOperationException) The ChainingMetadataProvider use internal a + * unmodifiableList to hold all registrated MetadataProviders. + */ + final Map<String, MetadataResolver> providersinuse = new HashMap<>(); + + // get all actually loaded metadata providers + final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); + + /* + * TODO: maybe add metadata provider destroy after timeout. But could be a + * problem if one Metadataprovider load an EntitiesDescriptor with more the + * multiple EntityDescriptors. If one of this EntityDesciptors are expired the + * full EntitiesDescriptor is removed. + * + * Timeout requires a better solution in this case! + */ + + // load all SAML2 SPs form configuration and + // compare actually loaded Providers with configured SAML2 SPs + final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); + + final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator(); + while (metadataUrlInterator.hasNext()) { + final String metadataurl = metadataUrlInterator.next(); + try { + if (StringUtils.isNotEmpty(metadataurl) + && loadedproviders.containsKey(metadataurl)) { + // SAML2 SP is actually loaded, to nothing + providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); + loadedproviders.remove(metadataurl); + + } + } catch (final Throwable e) { + log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e); + + } + } + + // remove all actually loaded MetadataProviders with are not in ConfigurationDB + // any more + final Collection<MetadataResolver> notusedproviders = loadedproviders.values(); + for (final MetadataResolver resolver : notusedproviders) { + log.info("Remove not used MetadataProvider with MetadataURL " + resolver.getId()); + destroyMetadataResolver(resolver); + internalResolvers.remove(resolver); /* * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider * (UnsupportedOperationException) The ChainingMetadataProvider use internal a * unmodifiableList to hold all registrated MetadataProviders. */ - final Map<String, MetadataResolver> providersinuse = new HashMap<>(); + // chainProvider.removeMetadataProvider(provider); - // get all actually loaded metadata providers - final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); - - /* - * TODO: maybe add metadata provider destroy after timeout. But could be a - * problem if one Metadataprovider load an EntitiesDescriptor with more the - * multiple EntityDescriptors. If one of this EntityDesciptors are expired the - * full EntitiesDescriptor is removed. - * - * Timeout requires a better solution in this case! - */ - - // load all SAML2 SPs form configuration and - // compare actually loaded Providers with configured SAML2 SPs - final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); - - final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator(); - while (metadataUrlInterator.hasNext()) { - final String metadataurl = metadataUrlInterator.next(); - try { - if (StringUtils.isNotEmpty(metadataurl) - && loadedproviders.containsKey(metadataurl)) { - // SAML2 SP is actually loaded, to nothing - providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); - loadedproviders.remove(metadataurl); - - } - } catch (final Throwable e) { - log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e); - - } - } - - - // remove all actually loaded MetadataProviders with are not in ConfigurationDB - // any more - final Collection<MetadataResolver> notusedproviders = loadedproviders.values(); - for (final MetadataResolver resolver : notusedproviders) { - log.info("Remove not used MetadataProvider with MetadataURL " + resolver.getId()); - destroyMetadataResolver(resolver); - internalResolvers.remove(resolver); - - /* - * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider - * (UnsupportedOperationException) The ChainingMetadataProvider use internal a - * unmodifiableList to hold all registrated MetadataProviders. - */ - // chainProvider.removeMetadataProvider(provider); - - - } + } } @@ -474,39 +465,34 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } } - - @Override public DateTime getLastSuccessfulRefresh() { return this.lastRefeshTimestamp; - - } + } @Override public Boolean wasLastRefreshSuccess() { return this.lastRefeshSuccessful; - - } - - - /** {@inheritDoc} */ - @Override public boolean isRequireValidMetadata() { - log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); - return false; } - /** {@inheritDoc} */ - @Override public void setRequireValidMetadata(final boolean requireValidMetadata) { - throw new UnsupportedOperationException("Setting requireValidMetadata is not supported on chaining resolver"); + @Override + public boolean isRequireValidMetadata() { + log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); + return false; } + @Override + public void setRequireValidMetadata(final boolean requireValidMetadata) { + throw new UnsupportedOperationException( + "Setting requireValidMetadata is not supported on chaining resolver"); + } @Override public String getId() { return getMetadataProviderId(); - + } - + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java index bd2b79cb..d2b861dc 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java @@ -1,18 +1,22 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; + import org.joda.time.DateTime; import org.opensaml.core.criterion.EntityIdCriterion; import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver; import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; import net.shibboleth.utilities.java.support.resolver.ResolverException; -public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { - - private ExtendedRefreshableMetadataResolver internalProvider; +@Slf4j +public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider, IRefreshableMetadataProvider { + + private final ExtendedRefreshableMetadataResolver internalProvider; public PvpMetadataResolverAdapter(ExtendedRefreshableMetadataResolver provider) { this.internalProvider = provider; @@ -27,7 +31,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { @Override public DateTime getLastRefresh() { return internalProvider.getLastRefresh(); - + } @Override @@ -38,7 +42,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { @Override public boolean isRequireValidMetadata() { return internalProvider.isRequireValidMetadata(); - + } @Override @@ -50,12 +54,12 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { @Override public MetadataFilter getMetadataFilter() { return internalProvider.getMetadataFilter(); - + } @Override public void setMetadataFilter(MetadataFilter newFilter) { - internalProvider.setMetadataFilter(newFilter); + internalProvider.setMetadataFilter(newFilter); } @@ -67,7 +71,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { @Override public EntityDescriptor resolveSingle(CriteriaSet criteria) throws ResolverException { return internalProvider.resolveSingle(criteria); - + } @Override @@ -80,7 +84,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { final CriteriaSet criteria = new CriteriaSet(); criteria.add(new EntityIdCriterion(entityId)); return internalProvider.resolveSingle(criteria); - + } @Override @@ -93,4 +97,19 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { return internalProvider.wasLastRefreshSuccess(); } + @Override + public boolean refreshMetadataProvider(String entityID) { + try { + log.trace("Refeshing metadata-provider: {} ... ", getId()); + internalProvider.refresh(); + return true; + + } catch (final ResolverException e) { + log.warn("Refreshing of metadata-provider: {} failed. Reason: {}", + getId(), e.getMessage()); + return false; + + } + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java index f548bc7b..0b505e56 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java @@ -8,23 +8,31 @@ import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.net.ssl.SSLHandshakeException; +import at.gv.egiz.components.spring.api.IDestroyableObject; +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.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; + import org.apache.http.client.HttpClient; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver; import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver; import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver; import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ResourceLoader; -import at.gv.egiz.components.spring.api.IDestroyableObject; -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.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; -import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.ResolverException; import net.shibboleth.utilities.java.support.resource.Resource; import net.shibboleth.utilities.java.support.xml.ParserPool; @@ -34,13 +42,18 @@ public class PvpMetadataResolverFactory implements IDestroyableObject { private static final String URI_PREFIX_HTTP = "http:"; private static final String URI_PREFIX_HTTPS = "https:"; + private static final String NOT_SUCCESS = "Maybe metadata was expired"; + private Timer timer = null; - - @Autowired private IConfiguration authConfig; - @Autowired private ResourceLoader resourceLoader; - + + @Autowired + private IConfiguration authConfig; + @Autowired + private ResourceLoader resourceLoader; + /** - * Create a single SAML2 metadata provider by using the default OpenSAML3 parser-pool. + * Create a single SAML2 metadata provider by using the default OpenSAML3 + * parser-pool. * * @param metadataLocation where the metadata should be loaded, but never null. * If the location starts with http(s):, than a http @@ -54,17 +67,18 @@ public class PvpMetadataResolverFactory implements IDestroyableObject { * * @return SAML2 Metadata Provider, or null if the metadata provider can not * initialized + * @throws Pvp2MetadataException In case of an initialization error */ - @Nullable + @Nullable public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation, @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, - @Nullable final HttpClient httpClient) { - return createMetadataProvider(metadataLocation, filter, idForLogging, - XMLObjectProviderRegistrySupport.getParserPool(), - httpClient); - + @Nullable final HttpClient httpClient) throws Pvp2MetadataException { + return createMetadataProvider(metadataLocation, filter, idForLogging, + XMLObjectProviderRegistrySupport.getParserPool(), + httpClient); + } - + /** * Create a single SAML2 metadata provider. * @@ -80,57 +94,74 @@ public class PvpMetadataResolverFactory implements IDestroyableObject { * * @return SAML2 Metadata Provider, or null if the metadata provider can not * initialized + * @throws Pvp2MetadataException In case of an initialization error */ - @Nullable + @Nullable public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation, @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, - @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) { - + @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) throws Pvp2MetadataException { + ExtendedRefreshableMetadataResolver internalProvider = null; - - if (metadataLocation.startsWith(URI_PREFIX_HTTP) - || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { - if (httpClient != null) { - internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter, idForLogging, timer, pool, - httpClient); + + try { + if (metadataLocation.startsWith(URI_PREFIX_HTTP) + || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { + internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter, + idForLogging, timer, pool, httpClient); + } else { - log.warn("Can not load http(s) based SAML2 metadata without a HTTP client"); - + final String absoluteMetadataLocation = + FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); + final org.springframework.core.io.Resource resource = + resourceLoader.getResource(absoluteMetadataLocation); + + if (resource.exists()) { + internalProvider = createNewFileSystemMetaDataProvider( + new OpenSaml3ResourceAdapter(resource), + filter, idForLogging, timer, + pool); + + } else { + log.warn( + "SAML2 metadata file: {} not found or not exist", absoluteMetadataLocation); + throw new Pvp2MetadataException("internal.pvp.05", + new Object[] { absoluteMetadataLocation, "File NOT found or exist." }); + + } } - } else { - String absoluteMetadataLocation; - try { - absoluteMetadataLocation = - FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); + } catch (final ComponentInitializationException e) { + log.warn("Failed to load Metadata file for {} [ {} ]", + idForLogging, e.getMessage()); + checkResolverInitializationError(e, metadataLocation); - org.springframework.core.io.Resource resource = resourceLoader.getResource(absoluteMetadataLocation); - if (resource.exists()) { - internalProvider = createNewFileSystemMetaDataProvider( - new OpenSaml3ResourceAdapter(resource), - filter, idForLogging, timer, - pool); - } else { - log.warn( - "SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist"); - - } + } catch (final Exception e) { + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }); + } - } catch (final IOException e) { - log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e); + if (!internalProvider.wasLastRefreshSuccess()) { + log.info("Metadata loading from source: {} failed. {}", metadataLocation, NOT_SUCCESS); + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, NOT_SUCCESS }); - } } - if (internalProvider != null) { - return new PvpMetadataResolverAdapter(internalProvider); - - } else { - log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); - return null; - + return new PvpMetadataResolverAdapter(internalProvider); + + } + + @Override + public void fullyDestroy() { + if (timer != null) { + log.info("Stopping timer-thread for PVP metadata resolver ... "); + timer.cancel(); } + } + + @PostConstruct + private void initialize() { + log.info("Initializing timer-thread for PVP metadata resolver ... "); + timer = new Timer("PVP metadata-resolver refresh"); } @@ -142,55 +173,26 @@ public class PvpMetadataResolverFactory implements IDestroyableObject { * @param idForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh * operations - * @param pool + * @param pool SAML2 parser pool that should be used * * @return SAML2 Metadata Provider - * @throws IOException + * @throws IOException In case of a metadata resource error + * @throws ComponentInitializationException In case of a metadata resolver + * initialization error */ private ExtendedRefreshableMetadataResolver createNewFileSystemMetaDataProvider(final Resource metadataFile, final MetadataFilter filter, final String idForLogging, final Timer timer, - final ParserPool pool) throws IOException { + final ParserPool pool) throws IOException, ComponentInitializationException { ResourceBackedMetadataResolver fileSystemResolver = null; - try { - //fileSystemResolver = new FilesystemMetadataResolver(timer, metadataFile); - - fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile); - - if (pool != null) { - fileSystemResolver.setParserPool(pool); - - } else { - fileSystemResolver.setParserPool( - XMLObjectProviderRegistrySupport.getParserPool()); - - } - fileSystemResolver.setRequireValidMetadata(true); - fileSystemResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes - fileSystemResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours - - fileSystemResolver.setMetadataFilter(filter); - fileSystemResolver.initialize(); - fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); - - fileSystemResolver.setRequireValidMetadata(true); - - return fileSystemResolver; - - } catch (final Exception e) { - log.warn("Failed to load Metadata file for " + idForLogging + "[ " + "File: " - + metadataFile.getURI().toASCIIString() + " Msg: " + e.getMessage() + " ]", e); - - log.warn("Can not initialize SAML2 metadata provider from filesystem: " - + metadataFile.getURI().toASCIIString() + " Reason: " + e.getMessage(), e); + fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile); + injectMetadataResolverConfiguration(fileSystemResolver, filter, pool); + fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); + fileSystemResolver.initialize(); - if (fileSystemResolver != null) { - fileSystemResolver.destroy(); + log.trace("Set-up metadata-resolver with ID: {} as: {}", + idForLogging, fileSystemResolver.getClass().getSimpleName()); - } - - } - - return null; + return fileSystemResolver; } @@ -202,70 +204,75 @@ public class PvpMetadataResolverFactory implements IDestroyableObject { * @param idForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh * operations - * @param pool - * + * @param pool SAML2 parser pool that should be used * @return SAML2 Metadata Provider + * @throws ComponentInitializationException In case of a metadata resolver + * initialization error + * @throws ResolverException In case of an internal OpenSAML + * resolver error */ private ExtendedRefreshableMetadataResolver createNewHttpMetaDataProvider(final String metadataUrl, final MetadataFilter filter, final String idForLogging, final Timer timer, - final ParserPool pool, final HttpClient httpClient) { + final ParserPool pool, final HttpClient httpClient) throws ComponentInitializationException, + ResolverException { HTTPMetadataResolver httpMetadataResolver = null; - try { - httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl); - httpMetadataResolver.setParserPool(pool); - httpMetadataResolver.setRequireValidMetadata(true); - httpMetadataResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes - httpMetadataResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours - // httpProvider.setRefreshDelayFactor(0.1F); + httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl); + injectMetadataResolverConfiguration(httpMetadataResolver, filter, pool); + httpMetadataResolver.setId(metadataUrl); + httpMetadataResolver.initialize(); - httpMetadataResolver.setMetadataFilter(filter); - httpMetadataResolver.setId(metadataUrl); - httpMetadataResolver.initialize(); + log.trace("Set-up metadata-resolver with ID: {} as: {}", + idForLogging, httpMetadataResolver.getClass().getSimpleName()); - httpMetadataResolver.setRequireValidMetadata(true); + return httpMetadataResolver; - return httpMetadataResolver; + } - } catch (final Throwable e) { - if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { - log.warn("SSL-Server certificate for metadata " + metadataUrl + " not trusted.", e); + private void injectMetadataResolverConfiguration(AbstractReloadingMetadataResolver resolver, + final MetadataFilter filter, final ParserPool pool) { + if (pool != null) { + resolver.setParserPool(pool); - } - if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { - log.warn("Signature verification for metadata" + metadataUrl + " FAILED.", e); + } else { + resolver.setParserPool( + XMLObjectProviderRegistrySupport.getParserPool()); - } - if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { - log.warn("Schema validation for metadata " + metadataUrl + " FAILED.", e); - } + } + + resolver.setRequireValidMetadata(true); + resolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes + resolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours + resolver.setMetadataFilter(filter); + + } - log.warn("Failed to load Metadata file for " + idForLogging + "[ " + e.getMessage() + " ]", + private void checkResolverInitializationError(ComponentInitializationException e, String metadataLocation) + throws Pvp2MetadataException { + if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SSLHandshakeException.class)).first().isPresent()) { + log.info("SSL-Server certificate for metadata: {} not trusted.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.06", new Object[] { metadataLocation, e.getMessage() }, e); - if (httpMetadataResolver != null) { - log.debug("Destroy failed Metadata provider"); - httpMetadataResolver.destroy(); + } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SignatureValidationException.class)).first().isPresent()) { + log.info("Signature verification for metadata: {} FAILED.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.07", new Object[] { metadataLocation, e.getMessage() }, + e); - } + } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SchemaValidationException.class)).first().isPresent()) { + log.info("Schema validation for metadata: {} FAILED.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.08", new Object[] { metadataLocation, e.getMessage() }, + e); + + } else { + log.info("Generic initialization error for metadata: {}", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }, + e); } - return null; } - @Override - public void fullyDestroy() { - if (timer != null) { - log.info("Stopping timer-thread for PVP metadata resolver ... "); - timer.cancel(); - } - } - - @PostConstruct - private void initialize() { - log.info("Initializing timer-thread for PVP metadata resolver ... "); - timer = new Timer("PVP metadata-resolver refresh"); - - } - } |