diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy
index 34e73233c..09f54ab75 100644
--- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy
+++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy
@@ -1,19 +1,14 @@
package edu.internet2.tier.shibboleth.admin.ui.service;
-import com.google.common.base.Predicate;
-import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter;
-import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver
-import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects;
-
-import com.google.common.base.Predicate
import com.google.common.base.Predicate
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver
@@ -111,10 +106,6 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
'requireSignedRoot': 'true',
'certificateFile': '%{idp.home}/credentials/inc-md-cert.pem'
)
- MetadataFilter(
- 'xsi:type': 'RequiredValidUntil',
- 'maxValidityInterval': 'P14D'
- )
//TODO: enhance
mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter ->
constructXmlNodeForFilter(filter, delegate)
@@ -199,6 +190,13 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
}
}
+ void constructXmlNodeForFilter(RequiredValidUntilFilter filter, def markupBuilderDelegate) {
+ markupBuilderDelegate.MetadataFilter(
+ 'xsi:type': 'RequiredValidUntil',
+ maxValidityInterval: filter.maxValidityInterval
+ )
+ }
+
void constructXmlNodeForResolver(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) {
markupBuilderDelegate.MetadataProvider(id: resolver.name,
'xsi:type': 'FileBackedHTTPMetadataProvider',
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java
index 40de7ea46..9735b708f 100644
--- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java
@@ -3,6 +3,7 @@
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter;
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter;
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter;
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter;
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation;
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver;
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository;
@@ -168,6 +169,11 @@ else if(filterWithUpdatedData instanceof EntityRoleWhiteListFilter) {
toFilter.setRemoveRolelessEntityDescriptors(fromFilter.getRemoveRolelessEntityDescriptors());
toFilter.setRetainedRoles(fromFilter.getRetainedRoles());
}
+ else if(filterWithUpdatedData instanceof RequiredValidUntilFilter) {
+ RequiredValidUntilFilter toFilter = RequiredValidUntilFilter.class.cast(filterToBeUpdated);
+ RequiredValidUntilFilter fromFilter = RequiredValidUntilFilter.class.cast(filterWithUpdatedData);
+ toFilter.setMaxValidityInterval(fromFilter.getMaxValidityInterval());
+ }
//TODO: add other types of concrete filters update here
}
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/MetadataFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/MetadataFilter.java
index aa5b063a4..3702bba3d 100644
--- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/MetadataFilter.java
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/MetadataFilter.java
@@ -29,7 +29,8 @@
@ToString
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "@type", visible = true)
@JsonSubTypes({@JsonSubTypes.Type(value=EntityRoleWhiteListFilter.class, name="EntityRoleWhiteList"),
- @JsonSubTypes.Type(value=EntityAttributesFilter.class, name="EntityAttributes")})
+ @JsonSubTypes.Type(value=EntityAttributesFilter.class, name="EntityAttributes"),
+ @JsonSubTypes.Type(value=RequiredValidUntilFilter.class, name="RequiredValidUntil")})
public class MetadataFilter extends AbstractAuditable {
@JsonProperty("@type")
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/RequiredValidUntilFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/RequiredValidUntilFilter.java
new file mode 100644
index 000000000..86bc03426
--- /dev/null
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/RequiredValidUntilFilter.java
@@ -0,0 +1,22 @@
+package edu.internet2.tier.shibboleth.admin.ui.domain.filters;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import javax.persistence.Entity;
+
+@Entity
+@EqualsAndHashCode(callSuper = true)
+@Getter
+@Setter
+@ToString
+public class RequiredValidUntilFilter extends MetadataFilter {
+
+ public RequiredValidUntilFilter() {
+ type = "RequiredValidUntil";
+ }
+
+ private String maxValidityInterval;
+}
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy
index c9cef2cb3..4e5899f49 100644
--- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator
import edu.internet2.tier.shibboleth.admin.util.AttributeUtility
@@ -74,28 +75,54 @@ class PolymorphicFiltersJacksonHandlingTests extends Specification {
simulatedPrePersistentFilter.relyingPartyOverrides = simulatedPersistentFilter.relyingPartyOverrides
simulatedPrePersistentFilter.fromTransientRepresentation()
+ expect:
+ simulatedPersistentFilter.attributes.size() == simulatedPrePersistentFilter.attributes.size()
+ }
+
+ def "Correct polymorphic serialization of RequiredValidUntilFilter"() {
+ given:
+ def givenFilterJson = """
+ {
+ "@type" : "RequiredValidUntil",
+ "createdDate" : null,
+ "modifiedDate" : null,
+ "createdBy" : null,
+ "modifiedBy" : null,
+ "name" : null,
+ "resourceId" : "9667ae04-8c36-4741-be62-dd325e7d6790",
+ "filterEnabled" : true,
+ "version" : 0,
+ "maxValidityInterval" : "P14D"
+
+ }
+ """
+
when:
- def jsonFromPersistentFilter = mapper.writeValueAsString(simulatedPersistentFilter)
- def jsonFromPrePersistentFilter = mapper.writeValueAsString(simulatedPrePersistentFilter)
- println("JSON from persistent filter -> $jsonFromPersistentFilter")
- println("JSON from PRE persistent filter -> $jsonFromPrePersistentFilter")
- println("Attributes from persistent filter -> $simulatedPersistentFilter.attributes")
- println("Attributes from PRE persistent filter -> $simulatedPrePersistentFilter.attributes")
+ def deSerializedFilter = mapper.readValue(givenFilterJson, MetadataFilter)
+ def json = mapper.writeValueAsString(deSerializedFilter)
+ println(json)
+ def roundTripFilter = mapper.readValue(json, MetadataFilter)
then:
- simulatedPersistentFilter.attributes.size() == simulatedPrePersistentFilter.attributes.size()
+ roundTripFilter == deSerializedFilter
+
+ and:
+ deSerializedFilter instanceof RequiredValidUntilFilter
+ roundTripFilter instanceof RequiredValidUntilFilter
}
def "List of filters with correct types"() {
given:
- def filters = testObjectGenerator.buildAllTypesOfFilterList();
+ def filters = testObjectGenerator.buildAllTypesOfFilterList()
when:
def json = mapper.writeValueAsString(filters)
println(json)
then:
- json
+ json.contains('EntityAttributes')
+ json.contains('RequiredValidUntil')
+ json.contains('EntityAttributes')
}
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy
index 6a90b2507..4e4600ae9 100644
--- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy
@@ -4,6 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat
import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository
import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator
@@ -19,8 +21,7 @@ import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.ContextConfiguration
-import org.xmlunit.builder.DiffBuilder
-import org.xmlunit.builder.Input
+
import spock.lang.Specification
import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.*
@@ -43,6 +44,10 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification {
def 'simple test generation of metadata-providers.xml'() {
when:
+ def mr = metadataResolverRepository.findAll().iterator().next()
+ mr.metadataFilters << requiredValidUntilFilterForXmlGenerationTests()
+ mr.metadataFilters << entityRoleWhiteListFilterForXmlGenerationTests()
+ metadataResolverRepository.save(mr)
def output = metadataResolverService.generateConfiguration()
println(output.documentElement)
@@ -55,6 +60,7 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification {
when:
//TODO: this might break later
def mr = metadataResolverRepository.findAll().iterator().next()
+ mr.metadataFilters << requiredValidUntilFilterForXmlGenerationTests()
mr.metadataFilters.add(new EntityAttributesFilter().with {
it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with {
it.entityAttributesFilterTargetType = EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY
@@ -70,6 +76,7 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification {
it.attributes = [attribute]
it
})
+ mr.metadataFilters << entityRoleWhiteListFilterForXmlGenerationTests()
metadataResolverRepository.save(mr)
def output = metadataResolverService.generateConfiguration()
@@ -78,6 +85,20 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification {
generatedXmlIsTheSameAsExpectedXml('/conf/278.2.xml', output)
}
+ EntityRoleWhiteListFilter entityRoleWhiteListFilterForXmlGenerationTests() {
+ new EntityRoleWhiteListFilter().with {
+ it.retainedRoles = ['md:SPSSODescriptor']
+ it
+ }
+ }
+
+ RequiredValidUntilFilter requiredValidUntilFilterForXmlGenerationTests() {
+ new RequiredValidUntilFilter().with {
+ it.maxValidityInterval = 'P14D'
+ it
+ }
+ }
+
//TODO: check that this configuration is sufficient
@TestConfiguration
static class TestConfig {
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy
index 546315d6f..e548d26b5 100644
--- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy
@@ -4,6 +4,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat
import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository
@@ -139,6 +140,21 @@ class JPAMetadataResolverServiceImplTests extends Specification {
then:
generatedXmlIsTheSameAsExpectedXml('/conf/533.xml', domBuilder.parseText(writer.toString()))
+
+ }
+
+ def 'test generating RequiredValidUntilFilter xml snippet'() {
+ given:
+ def filter = new RequiredValidUntilFilter().with {
+ it.maxValidityInterval = 'P14D'
+ it
+ }
+
+ when:
+ genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) }
+
+ then:
+ generatedXmlIsTheSameAsExpectedXml('/conf/552.xml', domBuilder.parseText(writer.toString()))
}
def 'test generating FileBackedHttMetadataResolver xml snippet'() {
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy
index c2c6f7761..04066c581 100644
--- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy
@@ -27,8 +27,11 @@ class TestHelpers {
}
static void generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Document generatedXml) {
- assert !DiffBuilder.compare(Input.fromStream(TestHelpers.getResourceAsStream(expectedXmlResource))).withTest(Input.fromDocument(generatedXml))
- .ignoreComments().ignoreWhitespace().build().hasDifferences()
-
+ assert !DiffBuilder.compare(Input.fromStream(TestHelpers.getResourceAsStream(expectedXmlResource)))
+ .withTest(Input.fromDocument(generatedXml))
+ .ignoreComments()
+ .ignoreWhitespace()
+ .build()
+ .hasDifferences()
}
}
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy
index 4069ab849..b2dd89727 100644
--- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy
@@ -5,12 +5,14 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFil
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter
+import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterTargetRepresentation
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.*
import edu.internet2.tier.shibboleth.admin.util.AttributeUtility
import edu.internet2.tier.shibboleth.admin.util.MDDCConstants
+
import org.opensaml.saml.saml2.metadata.Organization
import java.util.function.Supplier
@@ -119,6 +121,7 @@ class TestObjectGenerator {
(1..generator.randomInt(4, 10)).each {
filterList.add(buildFilter { entityAttributesFilter() })
filterList.add(buildFilter { entityRoleWhitelistFilter() })
+ filterList.add(buildFilter { requiredValidUntilFilter() })
}
return filterList
}
@@ -142,6 +145,13 @@ class TestObjectGenerator {
}
}
+ RequiredValidUntilFilter requiredValidUntilFilter() {
+ return new RequiredValidUntilFilter().with {
+ it.maxValidityInterval = 'P14D'
+ it
+ }
+ }
+
EntityAttributesFilter copyOf(EntityAttributesFilter entityAttributesFilter) {
new EntityAttributesFilter().with {
it.name = entityAttributesFilter.name
diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml
index b50d8e3d7..bd6c3b082 100644
--- a/backend/src/test/resources/conf/278.2.xml
+++ b/backend/src/test/resources/conf/278.2.xml
@@ -32,6 +32,9 @@
https://sp1.example.org
+
+ md:SPSSODescriptor
+
-
-
-
+
\ No newline at end of file
diff --git a/backend/src/test/resources/conf/278.xml b/backend/src/test/resources/conf/278.xml
index be69c5487..7241943ab 100644
--- a/backend/src/test/resources/conf/278.xml
+++ b/backend/src/test/resources/conf/278.xml
@@ -25,6 +25,9 @@
xsi:type="DynamicHttpMetadataProvider">
+
+ md:SPSSODescriptor
+
-
-
-
+
\ No newline at end of file
diff --git a/backend/src/test/resources/conf/552.xml b/backend/src/test/resources/conf/552.xml
new file mode 100644
index 000000000..6253b2323
--- /dev/null
+++ b/backend/src/test/resources/conf/552.xml
@@ -0,0 +1,9 @@
+
+
+
+
+