From ae97066d48525ec71392ca9b8df0e2b1a4f881ca Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 9 Aug 2022 13:55:06 -0700 Subject: [PATCH] SHIBUI-2268 Refactoring and simplifying code for AlgorithmFilter --- ...gorithmFilterUiDefinitionController.groovy | 56 +++++++++ .../JPAMetadataResolverServiceImpl.groovy | 62 +++++++--- .../domain/{filters/algorithm => }/MGF.java | 3 +- .../{filters/algorithm => }/OtherSource.java | 3 +- .../domain/{filters/algorithm => }/PRF.java | 3 +- .../domain/filters/AbstractFilterTarget.java | 39 +++++++ .../filters/EntityAttributesFilterTarget.java | 39 +------ .../ui/domain/filters/MetadataFilter.java | 2 +- .../filters/NameIdFormatFilterTarget.java | 29 +---- .../filters/algorithm/AlgorithmFilter.java | 38 +++--- .../algorithm/AlgorithmFilterTarget.java | 34 ++++++ .../filters/algorithm/ConditionRef.java | 38 ------ .../filters/algorithm/ConditionScript.java | 38 ------ .../ui/domain/filters/algorithm/Entity.java | 38 ------ .../jsonschema/JsonSchemaLocationLookup.java | 12 ++ .../resources/algorithm-filter.schema.json | 33 ++++++ ...JPAMetadataResolverServiceImplTests.groovy | 108 ++++-------------- .../src/test/resources/conf/2268-complex.xml | 29 ----- .../conf/{2268-simple.xml => 2268-entity.xml} | 0 .../conf/{2268-actual.xml => 2268-script.xml} | 2 - 20 files changed, 268 insertions(+), 338 deletions(-) create mode 100644 backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AlgorithmFilterUiDefinitionController.groovy rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/{filters/algorithm => }/MGF.java (78%) rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/{filters/algorithm => }/OtherSource.java (79%) rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/{filters/algorithm => }/PRF.java (78%) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/AbstractFilterTarget.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilterTarget.java delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java create mode 100644 backend/src/main/resources/algorithm-filter.schema.json delete mode 100644 backend/src/test/resources/conf/2268-complex.xml rename backend/src/test/resources/conf/{2268-simple.xml => 2268-entity.xml} (100%) rename backend/src/test/resources/conf/{2268-actual.xml => 2268-script.xml} (95%) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AlgorithmFilterUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AlgorithmFilterUiDefinitionController.groovy new file mode 100644 index 000000000..9c7698235 --- /dev/null +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AlgorithmFilterUiDefinitionController.groovy @@ -0,0 +1,56 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +import com.fasterxml.jackson.databind.ObjectMapper +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry +import edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService +import groovy.util.logging.Slf4j +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.tags.Tags +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +import javax.annotation.PostConstruct + +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR + +/** + * Controller implementing REST resource responsible for exposing structure definition for algorithm format filter user + * interface in terms of JSON schema. + */ +@RestController +@RequestMapping('/api/ui/AlgorithmFilter') +@Slf4j +@Tags(value = [@Tag(name = "ui")]) +class AlgorithmFilterUiDefinitionController { + + @Autowired + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry + + JsonSchemaResourceLocation jsonSchemaLocation + + @Autowired + ObjectMapper jacksonObjectMapper + + @Autowired + JsonSchemaBuilderService jsonSchemaBuilderService + + @GetMapping + ResponseEntity getUiDefinitionJsonSchema() { + try { + def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map) + return ResponseEntity.ok(parsedJson) + } catch (Exception e) { + log.error(e.getMessage(), e) + return ResponseEntity.status(INTERNAL_SERVER_ERROR).body([jsonParseError : e.getMessage(), sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url]) + } + } + + @PostConstruct + void init() { +// this.jsonSchemaLocation = algorithmFilterSchema(this.jsonSchemaResourceLocationRegistry) + } +} \ No newline at end of file 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 78ca12254..f3f0b0eb3 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 @@ -2,6 +2,8 @@ package edu.internet2.tier.shibboleth.admin.ui.service import com.google.common.base.Predicate import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethod +import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethodBuilder import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotFoundException import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget @@ -10,9 +12,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.SignatureValidationFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AlgorithmFilter -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.ConditionRef -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.ConditionScript -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.Entity +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AlgorithmFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.filters.opensaml.OpenSamlNameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver @@ -109,24 +109,50 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { 'xmlns:alg': 'urn:oasis:names:tc:SAML:metadata:algsupport', 'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#' ) { - filter.unknownXMLObjects.each { xmlObject -> - { - if (xmlObject instanceof Entity) { - Entity(xmlObject.getValue()) - } else if (xmlObject instanceof ConditionRef) { - ConditionRef(xmlObject.getValue()) - } else if (xmlObject instanceof ConditionScript) { - ConditionScript() { - Script() { - def script = xmlObject.getValue() - mkp.yieldUnescaped("\n\n") - } + for (String algValue : filter.getAlgorithms()) { + EncryptionMethod method = new EncryptionMethodBuilder().buildObject(); + method.setAlgorithm(algValue) + mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(method, false)) + } + switch (filter.algorithmFilterTarget.targetType) { + case AlgorithmFilterTarget.AlgorithmFilterTargetType.ENTITY: + filter.algorithmFilterTarget.value.each { + Entity(it) + } + break + case AlgorithmFilterTarget.AlgorithmFilterTargetType.CONDITION_REF: + ConditionRef(xmlObject.getValue()) + break + case AlgorithmFilterTarget.AlgorithmFilterTargetType.CONDITION_SCRIPT: + ConditionScript() { + Script() { + def script = filter.getAlgorithmFilterTarget().value[0] + mkp.yieldUnescaped("\n\n") } - } else { - mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(xmlObject, false)) } - } + break + default: + // do nothing, we'd have exploded elsewhere previously. + break } +// filter.unknownXMLObjects.each { xmlObject -> +// { +// if (xmlObject instanceof Entity) { +// Entity(xmlObject.getValue()) +// } else if (xmlObject instanceof ConditionRef) { +// ConditionRef(xmlObject.getValue()) +// } else if (xmlObject instanceof ConditionScript) { +// ConditionScript() { +// Script() { +// def script = xmlObject.getValue() +// mkp.yieldUnescaped("\n\n") +// } +// } +// } else { +// mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(xmlObject, false)) +// } +// } +// } } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/MGF.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MGF.java similarity index 78% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/MGF.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MGF.java index f78eaaf00..0278b3af8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/MGF.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MGF.java @@ -1,5 +1,6 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; +package edu.internet2.tier.shibboleth.admin.ui.domain; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AbstractAlgorithmIdentifierType; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/OtherSource.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OtherSource.java similarity index 79% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/OtherSource.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OtherSource.java index b57e0c82c..afc50b3f4 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/OtherSource.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OtherSource.java @@ -1,5 +1,6 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; +package edu.internet2.tier.shibboleth.admin.ui.domain; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AbstractAlgorithmIdentifierType; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/PRF.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PRF.java similarity index 78% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/PRF.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PRF.java index 3ee2dabec..b621a0278 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/PRF.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PRF.java @@ -1,5 +1,6 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; +package edu.internet2.tier.shibboleth.admin.ui.domain; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AbstractAlgorithmIdentifierType; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/AbstractFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/AbstractFilterTarget.java new file mode 100644 index 000000000..a26c06e88 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/AbstractFilterTarget.java @@ -0,0 +1,39 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters; + +import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractAuditable; +import lombok.EqualsAndHashCode; + +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.FetchType; +import javax.persistence.MappedSuperclass; +import javax.persistence.OrderColumn; +import java.util.ArrayList; +import java.util.List; + +@MappedSuperclass +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractFilterTarget extends AbstractAuditable implements IFilterTarget { + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn + @Column(length = 760, name="target_value") + protected List value; + + @Override + public List getValue() { + return value == null ? new ArrayList<>() : value; + } + + @Override + public void setSingleValue(String value) { + List values = new ArrayList<>(); + values.add(value); + this.value = values; + } + + @Override + public void setValue(List value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java index e2ed028a0..b2ffb6b0d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java @@ -4,31 +4,21 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractAuditable; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; -import javax.persistence.Column; -import javax.persistence.ElementCollection; import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.OrderColumn; -import java.util.ArrayList; -import java.util.List; @Entity @EqualsAndHashCode(callSuper = true) +@ToString @Audited @AuditOverride(forClass = AbstractAuditable.class) @JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) -public class EntityAttributesFilterTarget extends AbstractAuditable implements IFilterTarget { - +public class EntityAttributesFilterTarget extends AbstractFilterTarget { private EntityAttributesFilterTargetType entityAttributesFilterTargetType; - @ElementCollection (fetch = FetchType.EAGER) - @OrderColumn - @Column(length = 760, name="target_value") - private List value; - public EntityAttributesFilterTargetType getEntityAttributesFilterTargetType() { return entityAttributesFilterTargetType; } @@ -39,33 +29,10 @@ public String getTargetTypeValue() { return entityAttributesFilterTargetType == null ? "NONE" : entityAttributesFilterTargetType.name(); } - @Override - public List getValue() { - return value == null ? new ArrayList<>() : value; - } - public void setEntityAttributesFilterTargetType(EntityAttributesFilterTargetType entityAttributesFilterTarget) { this.entityAttributesFilterTargetType = entityAttributesFilterTarget; } - public void setSingleValue(String value) { - List values = new ArrayList<>(); - values.add(value); - this.value = values; - } - - public void setValue(List value) { - this.value = value; - } - - @Override - public String toString() { - return "EntityAttributesFilterTarget{" + - "entityAttributesFilterTargetType=" + entityAttributesFilterTargetType + - ", value=" + value + - '}'; - } - public enum EntityAttributesFilterTargetType { ENTITY, CONDITION_SCRIPT, CONDITION_REF, REGEX } 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 548c97356..c566576df 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 @@ -50,7 +50,7 @@ public abstract class MetadataFilter extends AbstractAuditable implements IConcr @JsonProperty("@type") @Transient - String type; + protected String type; @Transient private transient Integer version; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java index 3a5bfe9da..c5441a053 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java @@ -8,29 +8,18 @@ import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; -import javax.persistence.Column; -import javax.persistence.ElementCollection; import javax.persistence.Entity; -import javax.persistence.OrderColumn; -import javax.persistence.Transient; -import java.util.ArrayList; -import java.util.List; @Entity @EqualsAndHashCode(callSuper = true) @ToString @Audited @AuditOverride(forClass = AbstractAuditable.class) -@JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) -public class NameIdFormatFilterTarget extends AbstractAuditable implements IFilterTarget { +@JsonIgnoreProperties({ "handler", "hibernateLazyInitializer" }) +public class NameIdFormatFilterTarget extends AbstractFilterTarget { private NameIdFormatFilterTargetType nameIdFormatFilterTargetType; - @ElementCollection - @OrderColumn - @Column(name="target_value") - private List value; - public NameIdFormatFilterTargetType getNameIdFormatFilterTargetType() { return nameIdFormatFilterTargetType; } @@ -41,24 +30,10 @@ public String getTargetTypeValue() { return nameIdFormatFilterTargetType.name(); } - public List getValue() { - return value; - } - public void setNameIdFormatFilterTargetType(NameIdFormatFilterTargetType nameIdFormatFilterTargetType) { this.nameIdFormatFilterTargetType = nameIdFormatFilterTargetType; } - public void setSingleValue(String value) { - List values = new ArrayList<>(); - values.add(value); - this.value = values; - } - - public void setValue(List value) { - this.value = value; - } - public enum NameIdFormatFilterTargetType { ENTITY, CONDITION_SCRIPT, REGEX } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java index 85a4d9129..52e08b436 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java @@ -1,54 +1,46 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; -import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractXMLObject; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.IFilterTarget; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.ITargetable; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter; -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.SignatureValidationFilter; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.hibernate.envers.Audited; -import org.opensaml.core.xml.ElementExtensibleXMLObject; -import org.opensaml.core.xml.XMLObject; -import javax.annotation.Nonnull; import javax.persistence.CascadeType; import javax.persistence.ElementCollection; import javax.persistence.Entity; -import javax.persistence.OneToMany; +import javax.persistence.OneToOne; import javax.persistence.OrderColumn; -import javax.xml.namespace.QName; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -/** - * Following the pattern of AbstractElementExtensibleXMLObject - this XML type can hold a couple of different types of XML objects - */ @Entity @Audited @Getter @Setter @ToString @EqualsAndHashCode(callSuper = true) -public class AlgorithmFilter extends MetadataFilter { - @OneToMany(cascade = CascadeType.ALL) +public class AlgorithmFilter extends MetadataFilter implements ITargetable { + @OneToOne(cascade = CascadeType.ALL) private AlgorithmFilterTarget algorithmFilterTarget; + + @ElementCollection @OrderColumn - private List unknownXMLObjects = new ArrayList<>(); + private List algorithms; - public void addUnknownXMLObject(AbstractXMLObject xmlObject) { - this.unknownXMLObjects.add(xmlObject); + public AlgorithmFilter() { + type = "Algorithm"; } - @Nonnull - public List getUnknownXMLObjects() { - return (List) (List) this.unknownXMLObjects; + @Override + public IFilterTarget getTarget() { + return algorithmFilterTarget; } private AlgorithmFilter updateConcreteFilterTypeData(AlgorithmFilter filterToBeUpdated) { - for (XMLObject o : getUnknownXMLObjects()) { - filterToBeUpdated.addUnknownXMLObject((AbstractXMLObject) o); - } + filterToBeUpdated.setAlgorithms(getAlgorithms()); + filterToBeUpdated.setAlgorithmFilterTarget(getAlgorithmFilterTarget()); return filterToBeUpdated; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilterTarget.java new file mode 100644 index 000000000..558231038 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilterTarget.java @@ -0,0 +1,34 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractAuditable; +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.AbstractFilterTarget; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.hibernate.envers.AuditOverride; +import org.hibernate.envers.Audited; + +import javax.persistence.Entity; + +@Entity +@EqualsAndHashCode(callSuper = true) +@ToString +@Audited +@AuditOverride(forClass = AbstractAuditable.class) +@JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) +public class AlgorithmFilterTarget extends AbstractFilterTarget { + private AlgorithmFilterTargetType targetType; + + @Override + public String getTargetTypeValue() { + return targetType == null ? "NONE" : targetType.name(); + } + + public void setAlgorithmFilterTargetType(AlgorithmFilterTargetType type) { + this.targetType = type; + } + + public enum AlgorithmFilterTargetType { + ENTITY, CONDITION_SCRIPT, CONDITION_REF + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java deleted file mode 100644 index b35cd0762..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java +++ /dev/null @@ -1,38 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; - -import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractXMLObject; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.hibernate.envers.Audited; - -import javax.annotation.Nullable; - -@javax.persistence.Entity -@Audited -@Getter -@Setter -@ToString -@EqualsAndHashCode(callSuper = true) -/** - * The textual content (the value/uri) is the Bean ID of type Predicate - */ -public class ConditionRef extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { - private String uri; - - public ConditionRef() { - setElementLocalName("ConditionRef"); - } - - @Nullable - @Override - public String getValue() { - return this.uri; - } - - @Override - public void setValue(@Nullable String newValue) { - this.uri = newValue; - } -} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java deleted file mode 100644 index a2d58382a..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java +++ /dev/null @@ -1,38 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; - -import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractXMLObject; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.hibernate.envers.Audited; - -import javax.annotation.Nullable; - -@javax.persistence.Entity -@Audited -@Getter -@Setter -@ToString -@EqualsAndHashCode(callSuper = true) -/** - * The textual content is the JS script (the export of the XML will wrap it appropriately) - */ -public class ConditionScript extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { - private String uri; - - public ConditionScript() { - setElementLocalName("ConditionScript"); - } - - @Nullable - @Override - public String getValue() { - return this.uri; - } - - @Override - public void setValue(@Nullable String newValue) { - this.uri = newValue; - } -} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java deleted file mode 100644 index 18dfcbe8e..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java +++ /dev/null @@ -1,38 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; - -import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractXMLObject; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.hibernate.envers.Audited; - -import javax.annotation.Nullable; - -@javax.persistence.Entity -@Audited -@Getter -@Setter -@ToString -@EqualsAndHashCode(callSuper = true) -/** - * The textual content (value/uri) is an entityID. - */ -public class Entity extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { - private String uri; - - public Entity(){ - setElementLocalName("Entity"); - } - - @Nullable - @Override - public String getValue() { - return this.uri; - } - - @Override - public void setValue(@Nullable String newValue) { - this.uri = newValue; - } -} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java index b44e4e7ce..4e7da170f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java @@ -105,4 +105,16 @@ public static JsonSchemaResourceLocation nameIdFormatFilterSchema(JsonSchemaReso .lookup(NAME_ID_FORMAT_FILTER) .orElseThrow(() -> new IllegalStateException("JSON schema resource location for name id format filter is not registered.")); } + +// /** +// * Searches algorithm filter JSON schema resource location object in the given location registry. +// * +// * @param resourceLocationRegistry +// * @return algorithm filter JSON schema resource location object +// * @throws IllegalStateException if schema is not found in the given registry +// */ +// public static JsonSchemaResourceLocation algorithmFilterSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { +// return resourceLocationRegistry.lookup(ALGORITHM_FILTER) +// .orElseThrow(() -> new IllegalStateException("JSON schema resource location for algorithm filter is not registered.")); +// } } \ No newline at end of file diff --git a/backend/src/main/resources/algorithm-filter.schema.json b/backend/src/main/resources/algorithm-filter.schema.json new file mode 100644 index 000000000..642acbb4b --- /dev/null +++ b/backend/src/main/resources/algorithm-filter.schema.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "required": [ + "name" + ], + "properties": { + "@type": { + "type": "string", + "default": "Algorithm" + }, + "name": { + "title": "label.filter-algorithm", + "description": "tooltip.filter-algorithm", + "type": "string" + }, + "filterEnabled": { + "title": "label.enable-filter", + "description": "tooltip.enable-filter", + "type": "boolean", + "default": false + }, + "version": { + "type": "integer" + }, + "resourceId": { + "type": "string" + }, + "unknownXMLObjects": { + + } + }, + "definitions": {} +} \ No newline at end of file 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 505d1507a..4fe54e9cc 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 @@ -1,23 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.service - import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.AlgorithmDigestMethod import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethod import edu.internet2.tier.shibboleth.admin.ui.domain.SignatureDigestMethod -import edu.internet2.tier.shibboleth.admin.ui.domain.SigningMethod import edu.internet2.tier.shibboleth.admin.ui.domain.XSString 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.MetadataFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.ConditionRef -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.ConditionScript -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.Entity -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.MGF -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.PRF +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.AlgorithmFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ClasspathMetadataResource import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver @@ -194,101 +188,45 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { !diff.hasDifferences() } - def 'test generating AlgorithmFilter xml snippet'() { + def 'test generating AlgorithmFilter shibui-2268 entities'() { given: def filter = TestObjectGenerator.algorithmFilter() - EncryptionMethod encryptionMethod = new EncryptionMethod() - encryptionMethod.setElementLocalName(EncryptionMethod.DEFAULT_ELEMENT_LOCAL_NAME) - encryptionMethod.setNamespacePrefix(SAMLConstants.SAML20MD_PREFIX) - encryptionMethod.setNamespaceURI(SAMLConstants.SAML20MD_NS) - encryptionMethod.setSchemaLocation(SAMLConstants.SAML20MD_SCHEMA_LOCATION) - encryptionMethod.setAlgorithm("http://www.w3.org/2001/04/xmlenc#aes128-cbc") - filter.addUnknownXMLObject(encryptionMethod) - - Entity entity = new Entity() - entity.setValue("https://broken.example.org/sp") - filter.addUnknownXMLObject(entity) - Entity entity2 = new Entity() - entity2.setValue("https://also-broken.example.org/sp") - filter.addUnknownXMLObject(entity2) + ArrayList algs = new ArrayList<>() + algs.add("http://www.w3.org/2001/04/xmlenc#aes128-cbc") + filter.setAlgorithms(algs) + + AlgorithmFilterTarget target = new AlgorithmFilterTarget() + target.setAlgorithmFilterTargetType(AlgorithmFilterTarget.AlgorithmFilterTargetType.ENTITY) + ArrayList entities = new ArrayList<>() + entities.add("https://broken.example.org/sp") + entities.add("https://also-broken.example.org/sp") + target.setValue(entities) + filter.setAlgorithmFilterTarget(target) when: genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) } then: - generatedXmlIsTheSameAsExpectedXml('/conf/2268-simple.xml', domBuilder.parseText(writer.toString())) + generatedXmlIsTheSameAsExpectedXml('/conf/2268-entity.xml', domBuilder.parseText(writer.toString())) } - def 'test generating AlgorithmFilter shibui-2268 actual'() { + def 'test generating AlgorithmFilter shibui-2268 script'() { given: def filter = TestObjectGenerator.algorithmFilter() - EncryptionMethod encryptionMethod = new EncryptionMethod() - encryptionMethod.setElementLocalName(EncryptionMethod.DEFAULT_ELEMENT_LOCAL_NAME) - encryptionMethod.setNamespacePrefix(SAMLConstants.SAML20MD_PREFIX) - encryptionMethod.setNamespaceURI(SAMLConstants.SAML20MD_NS) - encryptionMethod.setSchemaLocation(SAMLConstants.SAML20MD_SCHEMA_LOCATION) - encryptionMethod.setAlgorithm("http://www.w3.org/2001/04/xmlenc#aes128-cbc") - filter.addUnknownXMLObject(encryptionMethod) + ArrayList algs = new ArrayList<>() + algs.add("http://www.w3.org/2001/04/xmlenc#aes128-cbc") + filter.setAlgorithms(algs) - Entity entity = new Entity() - entity.setValue("https://broken.example.org/sp") - filter.addUnknownXMLObject(entity) - - ConditionRef cr = new ConditionRef() - cr.setValue("shibboleth.Conditions.TRUE") - filter.addUnknownXMLObject(cr) - - ConditionScript cs = new ConditionScript() - cs.setValue("\"use strict\";\nfalse;") - filter.addUnknownXMLObject(cs) - - when: - genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) } - - then: - generatedXmlIsTheSameAsExpectedXml('/conf/2268-actual.xml', domBuilder.parseText(writer.toString())) - } - - /** - * This test was written before we simplified the concept of what we'd allow the users to build in the UI. Because the test was - * already done and working, it was left here for completeness. - */ - def 'test generating complex AlgorithmFilter xml snippet'() { - given: - def filter = TestObjectGenerator.algorithmFilter() - EncryptionMethod encryptionMethod = getEncryptionMethod("http://www.w3.org/2001/04/xmlenc#aes128-cbc") - filter.addUnknownXMLObject(encryptionMethod) - - EncryptionMethod encryptionMethod2 = getEncryptionMethod("http://www.w3.org/2009/xmlenc11#rsa-oaep") - MGF mgf = new MGF() - mgf.setAlgorithm("http://www.w3.org/2009/xmlenc11#mgf1sha256") - encryptionMethod2.addUnknownXMLObject(mgf) - PRF prf = new PRF() - prf.setAlgorithm("http://www.w3.org/2009/xmlenc11#mgf1sha384") - encryptionMethod2.addUnknownXMLObject(prf) - SignatureDigestMethod dm = getSignatureDigestMethod("http://www.w3.org/2001/04/xmlenc#sha256") - encryptionMethod2.addUnknownXMLObject(dm) - filter.addUnknownXMLObject(encryptionMethod2) - - AlgorithmDigestMethod dm2 = getDigestMethod("http://www.w3.org/2001/04/xmlenc#sha51") - filter.addUnknownXMLObject(dm2) - - SigningMethod sm = new SigningMethod() - sm.setNamespaceURI(SAMLConstants.SAML20ALG_NS) - sm.setElementLocalName(SigningMethod.DEFAULT_ELEMENT_LOCAL_NAME) - sm.setNamespacePrefix(SAMLConstants.SAML20ALG_PREFIX) - sm.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512") - filter.addUnknownXMLObject(sm) - - Entity entity = new Entity() - entity.setValue("https://broken.example.org/sp") - filter.addUnknownXMLObject(entity) + AlgorithmFilterTarget target = new AlgorithmFilterTarget() + target.setAlgorithmFilterTargetType(AlgorithmFilterTarget.AlgorithmFilterTargetType.CONDITION_SCRIPT) + target.setSingleValue("\"use strict\";\nfalse;") + filter.setAlgorithmFilterTarget(target) when: genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) } then: - generatedXmlIsTheSameAsExpectedXml('/conf/2268-complex.xml', domBuilder.parseText(writer.toString())) + generatedXmlIsTheSameAsExpectedXml('/conf/2268-script.xml', domBuilder.parseText(writer.toString())) } def 'test generating EntityAttributesFilter xml snippet with condition script'() { diff --git a/backend/src/test/resources/conf/2268-complex.xml b/backend/src/test/resources/conf/2268-complex.xml deleted file mode 100644 index ee76b2f84..000000000 --- a/backend/src/test/resources/conf/2268-complex.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - https://broken.example.org/sp - - - \ No newline at end of file diff --git a/backend/src/test/resources/conf/2268-simple.xml b/backend/src/test/resources/conf/2268-entity.xml similarity index 100% rename from backend/src/test/resources/conf/2268-simple.xml rename to backend/src/test/resources/conf/2268-entity.xml diff --git a/backend/src/test/resources/conf/2268-actual.xml b/backend/src/test/resources/conf/2268-script.xml similarity index 95% rename from backend/src/test/resources/conf/2268-actual.xml rename to backend/src/test/resources/conf/2268-script.xml index 961079197..3283e883c 100644 --- a/backend/src/test/resources/conf/2268-actual.xml +++ b/backend/src/test/resources/conf/2268-script.xml @@ -14,8 +14,6 @@ xsi:type="Algorithm"> - https://broken.example.org/sp - shibboleth.Conditions.TRUE