From 9827498670843cac2d0b3d86626afaca028bb49e Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 21 Jun 2022 11:03:53 -0700 Subject: [PATCH 01/20] SHIBUI-2268 initial commit, no working state --- .../JPAMetadataResolverServiceImpl.groovy | 11 + .../filters/algorithm/AlgorithmFilter.java | 59 +++ .../ui/domain/filters/algorithm/Entity.java | 24 ++ .../admin/ui/opensaml/OpenSamlObjects.java | 26 +- ...XMLObjectProviderInitializerForTest.groovy | 12 + ...JPAMetadataResolverServiceImplTests.groovy | 26 +- .../admin/ui/util/TestObjectGenerator.groovy | 9 + .../org.opensaml.core.config.Initializer | 1 + .../src/test/resources/conf/2268-simple.xml | 7 + .../resources/jpa-saml2-metadata-config.xml | 372 ++++++++++++++++++ 10 files changed, 533 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy create mode 100644 backend/src/test/resources/META-INF/services/org.opensaml.core.config.Initializer create mode 100644 backend/src/test/resources/conf/2268-simple.xml create mode 100644 backend/src/test/resources/jpa-saml2-metadata-config.xml 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 ed3f794c0..691828526 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 @@ -9,6 +9,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteList 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.opensaml.OpenSamlNameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver @@ -88,6 +89,16 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } + void constructXmlNodeForFilter(AlgorithmFilter filter, def markupBuilderDelegate) { + if (!filter.isFilterEnabled()) { return } + markupBuilderDelegate.MetadataFilter('xsi:type': 'Algorithm') { + // TODO: enhance. currently this does weird things with namespaces + filter.unknownXMLObjects.each { xmlObject -> + mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(xmlObject, false)) + } + } + } + void constructXmlNodeForFilter(EntityAttributesFilter filter, def markupBuilderDelegate) { if (!filter.isFilterEnabled()) { return } markupBuilderDelegate.MetadataFilter('xsi:type': 'EntityAttributes') { 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 new file mode 100644 index 000000000..85a4d9129 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AlgorithmFilter.java @@ -0,0 +1,59 @@ +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.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.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) + @OrderColumn + private List unknownXMLObjects = new ArrayList<>(); + + public void addUnknownXMLObject(AbstractXMLObject xmlObject) { + this.unknownXMLObjects.add(xmlObject); + } + + @Nonnull + public List getUnknownXMLObjects() { + return (List) (List) this.unknownXMLObjects; + } + + private AlgorithmFilter updateConcreteFilterTypeData(AlgorithmFilter filterToBeUpdated) { + for (XMLObject o : getUnknownXMLObjects()) { + filterToBeUpdated.addUnknownXMLObject((AbstractXMLObject) o); + } + return filterToBeUpdated; + } + + @Override + public MetadataFilter updateConcreteFilterTypeData(MetadataFilter filterToBeUpdated) { + return updateConcreteFilterTypeData((AlgorithmFilter) filterToBeUpdated); + } +} \ 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 new file mode 100644 index 000000000..9a741f6e8 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/Entity.java @@ -0,0 +1,24 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; + +import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractXMLObject; + +import javax.annotation.Nullable; + +public class Entity extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { + private String uri; + + private 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/opensaml/OpenSamlObjects.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/OpenSamlObjects.java index 8a25b0855..bd149c9ff 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/OpenSamlObjects.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/OpenSamlObjects.java @@ -88,11 +88,11 @@ public void init() throws ComponentInitializationException { this.unmarshallerFactory = registry.getUnmarshallerFactory(); } - public String marshalToXmlString(XMLObject ed, boolean includeXMLDeclaration) throws MarshallingException { - Marshaller marshaller = this.marshallerFactory.getMarshaller(ed); - ed.releaseDOM(); - ed.releaseChildrenDOM(true); - String entityDescriptorXmlString = null; + public String marshalToXmlString(XMLObject xmlObject, boolean includeXMLDeclaration) throws MarshallingException { + Marshaller marshaller = this.marshallerFactory.getMarshaller(xmlObject); + xmlObject.releaseDOM(); + xmlObject.releaseChildrenDOM(true); + String resultString = null; if (marshaller != null) { try (StringWriter writer = new StringWriter()) { Transformer transformer = TransformerFactory.newInstance().newTransformer(); @@ -101,22 +101,22 @@ public String marshalToXmlString(XMLObject ed, boolean includeXMLDeclaration) th if (!includeXMLDeclaration) { transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); } - transformer.transform(new DOMSource(marshaller.marshall(ed)), new StreamResult(writer)); - entityDescriptorXmlString = writer.toString(); + transformer.transform(new DOMSource(marshaller.marshall(xmlObject)), new StreamResult(writer)); + resultString = writer.toString(); } catch (TransformerException | IOException e) { logger.error(e.getMessage(), e); } } - if (entityDescriptorXmlString == null) { + if (resultString == null) { //Figure out the best way to deal with this case - throw new RuntimeException("Unable to marshal EntityDescriptor"); + throw new RuntimeException("Unable to marshal xmlObject"); } - return entityDescriptorXmlString; + return resultString; } - public String marshalToXmlString(XMLObject ed) throws MarshallingException { - return this.marshalToXmlString(ed, true); + public String marshalToXmlString(XMLObject xmlObject) throws MarshallingException { + return this.marshalToXmlString(xmlObject, true); } public EntityDescriptor unmarshalFromXml(byte[] entityDescriptorXml) throws Exception { @@ -152,4 +152,4 @@ public T buildDefaultInstanceOfType(Class type) { throw new RuntimeException("there was a problem building an instance", e); } } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy new file mode 100644 index 000000000..0a56abe54 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy @@ -0,0 +1,12 @@ +package edu.internet2.tier.shibboleth.admin.ui.opensaml.config + +import org.opensaml.core.xml.config.AbstractXMLObjectProviderInitializer + +class JPAXMLObjectProviderInitializerForTest extends AbstractXMLObjectProviderInitializer { + @Override + protected String[] getConfigResources() { + return new String[]{ + "/jpa-saml2-metadata-config.xml", + } + } +} \ 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 594ee6750..010ee9310 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 @@ -3,10 +3,12 @@ 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.EncryptionMethod 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.Entity 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.LocalDynamicMetadataResolver @@ -16,6 +18,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.SvnMetadataResour import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.TemplateScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.opensaml.config.JPAXMLObjectProviderInitializerForTest import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import groovy.xml.DOMBuilder @@ -40,7 +43,7 @@ import java.time.Instant import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml -@ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration ]) +@ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration, JPAXMLObjectProviderInitializerForTest ]) class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { @Autowired @@ -137,6 +140,27 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { !diff.hasDifferences() } + def 'test generating AlgorithmFilter xml snippet'() { + given: + def filter = TestObjectGenerator.algorithmFilter() + EncryptionMethod encryptionMethod = new EncryptionMethod() + encryptionMethod.setAlgorithm("http://www.w3.org/2001/04/xmlenc#aes128-cbc") + encryptionMethod.setElementLocalName("EncryptionMethod") + 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) + + when: + genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) } + + then: + generatedXmlIsTheSameAsExpectedXml('/conf/2268-simple.xml', domBuilder.parseText(writer.toString())) + } + def 'test generating EntityAttributesFilter xml snippet with condition script'() { given: def filter = testObjectGenerator.entityAttributesFilterWithConditionScript() 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 bf17b107e..276bbc17f 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 @@ -17,6 +17,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilterTarget 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.frontend.FilterRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterTargetRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ClasspathMetadataResource @@ -183,6 +184,14 @@ class TestObjectGenerator { randomFilter } + static AlgorithmFilter algorithmFilter() { + return new AlgorithmFilter().with { + it.name = "Algorithm" + it.enabled = true; + it + } + } + SignatureValidationFilter signatureValidationFilter() { new SignatureValidationFilter().with { it.name = 'SignatureValidation' diff --git a/backend/src/test/resources/META-INF/services/org.opensaml.core.config.Initializer b/backend/src/test/resources/META-INF/services/org.opensaml.core.config.Initializer new file mode 100644 index 000000000..c7c2e7cb3 --- /dev/null +++ b/backend/src/test/resources/META-INF/services/org.opensaml.core.config.Initializer @@ -0,0 +1 @@ +edu.internet2.tier.shibboleth.admin.ui.opensaml.config.JPAXMLObjectProviderInitializerForTest \ No newline at end of file diff --git a/backend/src/test/resources/conf/2268-simple.xml b/backend/src/test/resources/conf/2268-simple.xml new file mode 100644 index 000000000..2ffe731f1 --- /dev/null +++ b/backend/src/test/resources/conf/2268-simple.xml @@ -0,0 +1,7 @@ + + + + https://broken.example.org/sp + https://also-broken.example.org/sp + + \ No newline at end of file diff --git a/backend/src/test/resources/jpa-saml2-metadata-config.xml b/backend/src/test/resources/jpa-saml2-metadata-config.xml new file mode 100644 index 000000000..b008809ce --- /dev/null +++ b/backend/src/test/resources/jpa-saml2-metadata-config.xml @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From fcd4ea1b59f701ccdbd86a3615c7760660eac41b Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 22 Jun 2022 10:54:47 -0700 Subject: [PATCH 02/20] Initial commit for Algorithm filter in UI --- .../schema/filter/algorithm.schema.json | 53 +++++++++++++++++ .../component/fields/FilterTargetField.js | 3 +- .../definition/AlgorithmFilterDefinition.js | 59 +++++++++++++++++++ ui/src/app/metadata/domain/filter/index.js | 7 ++- 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 ui/public/assets/schema/filter/algorithm.schema.json create mode 100644 ui/src/app/metadata/domain/filter/definition/AlgorithmFilterDefinition.js diff --git a/ui/public/assets/schema/filter/algorithm.schema.json b/ui/public/assets/schema/filter/algorithm.schema.json new file mode 100644 index 000000000..0c0c74444 --- /dev/null +++ b/ui/public/assets/schema/filter/algorithm.schema.json @@ -0,0 +1,53 @@ +{ + "type": "object", + "required": ["name"], + "properties": { + "name": { + "title": "label.filter-name", + "description": "tooltip.filter-name", + "type": "string" + }, + "filterEnabled": { + "title": "label.enable-filter", + "description": "tooltip.enable-filter", + "type": "boolean", + "default": false + }, + "algorithmFilterTarget": { + "title": "label.search-criteria", + "description": "tooltip.search-criteria", + "type": "object", + "properties": { + "algorithmFilterTargetType": { + "title": "label.filter-target-type", + "type": "string", + "default": "ENTITY", + "enum": ["ENTITY", "REGEX", "CONDITION_SCRIPT"], + "enumNames": [ + "value.entity-id", + "value.regex", + "value.script" + ] + }, + "value": { + "title": "label.filter-target-value", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "required": ["value", "algorithmFilterTargetType"] + }, + "@type": { + "type": "string", + "default": "NameIDFormat" + }, + "version": { + "type": "integer" + } + }, + "definitions": {} +} diff --git a/ui/src/app/form/component/fields/FilterTargetField.js b/ui/src/app/form/component/fields/FilterTargetField.js index 2ce8f3ccc..125b26b0d 100644 --- a/ui/src/app/form/component/fields/FilterTargetField.js +++ b/ui/src/app/form/component/fields/FilterTargetField.js @@ -251,7 +251,8 @@ const FilterTargetField = ({ diff --git a/ui/src/app/metadata/domain/filter/definition/AlgorithmFilterDefinition.js b/ui/src/app/metadata/domain/filter/definition/AlgorithmFilterDefinition.js new file mode 100644 index 000000000..e0c15bf80 --- /dev/null +++ b/ui/src/app/metadata/domain/filter/definition/AlgorithmFilterDefinition.js @@ -0,0 +1,59 @@ +import defaultsDeep from "lodash/defaultsDeep"; +// import API_BASE_PATH from "../../../../App.constant"; +import { BASE_PATH } from '../../../../App.constant'; +import { BaseFilterDefinition } from "./BaseFilterDefinition"; + +export const AlgorithmFilterWizard = { + ...BaseFilterDefinition, + uiSchema: defaultsDeep({ + algorithmFilterTarget: { + 'ui:field': 'FilterTargetField', + api: '' + }, + formats: { + "ui:options": { + orderable: false + }, + items: { + 'ui:widget': 'OptionWidget' + } + } + }, BaseFilterDefinition.uiSchema), + label: 'Algorithm', + type: 'Algorithm', + // schema: `${API_BASE_PATH}/ui/AlgorithmFilter`, + schema: `${BASE_PATH}assets/schema/filter/algorithm.schema.json`, + steps: [], + validator: (data = [], current = { resourceId: null }, group) => { + return BaseFilterDefinition.validator(data, current, group, 'algorithmFilterTarget', 'algorithmFilterTargetType') + }, + formatter: (changes) => ({ + ...changes, + '@type': AlgorithmFilterWizard.type + }) +}; + +export const AlgorithmFilterEditor = { + ...AlgorithmFilterWizard, + steps: [ + { + id: 'common', + label: 'label.target', + index: 1, + fields: [ + 'name', + '@type', + 'resourceId', + 'algorithmFilterTarget', + 'filterEnabled' + ] + }, + { + id: 'options', + label: 'label.options', + index: 2, + initialValues: [], + fields: [] + } + ] +}; \ No newline at end of file diff --git a/ui/src/app/metadata/domain/filter/index.js b/ui/src/app/metadata/domain/filter/index.js index 9f5326ba9..fe4af7fd1 100644 --- a/ui/src/app/metadata/domain/filter/index.js +++ b/ui/src/app/metadata/domain/filter/index.js @@ -1,14 +1,17 @@ import { EntityAttributesFilterEditor } from './definition/EntityAttributesFilterDefinition'; import { NameIDFilterEditor } from './definition/NameIdFilterDefinition'; +import { AlgorithmFilterEditor } from './definition/AlgorithmFilterDefinition'; export const MetadataFilterWizardTypes = { EntityAttributes: EntityAttributesFilterEditor, - NameIDFormat: NameIDFilterEditor + NameIDFormat: NameIDFilterEditor, + Algorithm: AlgorithmFilterEditor, }; export const MetadataFilterEditorTypes = [ EntityAttributesFilterEditor, - NameIDFilterEditor + NameIDFilterEditor, + AlgorithmFilterEditor, ]; export const MetadataFilterTypes = [ From c7cd06fa66dd829cf396d438f8ac12fcc0c0c7d4 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 12 Jul 2022 09:56:11 -0700 Subject: [PATCH 03/20] SHIBUI-2268 intermediate checkin - tests not correct --- .../JPAMetadataResolverServiceImpl.groovy | 24 +++++++++++++++---- .../admin/ui/domain/EncryptionMethod.java | 4 +++- ...XMLObjectProviderInitializerForTest.groovy | 2 +- ...JPAMetadataResolverServiceImplTests.groovy | 10 ++++++-- .../src/test/resources/conf/2268-simple.xml | 8 ++++++- 5 files changed, 39 insertions(+), 9 deletions(-) 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 691828526..ffe491eec 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 @@ -10,6 +10,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.Entity 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.FileBackedHttpMetadataResolver @@ -90,11 +91,26 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } void constructXmlNodeForFilter(AlgorithmFilter filter, def markupBuilderDelegate) { - if (!filter.isFilterEnabled()) { return } - markupBuilderDelegate.MetadataFilter('xsi:type': 'Algorithm') { - // TODO: enhance. currently this does weird things with namespaces + if (!filter.isFilterEnabled()) { + return + } + markupBuilderDelegate.MetadataFilter( + 'xsi:type': 'Algorithm', + 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd', + 'xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata', + 'xmlns': 'urn:mace:shibboleth:2.0:metadata', + 'xmlns:security': 'urn:mace:shibboleth:2.0:security', + 'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion' + ) { filter.unknownXMLObjects.each { xmlObject -> - mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(xmlObject, false)) + { + if (xmlObject instanceof Entity) { + Entity(xmlObject.getValue()) + } else { + mkp.yieldUnescaped(openSamlObjects.marshalToXmlString(xmlObject, false)) + } + } } } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java index 06a47da63..be8da1f0c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java @@ -55,4 +55,6 @@ public org.opensaml.xmlsec.encryption.OAEPparams getOAEPparams() { public void setOAEPparams(@Nullable org.opensaml.xmlsec.encryption.OAEPparams oaePparams) { this.oaePparams = oaePparams; } -} + + +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy index 0a56abe54..b4df893ab 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy @@ -6,7 +6,7 @@ class JPAXMLObjectProviderInitializerForTest extends AbstractXMLObjectProviderIn @Override protected String[] getConfigResources() { return new String[]{ - "/jpa-saml2-metadata-config.xml", + "/jpa-saml2-metadata-config.xml" } } } \ 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 010ee9310..80acbdad3 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.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.EncryptionMethod +import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethodBuilder 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 @@ -26,6 +27,7 @@ import groovy.xml.MarkupBuilder import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet import org.opensaml.core.criterion.EntityIdCriterion +import org.opensaml.saml.common.xml.SAMLConstants import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver @@ -143,10 +145,14 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { def 'test generating AlgorithmFilter xml snippet'() { given: def filter = TestObjectGenerator.algorithmFilter() - EncryptionMethod encryptionMethod = new EncryptionMethod() + 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") - encryptionMethod.setElementLocalName("EncryptionMethod") filter.addUnknownXMLObject(encryptionMethod) + Entity entity = new Entity() entity.setValue("https://broken.example.org/sp") filter.addUnknownXMLObject(entity) diff --git a/backend/src/test/resources/conf/2268-simple.xml b/backend/src/test/resources/conf/2268-simple.xml index 2ffe731f1..f9b0ea14a 100644 --- a/backend/src/test/resources/conf/2268-simple.xml +++ b/backend/src/test/resources/conf/2268-simple.xml @@ -1,4 +1,10 @@ - + https://broken.example.org/sp From 5abc51a4815c3e3afc2617cc21b1126511b8324d Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 22 Jul 2022 10:39:01 -0700 Subject: [PATCH 04/20] SHIBUI-2268 intermediate update (non-passing tests / working code) --- backend/build.gradle | 6 ++ .../JPAMetadataResolverServiceImpl.groovy | 6 +- .../ui/domain/AlgorithmDigestMethod.java | 29 ++++++++ .../admin/ui/domain/EncryptionMethod.java | 14 ++-- ...Method.java => SignatureDigestMethod.java} | 9 +-- .../AbstractAlgorithmIdentifierType.java | 20 ++++++ .../ui/domain/filters/algorithm/Entity.java | 13 +++- .../ui/domain/filters/algorithm/MGF.java | 24 +++++++ .../domain/filters/algorithm/OtherSource.java | 26 +++++++ .../ui/domain/filters/algorithm/PRF.java | 24 +++++++ .../JPAXMLObjectProviderInitializer.java | 3 +- .../jpa-saml2-metadata-algorithm-config.xml | 6 +- .../jpa-saml2-metadata-ds-config.xml | 23 +++++++ .../templates/SignatureBuilderTemplate.java | 22 ++++++ ...XMLObjectProviderInitializerForTest.groovy | 2 +- ...JPAMetadataResolverServiceImplTests.groovy | 69 ++++++++++++++++++- .../admin/ui/util/TestHelpers.groovy | 17 ++++- .../src/test/resources/conf/2268-complex.xml | 36 ++++++++++ .../src/test/resources/conf/2268-simple.xml | 30 +++++--- .../jpa-saml2-metadata-algorithm-config.xml | 34 +++++++++ .../jpa-saml2-metadata-ds-config.xml | 23 +++++++ 21 files changed, 407 insertions(+), 29 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AlgorithmDigestMethod.java rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/{DigestMethod.java => SignatureDigestMethod.java} (66%) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/MGF.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/OtherSource.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/PRF.java create mode 100644 backend/src/main/resources/jpa-saml2-metadata-ds-config.xml create mode 100644 backend/src/main/templates/SignatureBuilderTemplate.java create mode 100644 backend/src/test/resources/conf/2268-complex.xml create mode 100644 backend/src/test/resources/jpa-saml2-metadata-algorithm-config.xml create mode 100644 backend/src/test/resources/jpa-saml2-metadata-ds-config.xml diff --git a/backend/build.gradle b/backend/build.gradle index 71ab2c763..cfd16a65a 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -331,6 +331,12 @@ task generateSources { processLine(it['@className'].toString(), 'src/main/templates/AlgorithmBuilderTemplate.java') } } + + new XmlSlurper().parse(file('src/main/resources/jpa-saml2-metadata-ds-config.xml')).with { builders -> + builders.ObjectProviders.ObjectProvider.BuilderClass.each { + processLine(it['@className'].toString(), 'src/main/templates/SignatureBuilderTemplate.java') + } + } } } 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 a8108cbc1..7efc18e47 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 @@ -97,11 +97,13 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { markupBuilderDelegate.MetadataFilter( 'xsi:type': 'Algorithm', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - 'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd', + 'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:metadata:algsupport https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0.xsd http://www.w3.org/2000/09/xmldsig# https://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd http://www.w3.org/2009/xmlenc11# https://www.w3.org/TR/xmlenc-core1/xenc-schema-11.xsd', 'xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata', 'xmlns': 'urn:mace:shibboleth:2.0:metadata', 'xmlns:security': 'urn:mace:shibboleth:2.0:security', - 'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion' + 'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion', + 'xmlns:xenc11': 'http://www.w3.org/2009/xmlenc11#', + 'xmlns:alg': 'urn:oasis:names:tc:SAML:metadata:algsupport' ) { filter.unknownXMLObjects.each { xmlObject -> { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AlgorithmDigestMethod.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AlgorithmDigestMethod.java new file mode 100644 index 000000000..509f9613d --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AlgorithmDigestMethod.java @@ -0,0 +1,29 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain; + +import lombok.EqualsAndHashCode; + +import javax.annotation.Nullable; +import javax.persistence.Entity; + +@Entity(name = "DigestMethod") // for backwards compatibility instead of dealing with renaming the table +@EqualsAndHashCode(callSuper = true) +public class AlgorithmDigestMethod extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.ext.saml2alg.DigestMethod { + private String algorithm; + + public AlgorithmDigestMethod() {} + + public AlgorithmDigestMethod(String algorithm) { + this.algorithm = algorithm; + } + + @Nullable + @Override + public String getAlgorithm() { + return this.algorithm; + } + + @Override + public void setAlgorithm(@Nullable String value) { + this.algorithm = value; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java index be8da1f0c..16a122883 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java @@ -2,12 +2,14 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; +import org.opensaml.core.xml.XMLObject; import org.opensaml.xmlsec.encryption.KeySize; import org.opensaml.xmlsec.encryption.OAEPparams; import javax.annotation.Nullable; import javax.persistence.Embedded; import javax.persistence.Entity; +import java.util.List; @Entity @EqualsAndHashCode(callSuper = true) @@ -16,12 +18,9 @@ public class EncryptionMethod extends AbstractElementExtensibleXMLObject impleme private String algorithm; - @Embedded - private KeySize keySize; - - @Embedded - private OAEPparams oaePparams; + @Embedded private KeySize keySize; + @Embedded private OAEPparams oaePparams; @Nullable @Override @@ -56,5 +55,8 @@ public void setOAEPparams(@Nullable org.opensaml.xmlsec.encryption.OAEPparams oa this.oaePparams = oaePparams; } - + @Override + public List getOrderedChildren() { + return this.getUnknownXMLObjects(); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DigestMethod.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SignatureDigestMethod.java similarity index 66% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DigestMethod.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SignatureDigestMethod.java index 199947f88..519df1faf 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DigestMethod.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SignatureDigestMethod.java @@ -1,18 +1,19 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.opensaml.xmlsec.signature.DigestMethod; import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) -public class DigestMethod extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.ext.saml2alg.DigestMethod { +public class SignatureDigestMethod extends AbstractElementExtensibleXMLObject implements DigestMethod { private String algorithm; - public DigestMethod() {} + public SignatureDigestMethod() {} - public DigestMethod(String algorithm) { + public SignatureDigestMethod(String algorithm) { this.algorithm = algorithm; } @@ -26,4 +27,4 @@ public String getAlgorithm() { public void setAlgorithm(@Nullable String value) { this.algorithm = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java new file mode 100644 index 000000000..fcca2dd08 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java @@ -0,0 +1,20 @@ +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.persistence.Entity; + +@Entity +@Audited +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractAlgorithmIdentifierType extends AbstractXMLObject { + private String algorithm; +} \ 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 index 9a741f6e8..b15ec2ca1 100644 --- 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 @@ -1,13 +1,24 @@ 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) public class Entity extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { private String uri; - private Entity(){ + public Entity(){ setElementLocalName("Entity"); } 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/filters/algorithm/MGF.java new file mode 100644 index 000000000..f78eaaf00 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/MGF.java @@ -0,0 +1,24 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.envers.Audited; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; + +import javax.persistence.Entity; + +@Entity +@Audited +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +public class MGF extends AbstractAlgorithmIdentifierType { + public MGF() { + setElementLocalName("MGF"); + setNamespaceURI(EncryptionConstants.XMLENC11_NS); + setNamespacePrefix(EncryptionConstants.XMLENC11_PREFIX); + } +} \ No newline at end of file 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/filters/algorithm/OtherSource.java new file mode 100644 index 000000000..b57e0c82c --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/OtherSource.java @@ -0,0 +1,26 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.envers.Audited; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; + +import javax.persistence.Entity; + +@Entity +@Audited +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +public class OtherSource extends AbstractAlgorithmIdentifierType { + public OtherSource() { + { + setElementLocalName("OtherSource"); + setNamespaceURI(EncryptionConstants.XMLENC11_NS); + setNamespacePrefix(EncryptionConstants.XMLENC11_PREFIX); + } + } +} \ No newline at end of file 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/filters/algorithm/PRF.java new file mode 100644 index 000000000..3ee2dabec --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/PRF.java @@ -0,0 +1,24 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.envers.Audited; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; + +import javax.persistence.Entity; + +@Entity +@Audited +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +public class PRF extends AbstractAlgorithmIdentifierType { + public PRF() { + setElementLocalName("PRF"); + setNamespaceURI(EncryptionConstants.XMLENC11_NS); + setNamespacePrefix(EncryptionConstants.XMLENC11_PREFIX); + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java index 25000ae67..d1413b87f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java @@ -15,10 +15,11 @@ protected String[] getConfigResources() { "/jpa-saml2-metadata-ui-config.xml", "/jpa-signature-config.xml", "/jpa-saml2-metadata-algorithm-config.xml", + "/jpa-saml2-metadata-ds-config.xml", "/encryption-config.xml", "/jpa-saml2-metadata-reqinit-config.xml", "/saml2-protocol-config.xml", "/modified-saml2-assertion-config.xml" }; } -} +} \ No newline at end of file diff --git a/backend/src/main/resources/jpa-saml2-metadata-algorithm-config.xml b/backend/src/main/resources/jpa-saml2-metadata-algorithm-config.xml index f6432a71a..c37c788c1 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-algorithm-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-algorithm-config.xml @@ -6,13 +6,13 @@ - + - + @@ -31,4 +31,4 @@ - + \ No newline at end of file diff --git a/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml b/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml new file mode 100644 index 000000000..3a0eed8f0 --- /dev/null +++ b/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/src/main/templates/SignatureBuilderTemplate.java b/backend/src/main/templates/SignatureBuilderTemplate.java new file mode 100644 index 000000000..d8ba87cb1 --- /dev/null +++ b/backend/src/main/templates/SignatureBuilderTemplate.java @@ -0,0 +1,22 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain; + +import edu.internet2.tier.shibboleth.admin.ui.opensaml.xml.AbstractXMLObjectBuilder; +import org.opensaml.xmlsec.signature.support.SignatureConstants; + +public class {{TOKEN}}Builder extends AbstractXMLObjectBuilder<{{TOKEN}}> { + public {{TOKEN}}Builder() { + } + + public {{TOKEN}} buildObject() { + return buildObject(SignatureConstants.XMLSIG_NS, {{TOKEN}}.DEFAULT_ELEMENT_LOCAL_NAME, + SignatureConstants.XMLSIG_PREFIX); + } + + public {{TOKEN}} buildObject(final String namespaceURI, final String localName, final String namespacePrefix) { + {{TOKEN}} o = new {{TOKEN}}(); + o.setNamespaceURI(namespaceURI); + o.setElementLocalName(localName); + o.setNamespacePrefix(namespacePrefix); + return o; + } +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy index b4df893ab..4ac1ba2b1 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy @@ -6,7 +6,7 @@ class JPAXMLObjectProviderInitializerForTest extends AbstractXMLObjectProviderIn @Override protected String[] getConfigResources() { return new String[]{ - "/jpa-saml2-metadata-config.xml" + "/jpa-saml2-metadata-config.xml", "jpa-saml2-metadata-algorithm-config.xml", "jpa-saml2-metadata-ds-config.xml" } } } \ 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 d5d8c5a23..524a03f78 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 @@ -3,13 +3,16 @@ 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.EncryptionMethodBuilder +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.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.Entity +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.algorithm.MGF 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.LocalDynamicMetadataResolver @@ -31,6 +34,7 @@ import org.opensaml.saml.common.xml.SAMLConstants import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver +import org.opensaml.xmlsec.signature.support.SignatureConstants import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean @@ -167,6 +171,41 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { generatedXmlIsTheSameAsExpectedXml('/conf/2268-simple.xml', domBuilder.parseText(writer.toString())) } + 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) + 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) + + when: + genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForFilter(filter, it) } + + then: + generatedXmlIsTheSameAsExpectedXml('/conf/2268-complex.xml', domBuilder.parseText(writer.toString())) + } + def 'test generating EntityAttributesFilter xml snippet with condition script'() { given: def filter = testObjectGenerator.entityAttributesFilterWithConditionScript() @@ -489,6 +528,34 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { !DiffBuilder.compare(Input.fromStream(this.class.getResourceAsStream('/metadata/984-3-expected.xml'))).withTest(Input.fromString(openSamlObjects.marshalToXmlString(ed))).ignoreComments().ignoreWhitespace().build().hasDifferences() } + private EncryptionMethod getEncryptionMethod(String algorithm){ + 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(algorithm) + return encryptionMethod + } + + private AlgorithmDigestMethod getDigestMethod(String algorithm) { + AlgorithmDigestMethod dm = new AlgorithmDigestMethod() + dm.setNamespaceURI(SAMLConstants.SAML20ALG_NS) + dm.setElementLocalName(AlgorithmDigestMethod.DEFAULT_ELEMENT_LOCAL_NAME) + dm.setNamespacePrefix(SAMLConstants.SAML20ALG_PREFIX) + dm.setAlgorithm(algorithm) + return dm + } + + private SignatureDigestMethod getSignatureDigestMethod(String algorithm) { + SignatureDigestMethod dm = new SignatureDigestMethod() + dm.setNamespaceURI(SignatureConstants.XMLSIG_NS) + dm.setElementLocalName(SignatureDigestMethod.DEFAULT_ELEMENT_LOCAL_NAME) + dm.setNamespacePrefix(SignatureConstants.XMLSIG_PREFIX) + dm.setAlgorithm(algorithm) + return dm + } + static genXmlSnippet(MarkupBuilder xml, Closure xmlNodeGenerator) { xml.MetadataProvider('id': 'ShibbolethMetadata', 'xmlns': 'urn:mace:shibboleth:2.0:metadata', 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 f50263663..3a21080bb 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 @@ -3,6 +3,8 @@ package edu.internet2.tier.shibboleth.admin.ui.util import edu.internet2.tier.shibboleth.admin.ui.security.model.User import groovy.xml.XmlUtil import junit.framework.Assert +import org.w3c.dom.Node + import javax.xml.transform.Source; import javax.xml.transform.Transformer import javax.xml.transform.TransformerException @@ -50,6 +52,19 @@ class TestHelpers { Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences()); } + static void generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Node generatedXml) { + def Builder builder = Input.fromDocument(generatedXml) + def Source source = builder.build() + def myDiff = DiffBuilder.compare(Input.fromStream(TestHelpers.getResourceAsStream(expectedXmlResource))) + .withTest(builder) + .withAttributeFilter({attribute -> !attribute.name.equals("sourceDirectory")}) + .ignoreComments() + .ignoreWhitespace() + .build() + System.out.println("@@@ \n" + getString(source) + "\n") + Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences()); + } + public static String getString(DOMSource domSource) throws TransformerException { StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); @@ -67,4 +82,4 @@ class TestHelpers { def user = new User(username: username, role: rolename) Optional.of(user) } -} +} \ No newline at end of file diff --git a/backend/src/test/resources/conf/2268-complex.xml b/backend/src/test/resources/conf/2268-complex.xml new file mode 100644 index 000000000..cb4615a40 --- /dev/null +++ b/backend/src/test/resources/conf/2268-complex.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + https://sp2.example.org + + \ No newline at end of file diff --git a/backend/src/test/resources/conf/2268-simple.xml b/backend/src/test/resources/conf/2268-simple.xml index f9b0ea14a..e4365da17 100644 --- a/backend/src/test/resources/conf/2268-simple.xml +++ b/backend/src/test/resources/conf/2268-simple.xml @@ -1,12 +1,24 @@ - - - + + + + + https://broken.example.org/sp https://also-broken.example.org/sp diff --git a/backend/src/test/resources/jpa-saml2-metadata-algorithm-config.xml b/backend/src/test/resources/jpa-saml2-metadata-algorithm-config.xml new file mode 100644 index 000000000..c37c788c1 --- /dev/null +++ b/backend/src/test/resources/jpa-saml2-metadata-algorithm-config.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/src/test/resources/jpa-saml2-metadata-ds-config.xml b/backend/src/test/resources/jpa-saml2-metadata-ds-config.xml new file mode 100644 index 000000000..3a0eed8f0 --- /dev/null +++ b/backend/src/test/resources/jpa-saml2-metadata-ds-config.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 1111d68bae1367627eafdecd366c3a3ffcba7a91 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 5 Aug 2022 14:21:31 -0700 Subject: [PATCH 05/20] SHIBUI-2268 Adding xml config for marshalling/unmarshalling xml pieces --- .../main/resources/jpa-encryption-config.xml | 284 ++++++++++++++++ .../test/resources/jpa-encryption-config.xml | 284 ++++++++++++++++ .../test/resources/jpa-signature-config.xml | 313 ++++++++++++++++++ 3 files changed, 881 insertions(+) create mode 100644 backend/src/main/resources/jpa-encryption-config.xml create mode 100644 backend/src/test/resources/jpa-encryption-config.xml create mode 100644 backend/src/test/resources/jpa-signature-config.xml diff --git a/backend/src/main/resources/jpa-encryption-config.xml b/backend/src/main/resources/jpa-encryption-config.xml new file mode 100644 index 000000000..05adde279 --- /dev/null +++ b/backend/src/main/resources/jpa-encryption-config.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/src/test/resources/jpa-encryption-config.xml b/backend/src/test/resources/jpa-encryption-config.xml new file mode 100644 index 000000000..05adde279 --- /dev/null +++ b/backend/src/test/resources/jpa-encryption-config.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/src/test/resources/jpa-signature-config.xml b/backend/src/test/resources/jpa-signature-config.xml new file mode 100644 index 000000000..9a8da32e8 --- /dev/null +++ b/backend/src/test/resources/jpa-signature-config.xml @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 50bd2c7d074081f06cd13b3f94c06f1f38c043c1 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 5 Aug 2022 14:22:09 -0700 Subject: [PATCH 06/20] SHIBUI-2268 Fixing broken enhancements --- .../JPAMetadataResolverServiceImpl.groovy | 3 +- .../AbstractAlgorithmIdentifierType.java | 18 +++++++++- .../jpa-saml2-metadata-ds-config.xml | 23 ------------- ...XMLObjectProviderInitializerForTest.groovy | 2 +- ...JPAMetadataResolverServiceImplTests.groovy | 18 +++++++--- .../src/test/resources/conf/2268-complex.xml | 33 ++++++++----------- .../src/test/resources/conf/2268-simple.xml | 29 ++++++++-------- 7 files changed, 60 insertions(+), 66 deletions(-) delete mode 100644 backend/src/main/resources/jpa-saml2-metadata-ds-config.xml 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 66bfb65ca..6497608a0 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 @@ -104,7 +104,8 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { 'xmlns:security': 'urn:mace:shibboleth:2.0:security', 'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion', 'xmlns:xenc11': 'http://www.w3.org/2009/xmlenc11#', - 'xmlns:alg': 'urn:oasis:names:tc:SAML:metadata:algsupport' + 'xmlns:alg': 'urn:oasis:names:tc:SAML:metadata:algsupport', + 'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#' ) { filter.unknownXMLObjects.each { xmlObject -> { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java index fcca2dd08..99fdc3bfa 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/AbstractAlgorithmIdentifierType.java @@ -6,7 +6,10 @@ import lombok.Setter; import lombok.ToString; import org.hibernate.envers.Audited; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.xmlsec.encryption.AlgorithmIdentifierType; +import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @@ -15,6 +18,19 @@ @Setter @ToString @EqualsAndHashCode(callSuper = true) -public abstract class AbstractAlgorithmIdentifierType extends AbstractXMLObject { +public abstract class AbstractAlgorithmIdentifierType extends AbstractXMLObject implements AlgorithmIdentifierType { private String algorithm; + + @Nullable + @Override + public XMLObject getParameters() { + // implement? + return null; + } + + @Override + public void setParameters(@Nullable final XMLObject newParameters) { + // do nothing? + } + } \ No newline at end of file diff --git a/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml b/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml deleted file mode 100644 index 3a0eed8f0..000000000 --- a/backend/src/main/resources/jpa-saml2-metadata-ds-config.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy index 4ac1ba2b1..f84afdcc5 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializerForTest.groovy @@ -6,7 +6,7 @@ class JPAXMLObjectProviderInitializerForTest extends AbstractXMLObjectProviderIn @Override protected String[] getConfigResources() { return new String[]{ - "/jpa-saml2-metadata-config.xml", "jpa-saml2-metadata-algorithm-config.xml", "jpa-saml2-metadata-ds-config.xml" + "/jpa-saml2-metadata-config.xml", "jpa-saml2-metadata-algorithm-config.xml", "jpa-encryption-config.xml", "jpa-signature-config.xml" } } } \ 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 0ca8ca3a3..1bdf0f791 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,11 +4,18 @@ 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.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.resolvers.ClasspathMetadataResource import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver @@ -19,6 +26,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.SvnMetadataResour import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.TemplateScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.opensaml.config.JPAXMLObjectProviderInitializerForTest import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.util.AttributeUtility @@ -48,7 +56,6 @@ import java.time.Instant import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml -@ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration ]) @ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration, JPAXMLObjectProviderInitializerForTest ]) class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { @@ -217,9 +224,12 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { 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) + 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) diff --git a/backend/src/test/resources/conf/2268-complex.xml b/backend/src/test/resources/conf/2268-complex.xml index cb4615a40..ee76b2f84 100644 --- a/backend/src/test/resources/conf/2268-complex.xml +++ b/backend/src/test/resources/conf/2268-complex.xml @@ -1,36 +1,29 @@ - - + + - + - https://sp2.example.org + 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-simple.xml index e4365da17..daf8c5fac 100644 --- a/backend/src/test/resources/conf/2268-simple.xml +++ b/backend/src/test/resources/conf/2268-simple.xml @@ -1,25 +1,22 @@ - - + https://broken.example.org/sp https://also-broken.example.org/sp + \ No newline at end of file From ccc61fff1e667ee0b0ec0a8826677111cbdac67a Mon Sep 17 00:00:00 2001 From: chasegawa Date: Mon, 8 Aug 2022 13:23:58 -0700 Subject: [PATCH 07/20] SHIBUI-2268 Adding remaining needed pieces for Algorithm filter --- backend/build.gradle | 2 +- .../JPAMetadataResolverServiceImpl.groovy | 17 +++++++-- .../filters/algorithm/ConditionRef.java | 38 +++++++++++++++++++ .../filters/algorithm/ConditionScript.java | 38 +++++++++++++++++++ .../ui/domain/filters/algorithm/Entity.java | 3 ++ .../JPAXMLObjectProviderInitializer.java | 13 +++---- ...JPAMetadataResolverServiceImplTests.groovy | 36 ++++++++++++++++++ .../src/test/resources/conf/2268-actual.xml | 29 ++++++++++++++ 8 files changed, 164 insertions(+), 12 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java create mode 100644 backend/src/test/resources/conf/2268-actual.xml diff --git a/backend/build.gradle b/backend/build.gradle index cfd16a65a..83d2c8dd8 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -332,7 +332,7 @@ task generateSources { } } - new XmlSlurper().parse(file('src/main/resources/jpa-saml2-metadata-ds-config.xml')).with { builders -> + new XmlSlurper().parse(file('src/main/resources/jpa-signature-config.xml')).with { builders -> builders.ObjectProviders.ObjectProvider.BuilderClass.each { processLine(it['@className'].toString(), 'src/main/templates/SignatureBuilderTemplate.java') } 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 6497608a0..78ca12254 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 @@ -10,6 +10,8 @@ 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.opensaml.OpenSamlNameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver @@ -111,6 +113,15 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { { 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)) } @@ -133,10 +144,8 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { Entity(it) } break - case EntityAttributesFilterTarget - .EntityAttributesFilterTargetType.CONDITION_SCRIPT: - case EntityAttributesFilterTarget - .EntityAttributesFilterTargetType.REGEX: + case EntityAttributesFilterTarget.EntityAttributesFilterTargetType.CONDITION_SCRIPT: + case EntityAttributesFilterTarget.EntityAttributesFilterTargetType.REGEX: ConditionScript() { Script() { def script 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 new file mode 100644 index 000000000..b35cd0762 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionRef.java @@ -0,0 +1,38 @@ +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 new file mode 100644 index 000000000..a2d58382a --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/algorithm/ConditionScript.java @@ -0,0 +1,38 @@ +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 index b15ec2ca1..18dfcbe8e 100644 --- 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 @@ -15,6 +15,9 @@ @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; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java index d1413b87f..24757d560 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/opensaml/config/JPAXMLObjectProviderInitializer.java @@ -8,16 +8,15 @@ public class JPAXMLObjectProviderInitializer extends AbstractXMLObjectProviderIn protected String[] getConfigResources() { return new String[]{ "/jpa-default-config.xml", - "/jpa-saml2-metadata-config.xml", - "/jpa-saml2-metadata-attr-config.xml", + "/encryption-config.xml", "/jpa-saml2-assertion-config.xml", - "/jpa-schema-config.xml", - "/jpa-saml2-metadata-ui-config.xml", - "/jpa-signature-config.xml", "/jpa-saml2-metadata-algorithm-config.xml", - "/jpa-saml2-metadata-ds-config.xml", - "/encryption-config.xml", + "/jpa-saml2-metadata-attr-config.xml", + "/jpa-saml2-metadata-config.xml", "/jpa-saml2-metadata-reqinit-config.xml", + "/jpa-saml2-metadata-ui-config.xml", + "/jpa-schema-config.xml", + "/jpa-signature-config.xml", "/saml2-protocol-config.xml", "/modified-saml2-assertion-config.xml" }; 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 1bdf0f791..505d1507a 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 @@ -13,6 +13,8 @@ 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.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 @@ -217,6 +219,40 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { generatedXmlIsTheSameAsExpectedXml('/conf/2268-simple.xml', domBuilder.parseText(writer.toString())) } + def 'test generating AlgorithmFilter shibui-2268 actual'() { + 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) + + 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() diff --git a/backend/src/test/resources/conf/2268-actual.xml b/backend/src/test/resources/conf/2268-actual.xml new file mode 100644 index 000000000..961079197 --- /dev/null +++ b/backend/src/test/resources/conf/2268-actual.xml @@ -0,0 +1,29 @@ + + + + + + https://broken.example.org/sp + shibboleth.Conditions.TRUE + + + + + + \ No newline at end of file From ae97066d48525ec71392ca9b8df0e2b1a4f881ca Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 9 Aug 2022 13:55:06 -0700 Subject: [PATCH 08/20] 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