diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata')
-rw-r--r-- | eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java | 318 | ||||
-rw-r--r-- | eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java | 96 | ||||
-rw-r--r-- | eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java (renamed from eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java) | 188 |
3 files changed, 379 insertions, 223 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 ec59b1df..3fc675e9 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,46 +27,41 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Timer; import java.util.UUID; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.naming.ConfigurationException; -import javax.xml.namespace.QName; - -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; import org.opensaml.saml.metadata.resolver.ClearableMetadataResolver; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver; import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver; -import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml.saml2.metadata.RoleDescriptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +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; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; import net.shibboleth.utilities.java.support.resolver.ResolverException; -public abstract class AbstractChainingMetadataProvider extends SimpleMetadataResolver - implements IGarbageCollectorProcessing, IRefreshableMetadataProvider, IDestroyableObject, IPvp2MetadataProvider, - RefreshableMetadataResolver, ClearableMetadataResolver { - - private static final Logger log = LoggerFactory.getLogger(AbstractChainingMetadataProvider.class); - +@Slf4j +public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, IRefreshableMetadataProvider, + IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver { + @Nonnull @NonnullElements private final List<MetadataResolver> internalResolvers; + private DateTime lastRefeshTimestamp; + private boolean lastRefeshSuccessful; private static Object mutex = new Object(); - private Timer timer = null; /** * Build a chaining metadata resolver that requires valid metadata. @@ -77,10 +72,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes } - public final Timer getTimer() { - return this.timer; - - } /* * (non-Javadoc) @@ -145,10 +136,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes } else { // load new Metadata Provider - if (timer == null) { - timer = new Timer(true); - } - internalResolvers.add(createNewMetadataProvider(metadataUrl)); log.info("SAML2 metadata for service provider: " + entityId + " is added."); @@ -183,78 +170,22 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes internalResolvers.clear(); - if (timer != null) { - timer.cancel(); - } - } - - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * getMetadataFilter() - */ - @Override - public MetadataFilter getMetadataFilter() { - return internalProvider.getMetadataFilter(); - } - - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * setMetadataFilter(org. opensaml.saml2.metadata.provider.MetadataFilter) - */ - @Override - public void setMetadataFilter(final MetadataFilter newFilter) throws MetadataProviderException { - internalProvider.setMetadataFilter(newFilter); - } - - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * getMetadata() - */ - @Override - public XMLObject getMetadata() throws MetadataProviderException { - return internalProvider.getMetadata(); + /** {@inheritDoc} */ + @Override + public final MetadataFilter getMetadataFilter() { + log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), + MetadataFilter.class.getName()); + return null; } - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * getEntitiesDescriptor( java.lang.String) - */ - @Override - public EntitiesDescriptor getEntitiesDescriptor(final String entitiesID) - throws MetadataProviderException { - EntitiesDescriptor entitiesDesc = null; - try { - entitiesDesc = internalProvider.getEntitiesDescriptor(entitiesID); - - if (entitiesDesc == null) { - log.debug("Can not find PVP metadata for entityID: " + entitiesID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entitiesID)) { - return internalProvider.getEntitiesDescriptor(entitiesID); - } - - } - - } catch (final MetadataProviderException e) { - log.debug("Can not find PVP metadata for entityID: " + entitiesID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entitiesID)) { - return internalProvider.getEntitiesDescriptor(entitiesID); - } - - } - - return entitiesDesc; + /** {@inheritDoc} */ + @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"); } /* @@ -265,68 +196,133 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes */ @Override public EntityDescriptor getEntityDescriptor(final String entityID) - throws MetadataProviderException { + throws ResolverException { EntityDescriptor entityDesc = null; try { - entityDesc = internalProvider.getEntityDescriptor(entityID); + entityDesc = resolveEntityDescripor(entityID); if (entityDesc == null) { log.debug("Can not find PVP metadata for entityID: " + entityID + " Start refreshing process ..."); if (refreshMetadataProvider(entityID)) { - return internalProvider.getEntityDescriptor(entityID); + return resolveEntityDescripor(entityID); } - } - } catch (final MetadataProviderException e) { + } catch (final ResolverException e) { log.debug( "Can not find PVP metadata for entityID: " + entityID + " Start refreshing process ..."); if (refreshMetadataProvider(entityID)) { - return internalProvider.getEntityDescriptor(entityID); + return resolveEntityDescripor(entityID); } } - // if (entityDesc != null) - // lastAccess.put(entityID, new Date()); - return entityDesc; } - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * getRole(java.lang. String, javax.xml.namespace.QName) - */ @Override - public List<RoleDescriptor> getRole(final String entityID, final QName roleName) - throws MetadataProviderException { - final List<RoleDescriptor> result = internalProvider.getRole(entityID, roleName); + @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; + } + + } catch (final ResolverException e) { + continue; + + } - // if (result != null) - // lastAccess.put(entityID, new Date()); + } + + return null; - return result; } - /* - * (non-Javadoc) - * - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# - * getRole(java.lang. String, javax.xml.namespace.QName, java.lang.String) - */ @Override - public RoleDescriptor getRole(final String entityID, final QName roleName, - final String supportedProtocol) throws MetadataProviderException { - final RoleDescriptor result = internalProvider.getRole(entityID, roleName, supportedProtocol); + @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(); + } + + @Override + public final void clear() throws ResolverException { + 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); + } + } + } - // if (result != null) - // lastAccess.put(entityID, new Date()); + @Override final public 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; + } - return result; + @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; + } + } + } + + 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; + } + } + } + + return ret; + } + + /** * Get the URL to metadata for a specific entityID. * @@ -359,6 +355,20 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes 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<>(); @@ -447,21 +457,7 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes private EntityDescriptor resolveEntityDescripor(String entityId) throws ResolverException { final CriteriaSet criteria = new CriteriaSet(); criteria.add(new EntityIdCriterion(entityId)); - for (final MetadataResolver resolver : internalResolvers) { - try { - final EntityDescriptor descriptors = resolver.resolveSingle(criteria); - if (descriptors != null) { - return descriptors; - } - - } catch (final ResolverException e) { - continue; - - } - - } - - return null; + return resolveSingle(criteria); } @@ -477,4 +473,40 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataRes } } + + + + @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 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 new file mode 100644 index 00000000..bd2b79cb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java @@ -0,0 +1,96 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; + +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 net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; + +public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { + + private ExtendedRefreshableMetadataResolver internalProvider; + + public PvpMetadataResolverAdapter(ExtendedRefreshableMetadataResolver provider) { + this.internalProvider = provider; + } + + @Override + public void refresh() throws ResolverException { + internalProvider.refresh(); + + } + + @Override + public DateTime getLastRefresh() { + return internalProvider.getLastRefresh(); + + } + + @Override + public DateTime getLastUpdate() { + return internalProvider.getLastUpdate(); + } + + @Override + public boolean isRequireValidMetadata() { + return internalProvider.isRequireValidMetadata(); + + } + + @Override + public void setRequireValidMetadata(boolean requireValidMetadata) { + internalProvider.setRequireValidMetadata(requireValidMetadata); + + } + + @Override + public MetadataFilter getMetadataFilter() { + return internalProvider.getMetadataFilter(); + + } + + @Override + public void setMetadataFilter(MetadataFilter newFilter) { + internalProvider.setMetadataFilter(newFilter); + + } + + @Override + public Iterable<EntityDescriptor> resolve(CriteriaSet criteria) throws ResolverException { + return internalProvider.resolve(criteria); + } + + @Override + public EntityDescriptor resolveSingle(CriteriaSet criteria) throws ResolverException { + return internalProvider.resolveSingle(criteria); + + } + + @Override + public String getId() { + return internalProvider.getId(); + } + + @Override + public EntityDescriptor getEntityDescriptor(String entityId) throws ResolverException { + final CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EntityIdCriterion(entityId)); + return internalProvider.resolveSingle(criteria); + + } + + @Override + public DateTime getLastSuccessfulRefresh() { + return internalProvider.getLastSuccessfulRefresh(); + } + + @Override + public Boolean wasLastRefreshSuccess() { + return internalProvider.wasLastRefreshSuccess(); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java index 35ad3f97..f548bc7b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java @@ -1,75 +1,70 @@ -/* - * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a - * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in - * compliance with the Licence. You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence - * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the Licence for the specific language governing permissions and limitations under - * the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text file for details on the - * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative - * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ - package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; -import java.io.File; -import java.net.MalformedURLException; +import java.io.IOException; import java.util.Timer; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; import javax.net.ssl.SSLHandshakeException; -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; - import org.apache.http.client.HttpClient; -import org.opensaml.saml.metadata.resolver.MetadataResolver; +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.FilesystemMetadataResolver; 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 lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.resource.Resource; import net.shibboleth.utilities.java.support.xml.ParserPool; -/** - * Simple SAML2 metadata provider. - * - * @author tlenz - * - */ @Slf4j -public abstract class SimpleMetadataResolver implements MetadataResolver { +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 URI_PREFIX_FILE = "file:"; - - @Autowired - protected IConfiguration authConfig; - - @Override - public final boolean isRequireValidMetadata() { - return true; - - } - - @Override - public final void setRequireValidMetadata(final boolean requireValidMetadata) { - log.warn("EAAF {} requires always valid metadata. Setting will be ignored", - SimpleMetadataResolver.class.getSimpleName()); + private Timer timer = null; + + @Autowired private IConfiguration authConfig; + @Autowired private ResourceLoader resourceLoader; + + /** + * 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 + * 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 httpClient Apache commons 4.x http client + * + * @return SAML2 Metadata Provider, or null if the metadata provider can not + * initialized + */ + @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); + } - - - + /** * Create a single SAML2 metadata provider. * @@ -81,24 +76,26 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { * @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 + * @param httpClient Apache commons 4.x http client * * @return SAML2 Metadata Provider, or null if the metadata provider can not * initialized */ - protected MetadataResolver createNewSimpleMetadataProvider(final String metadataLocation, - final MetadataFilter filter, final String idForLogging, final Timer timer, - final ParserPool pool, final HttpClient httpClient) { + @Nullable + public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation, + @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, + @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) { + + ExtendedRefreshableMetadataResolver internalProvider = null; + if (metadataLocation.startsWith(URI_PREFIX_HTTP) || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { if (httpClient != null) { - return createNewHttpMetaDataProvider(metadataLocation, filter, idForLogging, timer, pool, + internalProvider = 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 { @@ -107,28 +104,33 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { absoluteMetadataLocation = FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); - if (absoluteMetadataLocation.startsWith(URI_PREFIX_FILE)) { - final File metadataFile = new File(absoluteMetadataLocation); - if (metadataFile.exists()) { - return createNewFileSystemMetaDataProvider(metadataFile, filter, idForLogging, timer, + 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"); - return null; + } - } - } catch (final MalformedURLException e) { + } catch (final IOException e) { log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e); } - } - log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); - return null; + if (internalProvider != null) { + return new PvpMetadataResolverAdapter(internalProvider); + + } else { + log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); + return null; + + } } @@ -143,21 +145,32 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { * @param pool * * @return SAML2 Metadata Provider + * @throws IOException */ - private MetadataResolver createNewFileSystemMetaDataProvider(final File metadataFile, + private ExtendedRefreshableMetadataResolver createNewFileSystemMetaDataProvider(final Resource metadataFile, final MetadataFilter filter, final String idForLogging, final Timer timer, - final ParserPool pool) { - FilesystemMetadataResolver fileSystemResolver = null; + final ParserPool pool) throws IOException { + ResourceBackedMetadataResolver fileSystemResolver = null; try { - fileSystemResolver = new FilesystemMetadataResolver(timer, metadataFile); - fileSystemResolver.setParserPool(pool); + //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.getAbsolutePath()); + fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); fileSystemResolver.setRequireValidMetadata(true); @@ -165,10 +178,10 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { } catch (final Exception e) { log.warn("Failed to load Metadata file for " + idForLogging + "[ " + "File: " - + metadataFile.getAbsolutePath() + " Msg: " + e.getMessage() + " ]", e); + + metadataFile.getURI().toASCIIString() + " Msg: " + e.getMessage() + " ]", e); log.warn("Can not initialize SAML2 metadata provider from filesystem: " - + metadataFile.getAbsolutePath() + " Reason: " + e.getMessage(), e); + + metadataFile.getURI().toASCIIString() + " Reason: " + e.getMessage(), e); if (fileSystemResolver != null) { fileSystemResolver.destroy(); @@ -193,7 +206,7 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { * * @return SAML2 Metadata Provider */ - private MetadataResolver createNewHttpMetaDataProvider(final String metadataUrl, + private ExtendedRefreshableMetadataResolver createNewHttpMetaDataProvider(final String metadataUrl, final MetadataFilter filter, final String idForLogging, final Timer timer, final ParserPool pool, final HttpClient httpClient) { HTTPMetadataResolver httpMetadataResolver = null; @@ -240,4 +253,19 @@ public abstract class SimpleMetadataResolver implements MetadataResolver { 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"); + + } + } |