summaryrefslogtreecommitdiff
path: root/eaaf_modules
diff options
context:
space:
mode:
authorThomas <thomas.lenz@egiz.gv.at>2020-02-02 19:32:21 +0100
committerThomas <thomas.lenz@egiz.gv.at>2020-02-02 19:32:21 +0100
commit41ea2fdf782cd64d7d29f73c2e83f9c255810818 (patch)
tree9710ca3937ae82391c6a2a0e5176923e0a49a5af /eaaf_modules
parentd41afe91ee59daf6b5f5037cecac52900fe2ccb2 (diff)
downloadEAAF-Components-41ea2fdf782cd64d7d29f73c2e83f9c255810818.tar.gz
EAAF-Components-41ea2fdf782cd64d7d29f73c2e83f9c255810818.tar.bz2
EAAF-Components-41ea2fdf782cd64d7d29f73c2e83f9c255810818.zip
some more OpenSAML3 refactoring stuff
Diffstat (limited to 'eaaf_modules')
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java28
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java7
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java4
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java92
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java15
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java318
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java96
-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
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java30
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java85
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java71
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java196
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java83
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml3
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties3
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java31
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java29
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java12
19 files changed, 658 insertions, 650 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
index e2ee0c9d..1af8db7b 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
@@ -19,33 +19,13 @@
package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
-import java.util.List;
-
-import javax.xml.namespace.QName;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.metadata.resolver.MetadataResolver;
-import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml.saml2.metadata.RoleDescriptor;
-
-public interface IPvp2MetadataProvider extends MetadataResolver {
-
- XMLObject getMetadata() throws Pvp2MetadataException;
-
-
- EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws Pvp2MetadataException;
-
-
- EntityDescriptor getEntityDescriptor(String entityID) throws Pvp2MetadataException;
-
- List<RoleDescriptor> getRole(String entityID, QName roleName) throws Pvp2MetadataException;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+public interface IPvp2MetadataProvider extends ExtendedRefreshableMetadataResolver {
- RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
- throws Pvp2MetadataException;
+ EntityDescriptor getEntityDescriptor(String entityID) throws ResolverException;
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java
index 72cb3f3c..128d4c2f 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java
@@ -22,14 +22,15 @@ package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
import java.util.Collection;
import java.util.List;
-import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
-
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.metadata.ContactPerson;
import org.opensaml.saml.saml2.metadata.Organization;
import org.opensaml.saml.saml2.metadata.RequestedAttribute;
import org.opensaml.security.credential.Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+
/**
* PVP Metadata builder configuration.
*
@@ -109,7 +110,7 @@ public interface IPvpMetadataBuilderConfiguration {
* @return Credentials
* @throws CredentialsNotAvailableException In case of an error
*/
- Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException;
+ EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException;
/**
* Set the credential for request/response signing IDP metadata: this credential
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
index 5f69ba62..39536771 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
@@ -19,13 +19,15 @@
package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;
+
/**
* Metadata provider that supports dynamic refreshing on external events.
*
* @author tlenz
*
*/
-public interface IRefreshableMetadataProvider {
+public interface IRefreshableMetadataProvider extends RefreshableMetadataResolver{
/**
* Refresh a entity or load a entity in a metadata provider.
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
index 42f69a57..d5893d4a 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
@@ -20,31 +20,19 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
import java.io.IOException;
-import java.io.StringWriter;
import java.util.Collection;
import java.util.List;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
+import javax.naming.ConfigurationException;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import at.gv.egiz.eaaf.core.exceptions.EaafException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-
-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.io.Marshaller;
import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.SignableSAMLObject;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
@@ -64,16 +52,20 @@ import org.opensaml.saml.saml2.metadata.SingleSignOnService;
import org.opensaml.security.SecurityException;
import org.opensaml.security.credential.Credential;
import org.opensaml.security.credential.UsageType;
-import org.opensaml.xml.security.SecurityHelper;
import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
-import org.opensaml.xmlsec.signature.Signature;
import org.opensaml.xmlsec.signature.support.SignatureException;
-import org.opensaml.xmlsec.signature.support.Signer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
-import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
/**
* PVP metadata builder implementation.
@@ -153,19 +145,9 @@ public class PvpMetadataBuilder {
}
}
-
- // set metadata signature parameters
- final Credential metadataSignCred = config.getMetadataSigningCredentials();
- final Signature signature = AbstractCredentialProvider.getIdpSignature(metadataSignCred);
- SecurityHelper.prepareSignatureParams(signature, metadataSignCred, null, null);
-
- // initialize XML document builder
- DocumentBuilder builder;
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-
- builder = factory.newDocumentBuilder();
- final Document document = builder.newDocument();
-
+
+ SignableSAMLObject metadataToSign;
+
// build entities descriptor
if (config.buildEntitiesDescriptorAsRootElement()) {
final EntitiesDescriptor entitiesDescriptor =
@@ -174,45 +156,29 @@ public class PvpMetadataBuilder {
entitiesDescriptor.setID(Saml2Utils.getSecureIdentifier());
entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);
-
- // load default PVP security configurations
- entitiesDescriptor.setSignature(signature);
-
- // marshall document
- final Marshaller out =
- XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entitiesDescriptor);
- out.marshall(entitiesDescriptor, document);
-
+ metadataToSign = entitiesDescriptor;
+
} else {
entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
entityDescriptor.setID(Saml2Utils.getSecureIdentifier());
-
- entityDescriptor.setSignature(signature);
-
- // marshall document
- final Marshaller out =
- XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entityDescriptor);
- out.marshall(entityDescriptor, document);
-
+ metadataToSign = entityDescriptor;
+
}
// sign metadata
- Signer.signObject(signature);
-
- // transform metadata object to XML string
- final Transformer transformer = TransformerFactory.newInstance().newTransformer();
-
- final StringWriter sw = new StringWriter();
- final StreamResult sr = new StreamResult(sw);
- final DOMSource source = new DOMSource(document);
- transformer.transform(source, sr);
- sw.close();
-
- return sw.toString();
+ final EaafX509Credential metadataSignCred = config.getMetadataSigningCredentials();
+ SignableSAMLObject signedMetadata = Saml2Utils.signSamlObject(metadataToSign, metadataSignCred, true);
+
+
+ // Serialize metadata
+ final Element document =XMLObjectSupport.marshall(signedMetadata);
+ String serializedMetadata = SerializeSupport.nodeToString(document);
+ return serializedMetadata;
+
}
private RoleDescriptor generateSpMetadata(final IPvpMetadataBuilderConfiguration config)
- throws CredentialsNotAvailableException, SecurityException, EaafException {
+ throws SecurityException, EaafException {
final SPSSODescriptor spSsoDescriptor = Saml2Utils.createSamlObject(SPSSODescriptor.class);
spSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
spSsoDescriptor.setAuthnRequestsSigned(config.wantAuthnRequestSigned());
@@ -353,7 +319,7 @@ public class PvpMetadataBuilder {
}
private IDPSSODescriptor generateIdpMetadata(final IPvpMetadataBuilderConfiguration config)
- throws EaafException, CredentialsNotAvailableException, SecurityException {
+ throws EaafException, SecurityException {
// check response signing credential
final Credential responseSignCred = config.getRequestorResponseSigningCredentials();
if (responseSignCred == null) {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
index 8a741b69..da958d5b 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
@@ -25,18 +25,18 @@ import java.io.Serializable;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
-import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
-import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
-
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
public class InboundMessage implements InboundMessageInterface, Serializable {
private static final Logger log = LoggerFactory.getLogger(InboundMessage.class);
@@ -65,9 +65,10 @@ public class InboundMessage implements InboundMessageInterface, Serializable {
return metadataProvider.getEntityDescriptor(this.entityID);
- } catch (final Pvp2MetadataException e) {
+ } catch (final ResolverException e) {
log.warn("No Metadata for EntitiyID " + entityID);
throw new NoMetadataInformationException();
+
}
}
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");
+
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
index dc60019a..d23affba 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
@@ -7,10 +7,13 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
+import org.opensaml.core.xml.XMLObject;
import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;
import com.google.common.base.Strings;
+
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
import lombok.extern.slf4j.Slf4j;
import net.shibboleth.utilities.java.support.codec.Base64Support;
@@ -34,8 +37,6 @@ public class EaafHttpPostDecoder extends HTTPPostDecoder {
encodedMessage = getLastParameterFromRequest(request, "SAMLResponse");
}
-
-
if (Strings.isNullOrEmpty(encodedMessage)) {
log.info("Request did not contain either a SAMLRequest or "
+ "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding.");
@@ -54,14 +55,27 @@ public class EaafHttpPostDecoder extends HTTPPostDecoder {
}
/**
- * Always read the last parameter with this name from request to get a strict deterministic behavior.
- * <br><br>
- * <b><i>If more than one parameters with the same name exists,
- * this method always select the last parameter value.</i></b>
+ * EAAF specific unmarshaller perform XML schema validation before unmarshalling
+ * the SAML message.
+ *
+ */
+ @Override
+ protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ return Saml2Utils.unmarshallMessage(messageStream);
+
+ }
+
+ /**
+ * Always read the last parameter with this name from request to get a strict
+ * deterministic behavior. <br>
+ * <br>
+ * <b><i>If more than one parameters with the same name exists, this method
+ * always select the last parameter value.</i></b>
*
- * @param request Incoming http request
+ * @param request Incoming http request
* @param paramName Name of the http parameter
- * @return the last parameter value with this name, or <code>null</code> if the parameter not exists
+ * @return the last parameter value with this name, or <code>null</code> if the
+ * parameter not exists
*/
@Nullable
private String getLastParameterFromRequest(@Nonnull HttpServletRequest request, @Nonnull String paramName) {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
index e9140f26..16d73296 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
@@ -4,6 +4,7 @@ import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
+import org.opensaml.core.xml.XMLObject;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.saml.common.SAMLObject;
@@ -12,6 +13,8 @@ import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
import com.google.common.base.Strings;
+
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
import lombok.extern.slf4j.Slf4j;
import net.shibboleth.utilities.java.support.net.URISupport;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
@@ -58,7 +61,7 @@ public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {
throw new MessageDecodingException(
"No SAMLRequest or SAMLResponse query path parameter, invalid SAML 2 HTTP Redirect message");
}
-
+
final SAMLObject samlMessage = (SAMLObject) unmarshallMessage(samlMessageIns);
messageContext.setMessage(samlMessage);
log.debug("Decoded SAML message");
@@ -66,6 +69,18 @@ public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {
populateBindingContext(messageContext);
setMessageContext(messageContext);
+
+ }
+
+ /**
+ * EAAF specific unmarshaller perform XML schema validation before unmarshalling
+ * the SAML message.
+ *
+ */
+ @Override
+ protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ return Saml2Utils.unmarshallMessage(messageStream);
+
}
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java
new file mode 100644
index 00000000..2e45aea2
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java
@@ -0,0 +1,85 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+import net.shibboleth.utilities.java.support.resource.Resource;
+
+/**
+ * Adapter that connects a Spring {@link org.springframework.core.io.Resource} to a {@link Resource}.
+ *
+ * @author tlenz
+ *
+ */
+public class OpenSaml3ResourceAdapter implements Resource {
+
+ private org.springframework.core.io.Resource internalResource;
+
+ public OpenSaml3ResourceAdapter(org.springframework.core.io.Resource resource) {
+ this.internalResource = resource;
+ }
+
+ @Override
+ public boolean exists() {
+ return internalResource.exists();
+ }
+
+ @Override
+ public boolean isReadable() {
+ return internalResource.isReadable();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return internalResource.isOpen();
+ }
+
+ @Override
+ public URL getURL() throws IOException {
+ return internalResource.getURL();
+ }
+
+ @Override
+ public URI getURI() throws IOException {
+ return internalResource.getURI();
+ }
+
+ @Override
+ public File getFile() throws IOException {
+ return internalResource.getFile();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return internalResource.getInputStream();
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return internalResource.contentLength();
+ }
+
+ @Override
+ public long lastModified() throws IOException {
+ return internalResource.lastModified();
+ }
+
+ @Override
+ public Resource createRelativeResource(String relativePath) throws IOException {
+ throw new IOException("This method is not supperted by this adapter");
+ }
+
+ @Override
+ public String getFilename() {
+ return internalResource.getFilename();
+ }
+
+ @Override
+ public String getDescription() {
+ return internalResource.getDescription();
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
index 8b1b041b..763c07f6 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
@@ -20,6 +20,7 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
import java.io.IOException;
+import java.io.InputStream;
import java.security.PrivateKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
@@ -36,12 +37,6 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
-import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
-
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.opensaml.core.xml.XMLObject;
@@ -49,8 +44,12 @@ import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.io.Marshaller;
import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallingException;
import org.opensaml.core.xml.schema.XSString;
import org.opensaml.core.xml.schema.impl.XSStringBuilder;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.saml.common.SAMLObjectContentReference;
import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
@@ -80,6 +79,18 @@ import org.opensaml.xmlsec.signature.support.Signer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+import net.shibboleth.utilities.java.support.xml.QNameSupport;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
public class Saml2Utils {
private static final Logger log = LoggerFactory.getLogger(Saml2Utils.class);
@@ -153,6 +164,54 @@ public class Saml2Utils {
}
/**
+ * SAML2 message unmarshaller that performs schema validation before unmarshall the message.
+ *
+ * @param messageStream SAML2 message that shoulld be unmarshalled
+ * @return OpenSAML XML object
+ * @throws MessageDecodingException In case of a schema-validation or unmarshalling error
+ */
+ public static XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ try {
+ final Element samlElement = DomUtils.parseXmlValidating(messageStream);
+
+ if (log.isTraceEnabled()) {
+ log.trace("Resultant DOM message was:");
+ log.trace(SerializeSupport.nodeToString(samlElement));
+ }
+
+ log.debug("Unmarshalling DOM parsed from InputStream");
+ final Unmarshaller unmarshaller = XMLObjectSupport.getUnmarshaller(samlElement);
+ if (unmarshaller == null) {
+ log.error("Unable to unmarshall InputStream, no unmarshaller registered for element "
+ + QNameSupport.getNodeQName(samlElement));
+ throw new UnmarshallingException(
+ "Unable to unmarshall InputStream, no unmarshaller registered for element "
+ + QNameSupport.getNodeQName(samlElement));
+ }
+
+ final XMLObject message = unmarshaller.unmarshall(samlElement);
+
+ log.debug("InputStream succesfully unmarshalled");
+
+ return message;
+
+ } catch (final UnmarshallingException e) {
+ log.error("Error unmarshalling message from input stream", e);
+ throw new MessageDecodingException("Error unmarshalling message from input stream", e);
+
+ } catch (ParserConfigurationException | SAXException e) {
+ log.warn("Message schema-validation failed.");
+ throw new MessageDecodingException("Message schema-validation failed.",
+ new SchemaValidationException("internal.pvp.03", new Object[] { e.getMessage() }, e));
+
+ } catch (final IOException e) {
+ log.error("Error read message from input stream", e);
+ throw new MessageDecodingException("Error read message from input stream", e);
+
+ }
+ }
+
+ /**
* Select signature algorithm for a given credential.
*
* @param credentials {@link X509Credential} that will be used for signing
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
deleted file mode 100644
index 380e735c..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.verification;
-
-import javax.xml.namespace.QName;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.Validator;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.core.criterion.EntityIdCriterion;
-import org.opensaml.saml.common.SignableSAMLObject;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
-import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
-import org.opensaml.security.MetadataCriteria;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.security.criteria.UsageCriterion;
-import org.opensaml.ws.security.SecurityPolicyException;
-import org.opensaml.ws.security.SecurityPolicyRule;
-import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-
-/**
- * Signature Policy for SAML2 redirect-binding.
- *
- * @author tlenz
- *
- */
-public abstract class AbstractRequestSignedSecurityPolicyRule implements SecurityPolicyRule {
-
- private static final Logger log =
- LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class);
-
- private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
-
- private SignatureTrustEngine trustEngine = null;
- private QName peerEntityRole = null;
-
- /**
- * Role initializer.
- *
- * @param peerEntityRole
- *
- */
- public AbstractRequestSignedSecurityPolicyRule(final SignatureTrustEngine trustEngine,
- final QName peerEntityRole) {
- this.trustEngine = trustEngine;
- this.peerEntityRole = peerEntityRole;
-
- }
-
- /**
- * Reload the PVP metadata for a given entity.
- *
- * @param entityID for which the metadata should be refreshed.
- * @return true if the refresh was successful, otherwise false
- */
- protected abstract boolean refreshMetadataProvider(String entityID);
-
- protected abstract SignableSAMLObject getSignedSamlObject(XMLObject inboundData);
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.opensaml.ws.security.SecurityPolicyRule#evaluate(org.opensaml.ws.message.
- * MessageContext)
- */
- @Override
- public void evaluate(final MessageContext context) throws SecurityPolicyException {
- try {
- verifySignature(context);
-
- } catch (final SecurityPolicyException e) {
- if (StringUtils.isEmpty(context.getInboundMessageIssuer())) {
- throw e;
-
- }
- log.debug("PVP2X message validation FAILED. Reload metadata for entityID: "
- + context.getInboundMessageIssuer());
- if (!refreshMetadataProvider(context.getInboundMessageIssuer())) {
- throw e;
- } else {
- log.trace("PVP2X metadata reload finished. Check validate message again.");
- verifySignature(context);
-
- }
- log.trace("Second PVP2X message validation finished");
-
- }
-
- }
-
- private void verifySignature(final MessageContext context) throws SecurityPolicyException {
- final SignableSAMLObject samlObj = getSignedSamlObject(context.getInboundMessage());
- if (samlObj != null && samlObj.getSignature() != null) {
-
- final SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
- try {
- profileValidator.validate(samlObj.getSignature());
- performSchemaValidation(samlObj.getDOM());
-
- } catch (final ValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new SecurityPolicyException("Signature is not conform to SAML signature profile");
-
- } catch (final SchemaValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new SecurityPolicyException("Signature is not conform to SAML signature profile");
-
- }
-
- final CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add(new EntityIdCriterion(context.getInboundMessageIssuer()));
- criteriaSet.add(new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS));
- criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
-
- try {
- if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) {
- throw new SecurityPolicyException("Signature validation FAILED.");
-
- }
- log.debug("PVP message signature valid.");
-
- } catch (final org.opensaml.xml.security.SecurityException e) {
- log.info("PVP2x message signature validation FAILED. Message:" + e.getMessage());
- throw new SecurityPolicyException("Signature validation FAILED.");
-
- }
-
- } else {
- throw new SecurityPolicyException("PVP Message is not signed.");
-
- }
-
- }
-
- private void performSchemaValidation(final Element source) throws SchemaValidationException {
-
- String err = null;
- try {
- final Schema test = schemaBuilder.getSAMLSchema();
- final Validator val = test.newValidator();
- val.validate(new DOMSource(source));
- log.debug("Schema validation check done OK");
- return;
-
- } catch (final SAXException e) {
- err = e.getMessage();
- if (log.isDebugEnabled() || log.isTraceEnabled()) {
- log.warn("Schema validation FAILED with exception:", e);
- } else {
- log.warn("Schema validation FAILED with message: " + e.getMessage());
- }
-
- } catch (final Exception e) {
- err = e.getMessage();
- if (log.isDebugEnabled() || log.isTraceEnabled()) {
- log.warn("Schema validation FAILED with exception:", e);
- } else {
- log.warn("Schema validation FAILED with message: " + e.getMessage());
- }
-
- }
-
- throw new SchemaValidationException("pvp2.22", new Object[] { err });
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java
deleted file mode 100644
index 9c02221c..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.verification;
-
-import javax.xml.namespace.QName;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-
-import org.opensaml.saml.common.SignableSAMLObject;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
-
-public class PvpSignedRequestPolicyRule extends AbstractRequestSignedSecurityPolicyRule {
-
- private IRefreshableMetadataProvider metadataProvider = null;
-
- /**
- * EAAF specific signature rule for OpenSAML2 redirect-binding.
- *
- * @param metadataProvider SAML2 metadata provider
- * @param trustEngine SAML2 TrustEngine
- * @param peerEntityRole Role of the Entity
- */
- public PvpSignedRequestPolicyRule(final MetadataProvider metadataProvider,
- final SignatureTrustEngine trustEngine, final QName peerEntityRole) {
- super(trustEngine, peerEntityRole);
- if (metadataProvider instanceof IRefreshableMetadataProvider) {
- this.metadataProvider = (IRefreshableMetadataProvider) metadataProvider;
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.
- * AbstractRequestSignedSecurityPolicyRule#
- * refreshMetadataProvider(java.lang.String)
- */
- @Override
- protected boolean refreshMetadataProvider(final String entityID) {
- if (metadataProvider != null) {
- return metadataProvider.refreshMetadataProvider(entityID);
- }
-
- return false;
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.
- * AbstractRequestSignedSecurityPolicyRule#
- * getSignedSAMLObject(org.opensaml.xml.XMLObject)
- */
- @Override
- protected SignableSAMLObject getSignedSamlObject(final XMLObject inboundData) {
- if (inboundData instanceof SignableSAMLObject) {
- return (SignableSAMLObject) inboundData;
- } else {
- return null;
- }
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
index 2d5dc6ea..a2b52fbc 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
@@ -13,6 +13,9 @@
<bean id="pvpLogMessageSource"
class="at.gv.egiz.eaaf.modules.pvp2.impl.logging.PvpModuleMessageSource" />
+ <bean id="pvpMetadataResolverFactory"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory"/>
+
<bean id="PVPMetadataBuilder"
class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" />
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
index 6e647bd0..cee622c2 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
@@ -1,6 +1,9 @@
internal.pvp.00=KeyStore: {0} Key with alias: {0} not found or contains no PrivateKey.
internal.pvp.01=KeyStore: {0} contains an unsupported key with alias: {1}
internal.pvp.02=PVP message contains no signature.
+internal.pvp.03=Schema-validation of SAML2 message failed with error: {0}
+internal.pvp.04=Can not initialize metadata provider for metadata: {0}
+internal.pvp.05=Can not initialize metadata provider for metadata: {0}. Reason: {1}
internal.pvp.95=OpenSAML {0}-binding message {1} failed. Reason: {2}
internal.pvp.96=OpenSAML signing FAILED with key: {0}. Reason: {1}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
index 80dfc400..a99c8461 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
@@ -6,18 +6,6 @@ import java.util.Base64;
import javax.xml.parsers.ParserConfigurationException;
-import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
-import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
-import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
-
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Assert;
@@ -42,6 +30,18 @@ import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.xml.sax.SAXException;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.net.URIComparator;
import net.shibboleth.utilities.java.support.xml.XMLParserException;
@@ -60,6 +60,7 @@ public class RedirectBindingTest {
@Autowired private RedirectBinding bindingImpl;
@Autowired private DummyCredentialProvider credentialProvider;
+ @Autowired private PvpMetadataResolverFactory metadataResolverFactory;
protected MockHttpServletRequest httpReq;
protected MockHttpServletResponse httpResp;
@@ -98,8 +99,10 @@ public class RedirectBindingTest {
@Test
public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
final String serviceUrl = "http://testservice.org";
-
- final IPvp2MetadataProvider metadataProvider = null;
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/metadata_1.xml", null, "jUnit metadata resolver", null);
final boolean isSpEndPoint = false;
final URIComparator comparator = new EaafUriCompare(serviceUrl);
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java
index 74224dbe..200d98c4 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java
@@ -23,6 +23,19 @@ import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.joda.time.DateTime;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.idp.IAction;
import at.gv.egiz.eaaf.core.api.idp.IAuthData;
@@ -44,20 +57,6 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-import org.joda.time.DateTime;
-import org.opensaml.messaging.encoder.MessageEncodingException;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.core.Assertion;
-import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.saml2.core.Response;
-import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml.saml2.metadata.EntityDescriptor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Service;
-
@Service("PVPAuthenticationRequestAction")
public class AuthenticationAction implements IAction {
private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class);
@@ -142,7 +141,7 @@ public class AuthenticationAction implements IAction {
sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier());
return sloInformation;
- } catch (MessageEncodingException | SecurityException e) {
+ } catch (SecurityException e) {
log.warn("Message Encoding exception", e);
throw new ResponderErrorException("pvp2.01", null, e);
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java
index ac551612..8cafebb9 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java
@@ -22,10 +22,6 @@ package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder;
import java.util.ArrayList;
import java.util.List;
-import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
-import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-
import org.joda.time.DateTime;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.saml.common.xml.SAMLConstants;
@@ -38,17 +34,21 @@ import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement;
import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml.security.impl.MetadataCredentialResolver;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.security.MetadataCriteria;
import org.opensaml.security.credential.UsageType;
import org.opensaml.security.criteria.UsageCriterion;
import org.opensaml.security.x509.X509Credential;
import org.opensaml.xmlsec.EncryptionParameters;
+import org.opensaml.xmlsec.encryption.support.EncryptionException;
import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters;
import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
/**
@@ -73,7 +73,7 @@ public class AuthResponseBuilder {
* @return PVP2 S-Profile authentication response
* @throws InvalidAssertionEncryptionException In case of an error
*/
- public static Response buildResponse(final MetadataProvider metadataProvider,
+ public static Response buildResponse(final IPvp2MetadataProvider metadataProvider,
final String issuerEntityID, final RequestAbstractType req, final DateTime date,
final Assertion assertion, final boolean enableEncryption)
throws InvalidAssertionEncryptionException {