From 9827498670843cac2d0b3d86626afaca028bb49e Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 21 Jun 2022 11:03:53 -0700 Subject: [PATCH 01/57] 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/57] 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 3c4526ca2bc0d6b5bd92d93c8ef585854525b353 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 6 Jul 2022 13:13:28 -0700 Subject: [PATCH 03/57] Fixed access to non-admin pages --- ui/src/app/App.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/ui/src/app/App.js b/ui/src/app/App.js index 20331e4e8..546241f10 100644 --- a/ui/src/app/App.js +++ b/ui/src/app/App.js @@ -33,6 +33,7 @@ import { SessionModal } from './core/user/SessionModal'; import { Roles } from './admin/Roles'; import { Groups } from './admin/Groups'; import { BASE_PATH } from './App.constant'; +import { ProtectRoute } from './core/components/ProtectRoute'; function App() { @@ -81,12 +82,32 @@ function App() { - - - + + + + + } /> + + + + + } /> + + + + + } /> - - + + + + + } /> + + + + + } /> From 4cf79c36cb66029d4d88ada3264f868ef657d7fc Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 7 Jul 2022 08:29:04 -0700 Subject: [PATCH 04/57] Fixed cosmetic issues --- .../main/resources/i18n/messages.properties | 1 + ui/public/unsecured/error.html | 21 +++++++++++++----- ui/public/unsecured/favicon-96x96.png | Bin 0 -> 12383 bytes ui/public/unsecured/favicon.ico | Bin 0 -> 1150 bytes .../shibboleth_icon_color_130x130.png | Bin 0 -> 11665 bytes ui/src/app/metadata/new/NewProvider.js | 4 ++-- .../wizard/MetadataFilterTypeSelector.js | 8 +++---- .../wizard/MetadataProviderTypeSelector.js | 12 ++++++---- 8 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 ui/public/unsecured/favicon-96x96.png create mode 100644 ui/public/unsecured/favicon.ico create mode 100644 ui/public/unsecured/shibboleth_icon_color_130x130.png diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index e25a7e5b9..88aea4835 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -409,6 +409,7 @@ label.remove-roleless-entity-descriptors=Remove Roleless Entity Descriptors? label.remove-empty-entities-descriptors=Remove Empty Entities Descriptors? label.select-metadata-provider-type=Select Metadata Provider Type +label.select-metadata-filter-type=Select Metadata Filter Type label.filter-list=Filter List label.common-attributes=Common Attributes label.reloading-attributes=Reloading Attributes diff --git a/ui/public/unsecured/error.html b/ui/public/unsecured/error.html index 4d200efa8..910a81b61 100644 --- a/ui/public/unsecured/error.html +++ b/ui/public/unsecured/error.html @@ -4,20 +4,31 @@ Shibboleth Metadata Management - - + +
-
- +
+
+ + + +
User request received

Your request has been received and is being reviewed. You will be notified with access status.

diff --git a/ui/public/unsecured/favicon-96x96.png b/ui/public/unsecured/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..e19516fff44f2ee7d0a432dc542424d98bf30aac GIT binary patch literal 12383 zcmZ{~1yEc~&^EfbyGw9)*97pQ8xYMu%gX@X|N9j6R;EJlptvaLxj}1%|0!}{2QdJEeL+!1Qrr92MZTB6 z(NcO`=x2U|%2 znb^E5-mww=a?`aP$Uk}dYJBp?ZRYn?A}f*7@6Vx@!+tG+{iXG8k9u4B4h_AYol?x@ zPimdO5~EARmv@eLlx?2LBMJ#V(u3pq($@BNlgo-1quWlTxrK!xJhhL5hts)DY-g^5 zN6s0upMtx(L?$K$@BXYioSd9=ZcIPt9=Ksp5ypPoAIEv=y&xAimUML7JaAgrVhe+% z!i~m`mqY5k+1%VbUu%g)KtmlL*FN9s51JcFN=vDzU=R@zAs(L!7=Te=X6EEPs;(?B z|M%wuA0Hofw9H$*pKPfHYzUx9_Z%QDb}5w6tM3v=O{+hsv6ono)A4z+d+qJ|v%} zNDHSf9mTpt){`|CHaFvEk1USoifw;YwlqDR0e73mC`#+=6S^8 zTwQtUzYFj*&o-OwQFL{)_x#p2RK+rOrooI1lc16iB8N`l@87?TY+>q5!Db_k>p!2u zSiML<@}Z|FiJkSEFPsi*as`U-B%KggTXuV@|3UI z0O&OIdVTrTKHjh

K)c3A>F?OpvMvV8kHdrLG60h|X6)*2y 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 CAw)L- literal 0 HcmV?d00001 diff --git a/ui/public/unsecured/shibboleth_icon_color_130x130.png b/ui/public/unsecured/shibboleth_icon_color_130x130.png new file mode 100644 index 0000000000000000000000000000000000000000..313df313ec23714f1b1724665d7b731864523f1b GIT binary patch literal 11665 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 be*p#nPjC|=r4$7j00000NkvXXu0mjfIC%Fk literal 0 HcmV?d00001 diff --git a/ui/src/app/metadata/new/NewProvider.js b/ui/src/app/metadata/new/NewProvider.js index 43a9ed715..13d0d1061 100644 --- a/ui/src/app/metadata/new/NewProvider.js +++ b/ui/src/app/metadata/new/NewProvider.js @@ -7,7 +7,7 @@ import { MetadataProviderTypeSelector } from '../wizard/MetadataProviderTypeSele export function NewProvider() { - const { data } = useMetadataProviderTypes({}, []); + const { data, loading } = useMetadataProviderTypes({}, []); return (

- + {(data, onRestart) => - - + + - + {types.map(t => )} diff --git a/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js b/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js index fbc890fb9..e53f06b13 100644 --- a/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js +++ b/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js @@ -1,5 +1,5 @@ import React from 'react'; -import { faArrowCircleRight, faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { faArrowCircleRight, faAsterisk, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useForm } from 'react-hook-form'; @@ -10,11 +10,11 @@ import { InfoIcon } from '../../form/component/InfoIcon'; import { useTranslator } from '../../i18n/hooks'; import { useMetadataProviders } from '../hooks/api'; -export function MetadataProviderTypeSelector({ type, types = [], children}) { +export function MetadataProviderTypeSelector({ type, types = [], loading, children}) { const translator = useTranslator(); - const { data = [], loading } = useMetadataProviders({cachePolicy: 'no-cache'}, []); + const { data = [] } = useMetadataProviders({cachePolicy: 'no-cache'}, []); const [showSelector, setShowSelector] = React.useState(true); @@ -81,7 +81,10 @@ export function MetadataProviderTypeSelector({ type, types = [], children}) {
- + + + + + {loading && } From 0cd83bcd3acac8031ccf952ba6abdd5e528c26ea Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 7 Jul 2022 10:39:32 -0700 Subject: [PATCH 05/57] Fixed caching of source xml --- ui/src/app/metadata/hoc/MetadataXmlLoader.js | 10 +++++++--- ui/src/app/metadata/view/MetadataXml.js | 7 ++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ui/src/app/metadata/hoc/MetadataXmlLoader.js b/ui/src/app/metadata/hoc/MetadataXmlLoader.js index ffc1c8bcf..e5453a519 100644 --- a/ui/src/app/metadata/hoc/MetadataXmlLoader.js +++ b/ui/src/app/metadata/hoc/MetadataXmlLoader.js @@ -13,7 +13,7 @@ export function MetadataXmlLoader({ children }) { const [xml, setXml] = React.useState(); async function loadMetadataXml(id) { - const data = await get(`/${id}`) + const data = await get(`/${id}`); if (response.ok) { setXml(data); } @@ -22,12 +22,16 @@ export function MetadataXmlLoader({ children }) { /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { if (type === 'source') { - loadMetadataXml(id) + reload() } }, [id]); + function reload() { + loadMetadataXml(id); + } + return ( - + {children} ); diff --git a/ui/src/app/metadata/view/MetadataXml.js b/ui/src/app/metadata/view/MetadataXml.js index 5144b14af..17e79d26a 100644 --- a/ui/src/app/metadata/view/MetadataXml.js +++ b/ui/src/app/metadata/view/MetadataXml.js @@ -12,12 +12,17 @@ import { MetadataViewToggle } from '../component/MetadataViewToggle'; import { downloadAsXml } from '../../core/utility/download_as_xml'; export function MetadataXml () { - const xml = React.useContext(MetadataXmlContext); + const { xml, reload } = React.useContext(MetadataXmlContext); const entity = React.useContext(MetadataObjectContext); const { type } = useParams(); const download = () => downloadAsXml(entity.name ? entity.name : entity.serviceProviderName, xml); + /*eslint-disable react-hooks/exhaustive-deps*/ + React.useEffect(() => { + reload(); + }, []); + return ( <>

From 7684867a3cf49cf7fb473a504e02eed8f280b9a8 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 7 Jul 2022 12:27:36 -0700 Subject: [PATCH 06/57] Added success alert for custom entity attributes --- ui/public/assets/schema/attribute/attribute.schema.json | 2 +- ui/src/app/metadata/new/NewAttribute.js | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ui/public/assets/schema/attribute/attribute.schema.json b/ui/public/assets/schema/attribute/attribute.schema.json index 0514703f0..84590e08e 100644 --- a/ui/public/assets/schema/attribute/attribute.schema.json +++ b/ui/public/assets/schema/attribute/attribute.schema.json @@ -64,7 +64,7 @@ "title": "label.entity-attribute-help", "description": "tooltip.entity-attribute-help", "type": "string", - "minLength": 1, + "minLength": 0, "maxLength": 255 } }, diff --git a/ui/src/app/metadata/new/NewAttribute.js b/ui/src/app/metadata/new/NewAttribute.js index 3648942bb..0db6847cb 100644 --- a/ui/src/app/metadata/new/NewAttribute.js +++ b/ui/src/app/metadata/new/NewAttribute.js @@ -11,7 +11,7 @@ import { useMetadataAttribute } from '../hooks/api'; import {CustomAttributeDefinition} from '../domain/attribute/CustomAttributeDefinition'; import MetadataSchema from '../hoc/MetadataSchema'; import { MetadataForm } from '../hoc/MetadataFormContext'; -import { createNotificationAction, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; export function NewAttribute() { const history = useHistory(); @@ -25,11 +25,16 @@ export function NewAttribute() { const [blocking, setBlocking] = React.useState(false); async function save(metadata) { + let toast; const resp = await post(``, definition.parser(metadata)); if (response.ok) { + toast = createNotificationAction(`Added attribute successfully.`, NotificationTypes.SUCCESS); gotoDetail({ refresh: true }); } else { - dispatch(createNotificationAction(`${resp.errorCode}: Unable to create attribute ... ${resp.errorMessage}`, 'danger', 5000)); + toast = createNotificationAction(`${resp.errorCode}: Unable to create attribute ... ${resp.errorMessage}`, 'danger', 5000); + } + if (toast) { + dispatch(toast); } }; From be660ed0c48a542fe61796f8f5e2704f5ea84fee Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 7 Jul 2022 12:34:44 -0700 Subject: [PATCH 07/57] Added success notifcation for editing/deleting attributes --- ui/src/app/metadata/hoc/MetadataAttributes.js | 4 ++++ ui/src/app/metadata/view/MetadataAttributeEdit.js | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ui/src/app/metadata/hoc/MetadataAttributes.js b/ui/src/app/metadata/hoc/MetadataAttributes.js index c4c59d3c0..e4cf57a2d 100644 --- a/ui/src/app/metadata/hoc/MetadataAttributes.js +++ b/ui/src/app/metadata/hoc/MetadataAttributes.js @@ -1,8 +1,11 @@ import React from 'react'; +import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { useMetadataAttribute, useMetadataAttributes } from '../hooks/api'; export function MetadataAttributes ({children}) { + const dispatch = useNotificationDispatcher(); + const { get, response } = useMetadataAttributes({ cachePolicy: 'no-cache' }); @@ -24,6 +27,7 @@ export function MetadataAttributes ({children}) { await del(`/${id}`); if (attrApi.response.ok) { loadAttributes(); + dispatch(createNotificationAction(`Attribute deleted successfully`, NotificationTypes.SUCCESS, 5000)); } } diff --git a/ui/src/app/metadata/view/MetadataAttributeEdit.js b/ui/src/app/metadata/view/MetadataAttributeEdit.js index b45dfeaa5..84670d467 100644 --- a/ui/src/app/metadata/view/MetadataAttributeEdit.js +++ b/ui/src/app/metadata/view/MetadataAttributeEdit.js @@ -11,7 +11,7 @@ import { useMetadataAttribute } from '../hooks/api'; import { CustomAttributeDefinition, CustomAttributeEditor } from '../domain/attribute/CustomAttributeDefinition'; import MetadataSchema from '../hoc/MetadataSchema'; import { MetadataForm } from '../hoc/MetadataFormContext'; -import { createNotificationAction, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; export function MetadataAttributeEdit() { const { id } = useParams(); @@ -35,11 +35,16 @@ export function MetadataAttributeEdit() { } async function save(metadata) { + let toast; const resp = await put(``, definition.parser(metadata)); if (response.ok) { + toast = createNotificationAction(`Updated attribute successfully.`, NotificationTypes.SUCCESS); gotoDetail({ refresh: true }); } else { - dispatch(createNotificationAction(`${resp.errorCode}: Unable to edit attribute ... ${resp.errorMessage}`, 'danger', 5000)); + toast = createNotificationAction(`${resp.errorCode}: Unable to edit attribute ... ${resp.errorMessage}`, 'danger', 5000); + } + if (toast) { + dispatch(toast); } }; From c7cd06fa66dd829cf396d438f8ac12fcc0c0c7d4 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 12 Jul 2022 09:56:11 -0700 Subject: [PATCH 08/57] 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 b6ba7ef2a91adcc506429187503489fb90eaec2d Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 13 Jul 2022 15:19:10 -0700 Subject: [PATCH 09/57] SHIBUI-944 Base copy off of JSON Schema --- ui/src/app/metadata/copy/CopySource.js | 17 +++------- .../source/definition/SourceDefinition.js | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/ui/src/app/metadata/copy/CopySource.js b/ui/src/app/metadata/copy/CopySource.js index 83a8591e8..f3ae6b142 100644 --- a/ui/src/app/metadata/copy/CopySource.js +++ b/ui/src/app/metadata/copy/CopySource.js @@ -9,18 +9,9 @@ import { Translate } from '../../i18n/components/translate'; import { EntityTypeahead } from './EntityTypeahead'; import kebabCase from 'lodash/kebabCase'; import { useMetadataSources } from '../hooks/api'; +import { useMetadataSourceSections } from '../domain/source/definition/SourceDefinition'; + -const sections = [ - { i18nKey: 'organizationInformation', property: 'organization' }, - { i18nKey: 'contacts', property: 'contacts' }, - { i18nKey: 'uiMduiInfo', property: 'mdui' }, - { i18nKey: 'spSsoDescriptorInfo', property: 'serviceProviderSsoDescriptor' }, - { i18nKey: 'logoutEndpoints', property: 'logoutEndpoints' }, - { i18nKey: 'securityDescriptorInfo', property: 'securityInfo' }, - { i18nKey: 'assertionConsumerServices', property: 'assertionConsumerServices' }, - { i18nKey: 'relyingPartyOverrides', property: 'relyingPartyOverrides' }, - { i18nKey: 'attributeRelease', property: 'attributeRelease' } -]; export function CopySource({ copy, onNext }) { @@ -64,6 +55,8 @@ export function CopySource({ copy, onNext }) { const sourceIds = data.map(p => p.entityId); + const sections = useMetadataSourceSections(); + return ( <>
@@ -162,7 +155,7 @@ export function CopySource({ copy, onNext }) { onSelect(item, checked)} diff --git a/ui/src/app/metadata/domain/source/definition/SourceDefinition.js b/ui/src/app/metadata/domain/source/definition/SourceDefinition.js index a448d2d03..41d409907 100644 --- a/ui/src/app/metadata/domain/source/definition/SourceDefinition.js +++ b/ui/src/app/metadata/domain/source/definition/SourceDefinition.js @@ -6,6 +6,7 @@ import API_BASE_PATH from '../../../../App.constant'; import {removeNull} from '../../../../core/utility/remove_null'; import { detailedDiff } from 'deep-object-diff'; import isNil from 'lodash/isNil'; +import { useMetadataSchemaContext } from '../../../hoc/MetadataSchema'; export const SourceBase = { label: 'Metadata Source', @@ -534,4 +535,35 @@ export const SourceWizard = { fields: [] } ] +} + +export const sections = [ + { i18nKey: 'organizationInformation', property: 'organization' }, + { i18nKey: 'contacts', property: 'contacts' }, + { i18nKey: 'uiMduiInfo', property: 'mdui' }, + { i18nKey: 'spSsoDescriptorInfo', property: 'serviceProviderSsoDescriptor' }, + { i18nKey: 'logoutEndpoints', property: 'logoutEndpoints' }, + { i18nKey: 'securityDescriptorInfo', property: 'securityInfo' }, + { i18nKey: 'assertionConsumerServices', property: 'assertionConsumerServices' }, + { i18nKey: 'relyingPartyOverrides', property: 'relyingPartyOverrides' }, + { i18nKey: 'attributeRelease', property: 'attributeRelease' } +]; + +export function useMetadataSourceSections() { + const schema = useMetadataSchemaContext(); + + const keys = Object.keys(schema.properties); + const properties = sections.map((s) => s.property); + + const reduced = keys.reduce( + (collection, key) => { + if (properties.indexOf(key) > -1) { + collection.push(sections.find(s => s.property === key)); + } + return collection; + }, + [] + ); + + return reduced; } \ No newline at end of file From 4388dfa2a01054fb5be51f16dd5f70af970d3a5e Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 15 Jul 2022 09:48:16 -0700 Subject: [PATCH 10/57] Added spinner to dashboard pages --- ui/src/app/core/components/Spinner.js | 9 +++++++++ ui/src/app/dashboard/view/ActionsTab.js | 11 ++++++++--- ui/src/app/dashboard/view/AdminTab.js | 5 ++++- ui/src/app/dashboard/view/Dashboard.js | 14 ++++++++++---- ui/src/app/dashboard/view/ProvidersTab.js | 7 +++++-- ui/src/app/dashboard/view/SourcesTab.js | 8 ++++++-- .../domain/provider/component/ProviderList.js | 3 ++- .../metadata/domain/source/component/SourceList.js | 3 ++- 8 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 ui/src/app/core/components/Spinner.js diff --git a/ui/src/app/core/components/Spinner.js b/ui/src/app/core/components/Spinner.js new file mode 100644 index 000000000..880f53d2a --- /dev/null +++ b/ui/src/app/core/components/Spinner.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; + +export function Spinner ({ size, className }) { + return () +} + +export default Spinner; \ No newline at end of file diff --git a/ui/src/app/dashboard/view/ActionsTab.js b/ui/src/app/dashboard/view/ActionsTab.js index 30bc9e371..eda40b751 100644 --- a/ui/src/app/dashboard/view/ActionsTab.js +++ b/ui/src/app/dashboard/view/ActionsTab.js @@ -1,11 +1,12 @@ import React from 'react'; import { MetadataActions } from '../../admin/container/MetadataActions'; import UserActions from '../../admin/container/UserActions'; +import Spinner from '../../core/components/Spinner'; import Translate from '../../i18n/components/translate'; import SourceList from '../../metadata/domain/source/component/SourceList'; -export function ActionsTab({ sources, users, reloadSources, reloadUsers }) { +export function ActionsTab({ sources, users, reloadSources, reloadUsers, loadingSources, loadingUsers }) { return ( <> @@ -21,7 +22,9 @@ export function ActionsTab({ sources, users, reloadSources, reloadUsers }) {
{(enable) => - enable(s, e, reloadSources)} /> + enable(s, e, reloadSources)}> + {loadingSources &&
} +
}
@@ -36,7 +39,9 @@ export function ActionsTab({ sources, users, reloadSources, reloadUsers }) {

- + + {loadingUsers &&
} +
diff --git a/ui/src/app/dashboard/view/AdminTab.js b/ui/src/app/dashboard/view/AdminTab.js index 5c116c242..ba71e0685 100644 --- a/ui/src/app/dashboard/view/AdminTab.js +++ b/ui/src/app/dashboard/view/AdminTab.js @@ -5,12 +5,13 @@ import UserMaintenance from '../../admin/component/UserMaintenance'; import API_BASE_PATH from '../../App.constant'; import Translate from '../../i18n/components/translate'; +import Spinner from '../../core/components/Spinner'; export function AdminTab () { const [users, setUsers] = React.useState([]); - const { get, response } = useFetch(`${API_BASE_PATH}/admin/users`, { + const { get, response, loading } = useFetch(`${API_BASE_PATH}/admin/users`, { cachePolicy: 'no-cache' }, []); @@ -46,7 +47,9 @@ export function AdminTab () { onChangeUserRole={onChangeUserRole} onDeleteUser={onDeleteUser} onChangeUserGroup={onChangeUserGroup} />} + + {loading &&
}
diff --git a/ui/src/app/dashboard/view/Dashboard.js b/ui/src/app/dashboard/view/Dashboard.js index e5f145572..49cba4079 100644 --- a/ui/src/app/dashboard/view/Dashboard.js +++ b/ui/src/app/dashboard/view/Dashboard.js @@ -26,13 +26,13 @@ export function Dashboard () { const isAdmin = useIsAdmin(); - const loading = useCurrentUserLoading(); + const loadingUser = useCurrentUserLoading(); const [actions, setActions] = React.useState(0); const [users, setUsers] = React.useState([]); const [sources, setSources] = React.useState([]); - const { get, response } = useFetch(`${API_BASE_PATH}`, { + const { get, response, loading } = useFetch(`${API_BASE_PATH}`, { cachePolicy: 'no-cache' }); @@ -64,7 +64,7 @@ export function Dashboard () { return (
- {loading ? + {loadingUser ?
@@ -109,7 +109,13 @@ export function Dashboard () { } /> - + } /> diff --git a/ui/src/app/dashboard/view/ProvidersTab.js b/ui/src/app/dashboard/view/ProvidersTab.js index 023a7f78a..d986f3f68 100644 --- a/ui/src/app/dashboard/view/ProvidersTab.js +++ b/ui/src/app/dashboard/view/ProvidersTab.js @@ -8,13 +8,14 @@ import { Ordered } from '../component/Ordered'; import { useIsAdmin } from '../../core/user/UserContext'; import Alert from 'react-bootstrap/Alert'; import { MetadataActions } from '../../admin/container/MetadataActions'; +import Spinner from '../../core/components/Spinner'; const searchProps = ['name', '@type', 'createdBy']; export function ProvidersTab () { const [providers, setProviders] = React.useState([]); - const { get, response } = useMetadataEntities('provider', { + const { get, response, loading } = useMetadataEntities('provider', { cachePolicy: 'no-cache' }); @@ -54,7 +55,9 @@ export function ProvidersTab () { last={last} onEnable={(p, e) => enable(p, e, loadProviders)} onOrderUp={onOrderUp} - onOrderDown={onOrderDown}> + onOrderDown={onOrderDown}> + {loading &&
} + } } diff --git a/ui/src/app/dashboard/view/SourcesTab.js b/ui/src/app/dashboard/view/SourcesTab.js index b564a3872..40ff4dd4f 100644 --- a/ui/src/app/dashboard/view/SourcesTab.js +++ b/ui/src/app/dashboard/view/SourcesTab.js @@ -5,9 +5,11 @@ import Translate from '../../i18n/components/translate'; import SourceList from '../../metadata/domain/source/component/SourceList'; import { useMetadataEntities, useMetadataEntity } from '../../metadata/hooks/api'; import { Search } from '../component/Search'; +import { Spinner } from '../../core/components/Spinner'; import { NotificationContext, createNotificationAction, NotificationTypes } from '../../notifications/hoc/Notifications'; + const searchProps = ['serviceProviderName', 'entityId', 'createdBy']; export function SourcesTab () { @@ -16,7 +18,7 @@ export function SourcesTab () { const [sources, setSources] = React.useState([]); - const { get, response } = useMetadataEntities('source', { + const { get, response, loading } = useMetadataEntities('source', { cachePolicy: 'no-cache' }); @@ -68,7 +70,9 @@ export function SourcesTab () { entities={searched} onDelete={(id) => remove(id, loadSources)} onEnable={(s, e) => enable(s, e, loadSources) } - onChangeGroup={changeSourceGroup} /> + onChangeGroup={changeSourceGroup}> + {loading &&
} + } } diff --git a/ui/src/app/metadata/domain/provider/component/ProviderList.js b/ui/src/app/metadata/domain/provider/component/ProviderList.js index 3e559eb2a..1b367a69d 100644 --- a/ui/src/app/metadata/domain/provider/component/ProviderList.js +++ b/ui/src/app/metadata/domain/provider/component/ProviderList.js @@ -12,7 +12,7 @@ import { Scroller } from '../../../../dashboard/component/Scroller'; import { useIsAdmin } from '../../../../core/user/UserContext'; import { useTranslator } from '../../../../i18n/hooks'; -export function ProviderList({ entities, reorder = true, first, last, onEnable, onOrderUp, onOrderDown }) { +export function ProviderList({ children, entities, reorder = true, first, last, onEnable, onOrderUp, onOrderDown }) { const isAdmin = useIsAdmin(); const translator = useTranslator(); @@ -91,6 +91,7 @@ export function ProviderList({ entities, reorder = true, first, last, onEnable, )} + {children}
} diff --git a/ui/src/app/metadata/domain/source/component/SourceList.js b/ui/src/app/metadata/domain/source/component/SourceList.js index 109396c2c..42af027dd 100644 --- a/ui/src/app/metadata/domain/source/component/SourceList.js +++ b/ui/src/app/metadata/domain/source/component/SourceList.js @@ -16,7 +16,7 @@ import { useTranslator } from '../../../../i18n/hooks'; import { useCanEnable, useIsAdmin } from '../../../../core/user/UserContext'; import { GroupsProvider } from '../../../../admin/hoc/GroupsProvider'; -export default function SourceList({ entities, onDelete, onEnable, onChangeGroup }) { +export default function SourceList({ entities, onDelete, onEnable, onChangeGroup, children }) { const translator = useTranslator(); const isAdmin = useIsAdmin(); @@ -122,6 +122,7 @@ export default function SourceList({ entities, onDelete, onEnable, onChangeGroup + {children} } From 6694ec4a7c12992228708752e920d004dc7698c7 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 15 Jul 2022 10:27:04 -0700 Subject: [PATCH 11/57] Added spinner to history pages --- .../app/metadata/hoc/MetadataVersionsLoader.js | 16 +++++++++++++--- ui/src/app/metadata/view/MetadataHistory.js | 6 ++---- ui/src/app/metadata/view/MetadataWizard.js | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js index 025cea743..f552db8c4 100644 --- a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js +++ b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js @@ -4,12 +4,15 @@ import { getMetadataPath } from '../hooks/api'; import API_BASE_PATH from '../../App.constant'; import useFetch from 'use-http'; import { last } from 'lodash'; +import Spinner from '../../core/components/Spinner'; export function MetadataVersionsLoader ({versions, children}) { const ref = React.useRef({}); const [list, setList] = React.useState({}); + const [loading, setLoading] = React.useState(false); + const { type, id } = useParams(); const { get, response } = useFetch(`/${API_BASE_PATH}${getMetadataPath(type)}/${id}/Versions`, { @@ -22,6 +25,8 @@ export function MetadataVersionsLoader ({versions, children}) { addToList(v, l); if (last(versions) !== v) { loadNext(versions[versions.indexOf(v) + 1]); + } else { + setLoading(false); } } } @@ -36,14 +41,19 @@ export function MetadataVersionsLoader ({versions, children}) { function loadNext (v) { loadVersion(v); + } /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { loadNext(versions[0]); + setLoading(true); }, [versions]); - return ( - {children(versions.map(v => list[v]).filter(v => !!v))} - ); + return ( + + {children(versions.map(v => list[v]).filter(v => !!v))} + {loading &&
} +
+ ); } \ No newline at end of file diff --git a/ui/src/app/metadata/view/MetadataHistory.js b/ui/src/app/metadata/view/MetadataHistory.js index 719ce8dc3..6df6a7c2e 100644 --- a/ui/src/app/metadata/view/MetadataHistory.js +++ b/ui/src/app/metadata/view/MetadataHistory.js @@ -9,6 +9,7 @@ import Translate from '../../i18n/components/translate'; import { useMetadataHistory } from '../hooks/api'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faUndo } from '@fortawesome/free-solid-svg-icons'; +import Spinner from '../../core/components/Spinner'; const sortVersionsByDate = (versions) => { return versions.sort((a, b) => { @@ -107,16 +108,13 @@ export function MetadataHistory () { )} + {loading &&
} } - {loading &&
- - Loading... -
} ); } \ No newline at end of file diff --git a/ui/src/app/metadata/view/MetadataWizard.js b/ui/src/app/metadata/view/MetadataWizard.js index a95ca777c..8dc5a9d51 100644 --- a/ui/src/app/metadata/view/MetadataWizard.js +++ b/ui/src/app/metadata/view/MetadataWizard.js @@ -8,6 +8,7 @@ import { useMetadataEntity } from '../hooks/api'; import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { Prompt, useHistory } from 'react-router-dom'; import { useTranslator } from '../../i18n/hooks'; +import Spinner from '../../core/components/Spinner'; export function MetadataWizard ({type, data, onCallback}) { @@ -61,6 +62,7 @@ export function MetadataWizard ({type, data, onCallback}) { : } + {loading &&
} ); From 5abc51a4815c3e3afc2617cc21b1126511b8324d Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 22 Jul 2022 10:39:01 -0700 Subject: [PATCH 12/57] 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 16f09fa6549fb504022a06ff6022b281bbafdc11 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 27 Jul 2022 10:06:31 -0700 Subject: [PATCH 13/57] Consolidated messages files --- .../main/resources/i18n/messages.properties | 23 +- .../resources/i18n/messages_en.properties | 566 ------------------ 2 files changed, 18 insertions(+), 571 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index d5202280e..a9a0560be 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -216,7 +216,7 @@ label.select-protocol=Select Protocol label.nameid-format=NameID Format label.nameid-formats=NameID Formats label.name-and-entity-id=Name and Entity ID -label.organization-information=SP/Organization Information +label.organization-information=Organization Information label.contact-information=Contact Information label.given-name=Given Name label.contact-type=Contact Type @@ -282,7 +282,7 @@ label.add-a-new-metadata-source=Add a new metadata source - Finish Summary label.name-and-entityid=Name and Entity ID. label.finish-summary-validation=Finished! label.select-entity-id-to-copy=Select the Entity ID to copy -label.metadata-source-name-dashboard-display-only=Metadata Source Name (Dashboard Display Only) +label.metadata-source-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) label.new-entity-id=New Entity ID label.sections-to-copy=Sections to Copy? label.add-a-new-metadata-resolver=Add a new metadata source @@ -417,6 +417,7 @@ label.dynamic-attributes=Dynamic Attributes label.metadata-filter-plugins=Metadata Filter Plugins label.advanced-settings=Advanced Settings label.edit-metadata-provider=Edit Metadata Provider +label.edit-metadata-source=Edit Metadata Source label.http-settings-advanced=Http Settings (Advanced) label.metadata-ui=User Interface / MDUI Information @@ -439,6 +440,7 @@ label.attribute-eduPersonUniqueId=eduPersonUniqueId label.attribute-employeeNumber=employeeNumber label.force-authn=Force AuthN +label.dynamic-attributes=Dynamic Attributes label.min-cache-duration=Min Cache Duration label.max-cache-duration=Max Cache Duration label.max-idle-entity-data=Max Idle Entity Data @@ -466,14 +468,20 @@ label.nameid-formats-type=NameID Type label.select-filter-type=Select Filter Type label.admin=Admin +label.action-required=Action Required +label.user-access-request=User Access Request label.user-maintenance=User Maintenance label.user-id=UserId label.email=Email +label.role=Role label.delete=Delete? - -label.title=Title +label.delete-request=Delete Request +label.enable=Enable +label.disable=Disable label.enabled=Enabled label.disabled=Disabled +label.enable-metadata-sources=Enable Metadata Sources +label.title=Title label.author=Author label.creation-date=Creation Date label.order=Order @@ -543,6 +551,7 @@ message.uri-valid-format=URI must be valid format. message.id-unique=ID must be unique. message.name-unique=Service provider name must be unique. message.array-items-must-be-unique=Items in list must be unique. +message.real-number=Optional. If using a value, must be a real number between 0-1. message.valid-duration=Must be a valid duration. message.valid-name=No special characters or whitespace allowed. message.required=Missing required property. @@ -592,7 +601,9 @@ message.database-constraint=There was a database constraint problem processing t message.no-filters=No Filters message.no-filters-added=No filters have been added to this Metadata Provider - +message.user-request-received-title=User request received +message.user-request-received-body=Your request has been received and is being reviewed. You will be notified with access status. +message.filter-fail=A server error occured, and the filter failed to save. message.create-new-version-from-version=Create New Version from Previous Settings message.restoring-this-version-will-copy=Restoring this version will copy the Version ({ date }) configuration and create a new Version from the selected version settings. You can then edit the configuration before saving the new version. @@ -628,6 +639,8 @@ tooltip.certificate-name=Certificate Name tooltip.certificate-type=Certificate Type tooltip.certificate=Certificate tooltip.logout-endpoints=Logout Endpoints +tooltip.logout-endpoints-url=Logout Endpoints Url +tooltip.logout-endpoints-binding-type=Logout Endpoints Binding Type tooltip.url=Logout Endpoints Url tooltip.binding-type=Logout Endpoints Binding Type tooltip.mdui-display-name=Typically, the IdP Display Name field will be presented on IdP discovery service interfaces. diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index ca93cdbb3..e69de29bb 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -1,566 +0,0 @@ -# Fill this file with key/value pairs, as follows: -# -# some.test.message=This is a test message. -# -# Then, create a copy using the name of the language code: -# -# messages_.properties -# -# Do this for each language we want to support. -# Ideally, all messages should exist for each language. - -action.dashboard=Dashboard -action.logout=Logout -action.add=Add -action.add-new=Add New -action.add-new-provider=Add a new metadata provider -action.add-new-source=Add a new metadata source -action.clear=Clear -action.delete=Delete -action.remove=Remove -action.save=Save -action.toggle=Toggle -action.add-contact=Add Contact -action.add-contacts=Add Contacts -action.use-mine=Use My Changes -action.use-theirs=Use Their Changes -action.discard-changes=Discard Changes -action.add-endpoint=Add Endpoint -action.add-nameid-format=Add NameID Format -action.add-certificate=Add Certificate -action.add-entity-id=Add Entity ID -action.download-file=Download File -action.cancel=Cancel -action.search=Search -action.select-id=Select ID -action.finish-later=Finish Later -action.back=Back -action.next=Next -action.create=Create -action.copy=Copy -action.choose-file=Choose File -action.search-by=Search By -action.preview=Preview -action.select-metadata-filter-type=Select a metadata filter type -action.add-authentication-method=Add Authentication Method -action.move-up=Move Up -action.move-down=Move Down -action.edit=Edit -action.add-filter=Add Filter -action.manage-filters=Manage Filters - -value.enabled=Enabled -value.disabled=Disabled -value.none=None -value.file=File -value.memory=Memory -value.true=true -value.false=false -value.regex=Regex -value.script=Script -value.entity-id=Entity ID - -value.support=Support -value.technical=Technical -value.administrative=Administrative -value.other=Other - -value.signing=Signing -value.encryption=Encryption -value.both=Both - -value.entity=Entity -value.condition-ref=ConditionRef -value.condition-script=ConditionScript - -value.file-backed-http-metadata-provider=FileBackedHttpMetadataProvider -value.file-system-metadata-provider=FileSystemMetadataProvider -value.local-dynamic-metadata-provider=LocalDynamicMetadataProvider -value.dynamic-http-metadata-provider=DynamicHttpMetadataProvider -value.entity-attributes-filter=EntityAttributes Filter -value.spdescriptor=SPSSODescriptor -value.attr-auth-descriptor=AttributeAuthorityDescriptor -value.dynamic-http-metadata-provider=DynamicHttpMetadataProvider -value.local-dynamic-metadata-provider=LocalDynamicMetadataProvider - -value.md-query-protocol=MetadataQueryProtocol -value.template=Template - -brand.header.title=Source Management -brand.logo-link-label=Shibboleth -brand.logo-link-description=Link to Shibboleth Website -brand.logo-alt=Shibboleth Logo - Click to be directed to www.shibboleth.net -brand.footer.text=Links to Shibboleth resources: -brand.footer.links-label-1=Home Page -brand.footer.links-desc-1=Shibboleth.net open-source community home page -brand.footer.links-label-2=Wiki -brand.footer.links-desc-2=Shibboleth.net open-source community wiki -brand.footer.links-label-3=Issue Tracker -brand.footer.links-desc-3=Shibboleth.net open-source community issue tracker -brand.footer.links-label-4=Mailing List -brand.footer.links-desc-4=Shibboleth.net open-source community mailing list -brand.footer.copyright=Copyright \u00A9 {year} Internet2 - -brand.in-partnership-with=In partnership with -brand.and=and - -heading.shibboleth=Shibboleth - -label.metadata-source=Metadata Source -label.metadata-sources=Metadata Sources -label.metadata-provider=Metadata Provider -label.metadata-providers=Metadata Providers -label.source-management=Source Management -label.search-files=Search Files -label.service-provider-entity-id=Service Provider Entity ID -label.service-provider-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) -label.enable-this-service=Enable this service? -label.organization-name=Organization Name -label.organization-display-name=Organization Display Name -label.organization-url=Organization URL -label.name=Name -label.type=Type -label.email-address=Email Address -label.assertion-consumer-service-endpoints=Assertion Consumer Service Endpoints -label.my-changes=My Changes -label.their-changes=Their Changes -label.new-endpoint=New Endpoint -label.select-binding=Select Binding Type -label.mark-as-default=Mark as Default -label.attribute-name=Attribute Name -label.yes=Yes -label.check-all-attributes=Check All Attributes -label.clear-all-attributes=Clear All Attributes -label.protocol-support-enumeration=Protocol Support Enumeration -label.select-protocol=Select Protocol -label.nameid-format=NameID Format -label.nameid-formats=NameID Formats -label.name-and-entity-id=Name and Entity ID -label.organization-information=Organization Information -label.contact-information=Contact Information -label.given-name=Given Name -label.contact-type=Contact Type -label.user-interface-mdui-infromation=User Interface / MDUI Information -label.display-name=Display Name -label.information-url=Information URL -label.description=Description -label.privacy-statement=Privacy Statement URL -label.logo-url=Logo URL -label.logo-width=Logo Width -label.logo-height=Logo Height -label.sp-sso-descriptor-information=SP SSO Descriptor Information -label.logout-endpoints=Logout Endpoints -label.binding-types=Binding Type -label.security-information=Security Information -label.is-there-a-x509-certificate=Is there a X509 Certificate? -label.authentication-requests-signed=Authentication Requests Signed? -label.want-assertions-signed=Want Assertions Signed? -label.x509-certificates=X509 Certificates -label.certificate-name-display-only=Certificate Name (Display Only) -label.certificate=Certificate -label.assertion-consumer-services=Assertion Consumer Services -label.assertion-consumer-service-location=Location -label.assertion-consumer-service-endpoint=Assertion Consumer Service Endpoints -label.default=(default) -label.assertion-consumer-service-location-binding=Location Binding -label.relying-party-overrides=Relying Party Overrides -label.sign-the-assertion=Sign the Assertion? -label.turn-off-encryption-of-response=Turn off Encryption of Response? -label.use-sha1-signing-algorithm=Use SHA1 Signing Algorithm? -label.ignore-any-sp-requested-authentication-method=Ignore any SP-Requested Authentication Method? -label.omit-not-before-condition=Omit Not Before Condition? -label.responderid=ResponderID -label.attribute-release=Attribute Release -label.true=True -label.false=False -label.no=No -label.new-cert=New Certificate -label.url=URL -label.privacy-statement-url=Privacy Statement URL -label.contact-name=Contact Name -label.select-contact-type=Select Contact Type -label.contact-email-address=Contact Email Address -label.dont-sign-the-response=Don\u0027t Sign the Response -label.nameid-format-to-send=NameID Format to Send -label.authentication-methods-to-use=Authentication Methods to Use -label.auth-method-indexed=Authentication Method -label.preview-provider=Preview XML -label.search-entity-id=Search Entity Id -label.edit-filter=Edit Filter -label.min-4-chars=Minimum 4 characters. -label.new-filter=New Filter -label.service-provider=Metadata Source Name: -label.created-date=Created Date: -label.service-entity-id=Metadata Source Entity ID: -label.service-provider-status=Metadata Source Status: -label.current-metadata-sources=Current Metadata Sources -label.current-metadata-providers=Current Metadata Providers -label.add-a-new-metadata-provider=Add a new metadata provider -label.service-resolver-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) -label.service-resolver-entity-id=Service Provider Entity ID -label.add-a-new-metadata-source=Add a new metadata source - Finish Summary -label.name-and-entityid=Name and Entity ID. -label.finish-summary-validation=Finished! -label.select-entity-id-to-copy=Select the Entity ID to copy -label.metadata-source-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) -label.new-entity-id=New Entity ID -label.sections-to-copy=Sections to Copy? -label.add-a-new-metadata-resolver=Add a new metadata source -label.how-are-you-adding-the-metadata-information=How are you adding the metadata information? -label.upload-url=Upload/URL -label.or=or -label.name-and-upload-url=Name and Upload Url -label.service-resolver-file=Select Provider Metadata File -label.service-resolver-metadata-url=Service Provider Metadata URL -label.search-criteria-by=Search Criteria by { displayType } -label.entity-ids-added=Entity Ids Added -label.ui-mdui-info=User Interface / MDUI Information -label.sp-sso-descriptor-info=SP SSO Descriptor Information -label.security-info=Security Information -label.sp-org-info=SP/Organization Information -label.finished=Finished! -label.signing=Signing -label.encryption=Encryption -label.both=Both -label.org-info=Organization Information -label.security-descriptor-info=Security Descriptor Information -label.entity-id=Entity ID -label.service-provider-name=Service Provider Name -label.organization=Organization -label.contacts=Contacts -label.contact=Contact -label.mdui=MDUI Information -label.service-provider-sso-descriptor=Service Provider Sso Descriptor -label.service-enabled=Service Enabled -label.filter-name=Filter Name -label.filter-enabled=Filter Enabled -label.filter-target=FilterTarget -label.filter-type=Filter Type -label.value=Value -label.binding-type=Binding Type -label.sign-assertion=Sign Assertions -label.dont-sign-response=Don\u0027t Sign Response -label.turn-off-encryption=Turn off encryption -label.use-sha=Use Sha -label.ignore-authentication-method=Ignore Authentication Method -label.omit-not-before=Omit Not Before -label.responder-id=Responder ID -label.name-id-formats=Name ID Formats -label.name-id-format= Name ID Format -label.authentication-methods=Authentication Methods -label.authentication-method=Authentication Method -label.x509-certificate-available=x509 Certificate Available -label.protocol-support-enum=Protocol Support Enumeration -label.binding=Binding -label.location-url=Location URL -label.make-default=Make Default -label.metadata-provider-name-dashboard-display-only=Metadata Provider Name (Dashboard Display Only) -label.default-authentication-methods=Default Authentication Method(s) -label.new-of-type=New { type } - -label.metadata-filter-name=Metadata Filter Name (Dashboard Display Only) -label.filter-enable=Enable this Filter? -label.search-criteria=Search Criteria -label.metadata-filter=Metadata Filter -label.metadata-filter-type=Metadata Filter Type - -label.http-connection-attributes=HTTP Connection Attributes -label.http-security-attributes=HTTP Security Attributes -label.http-proxy-attributes=HTTP Proxy Attributes -label.http-caching-attributes=HTTP Caching Attributes - -label.connection-request-timeout=Connection Request Timeout -label.connection-timeout=Connection Timeout -label.socket-timeout=Socket Timeout -label.disregard-tls-cert=Disregard TLS Certificate? -label.proxy-host=Proxy Host -label.proxy-port=Proxy Port -label.proxy-user=Proxy User -label.proxy-password=Proxy Password -label.http-caching=HTTP Caching? -label.select-caching-type=Select Caching Type -label.http-caching-directory=HTTP Cache Directory -label.http-max-cache-entries=HTTP Max Cache Entries -label.max-cache-entry-size=HTTP Max Cache Entry Size -label.duration=Duration -label.real-number=Real Number (between 0.0 and 1.0) -label.min-refresh-delay=Min Refresh Delay -label.max-refresh-delay=Max Refresh Delay -label.refresh-delay-factor=Refresh Delay Factor -label.resolve-via-predicates-only=Resolve Via Predicates Only? -label.expiration-warning-threshold=Expiration Warning Threshold - -label.satisfy-any-predicates=Satisfy Any Predicates? -label.use-default-predicate-reg=Use Default Predicate Registry? -label.fail-fast-init=Fail Fast Initialization? -label.require-valid-metadata=Require Valid Metadata? -label.backup-file-init-refresh-delay=Backup File Init Next Refresh Delay -label.backing-file=Backing File -label.init-from-backup=Initialize From Backup File? -label.metadata-url=Metadata URL -label.xml-id=ID -label.enable-service=Enable this service? -label.metadata-provider-type=Metadata Provider Type -label.metadata-provider-name=Metadata Provider Name -label.select-metadata-type=Select a metadata provider type -label.metadata-provider-status=Metadata Provider Status -label.enable-provider-upon-saving=Enable Metadata Provider? -label.certificate-type=Type - -label.metadata-file=Metadata File - -label.enable-filter=Enable Filter? -label.required-valid-until=Required Valid Until Filter -label.max-validity-interval=Max Validity Interval -label.signature-validation-filter=Signature Validation Filter -label.require-signed-root=Require Signed Root -label.certificate-file=Certificate File -label.entity-role-whitelist=Entity Role Whitelist Filter -label.retained-roles=Retained Roles -label.remove-roleless-entity-descriptors=Remove Roleless Entity Descriptors? -label.remove-empty-entities-descriptors=Remove Empty Entities Descriptors? - -label.select-metadata-provider-type=Select Metadata Provider Type -label.filter-list=Filter List -label.common-attributes=Common Attributes -label.reloading-attributes=Reloading Attributes -label.dynamic-attributes=Dynamic Attributes -label.metadata-filter-plugins=Metadata Filter Plugins -label.advanced-settings=Advanced Settings -label.edit-metadata-provider=Edit Metadata Provider -label.edit-metadata-source=Edit Metadata Source -label.http-settings-advanced=Http Settings (Advanced) - -label.metadata-ui=User Interface / MDUI Information -label.descriptor-info=SP SSO Descriptor Information -label.key-info=Security Information -label.assertion=Assertion Consumer Service -label.relying-party=Relying Party Overrides - -label.attribute-eduPersonPrincipalName=eduPersonPrincipalName (EPPN) -label.attribute-uid=uid -label.attribute-mail=mail -label.attribute-surname=surname -label.attribute-givenName=givenName -label.attribute-eduPersonAffiliation=eduPersonAffiliation -label.attribute-eduPersonScopedAffiliation=eduPersonScopedAffiliation -label.attribute-eduPersonPrimaryAffiliation=eduPersonPrimaryAffiliation -label.attribute-eduPersonEntitlement=eduPersonEntitlement -label.attribute-eduPersonAssurance=eduPersonAssurance -label.attribute-eduPersonUniqueId=eduPersonUniqueId -label.attribute-employeeNumber=employeeNumber -label.force-authn=Force AuthN - -label.dynamic-attributes=Dynamic Attributes -label.min-cache-duration=Min Cache Duration -label.max-cache-duration=Max Cache Duration -label.max-idle-entity-data=Max Idle Entity Data -label.cleanup-task-interval=Cleanup Task Interval -label.persistent-cache-manager-directory=Persistent Cache Manager Directory -label.initialize-from-persistent-cache-in-background=Initialize from Persistent Cache in Background? -label.background-init-from-cache-delay=Background Initialization from Cache Delay -label.source-directory=Source Directory -label.remove-idle-entity-data=Remove Idle Entity Data? -label.do-resolver-initialization=Initialize -label.file-doesnt-exist=The file specified in the resolver does not exist on the file system. Therefore, the resolver cannot be initialized. - -label.md-request-type=Metadata Request URL Construction Type -label.md-request-value=Metadata Request URL Construction Value -label.transform-ref=Transform Ref -label.encoding-style=Encoding Style -label.velocity-engine=Velocity Engine -label.match=Match - -label.remove-existing-formats=Remove Existing Formats? -label.nameid-formats-format=NameID Format -label.nameid-formats-value=NameID Value -label.nameid-formats-type=NameID Type - -label.select-filter-type=Select Filter Type - -label.admin=Admin -label.action-required=Action Required -label.user-access-request=User Access Request -label.user-maintenance=User Maintenance -label.user-id=UserId -label.email=Email -label.role=Role -label.delete=Delete? -label.delete-request=Delete Request - -label.enable=Enable -label.disable=Disable -label.enable-metadata-sources=Enable Metadata Sources - -label.source=Metadata Source -label.provider=Metadata Provider - -message.delete-user-title=Delete User? -message.delete-user-body=You are requesting to delete a user. If you complete this process the user will be removed. This cannot be undone. Do you wish to continue? - -message.must-be-unique=Must be unique. -message.name-must-be-unique=Name must be unique. -message.uri-valid-format=URI must be valid format. -message.id-unique=ID must be unique. -message.array-items-must-be-unique=Items in list must be unique. -message.real-number=Optional. If using a value, must be a real number between 0-1. - -message.org-name-required=Organization Name is required. -message.org-displayName-required=Organization Name is required. -message.org-url-required=Organization Name is required. -message.org-incomplete=These three fields must all be entered if any single field has a value. - -message.type-required=Missing required property: Type -message.match-required=Missing required property: Match -message.value-required=Missing required property: Value -message.required=Missing required property. - -message.conflict=Conflict -message.data-version-contention=Data Version Contention -message.contention-new-version=A newer version of this metadata source has been saved. Below are a list of changes. You can use your changes or their changes. -message.organization-feedback=These three fields must all be entered if any single field has a value. -message.valid-email=Must be a valid Email Address -message.valid-url=Must be a valid URL -message.must-be-valid-url=Must be a valid URL -message.must-be-integer=Must be an integer equal to or greater than 0 -message.delete-source-title=Delete Metadata Source? -message.delete-source-body=You are deleting a metadata source. This cannot be undone. Continue? -message.incomplete-form=Incomplete Form -message.delete-filter-title=Delete Metadata Filter? -message.delete-filter-body=You are deleting a metadata filter. This cannot be undone. Continue? -message.unsaved-dialog-title=Save your information? -message.unsaved-editor=You have not saved your changes. If you exit this screen, your changes will be lost. -message.editor-invalid=All forms must be valid before changes can be saved! -message.unsaved-source-1=You have not completed the wizard! Do you wish to save this information? You can finish the wizard later by clicking the \u0027Edit\u0027 -message.unsaved-source-2=icon on the dashboard. -message.service-resolver-name-required=Service Provider Name is required -message.entity-id-required=Entity ID is required -message.entity-id-must-be-unique=Entity ID must be unique -message.target-required=Entity ID to copy is required -message.file-upload-alert=Note: You can only import a file with a single entityID (EntityDescriptor element) in it. Anything more in that file will result in an error. -message.add-new-md-resolver=Add a new metadata source -message.wizard-status=Step { index } of { length } -message.entity-id-min-unique=You must add at least one entity id target and they must each be unique. -message.required-for-scripts=Required for Scripts -message.required-for-regex=Required for Regex -message.file-doesnt-exist=The requested file to be processed does not exist on the server. -message.database-constraint=There was a database constraint problem processing the request. Check the request to ensure that fields that must be unique are truly unique. - -message.user-request-received-title=User request received -message.user-request-received-body=Your request has been received and is being reviewed. You will be notified with access status. - -message.filter-fail=A server error occured, and the filter failed to save. - -tooltip.entity-id=Entity ID -tooltip.service-provider-name=Service Provider Name (Dashboard Display Only) -tooltip.force-authn=Disallows use (or reuse) of authentication results and login flows that don\u0027t provide a real-time proof of user presence in the login process -tooltip.service-provider-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) -tooltip.service-provider-entity-id=Service Provider Entity ID -tooltip.organization-name=Organization Name -tooltip.organization-display-name=Organization Display Name -tooltip.organization-url=Organization URL -tooltip.name=Name -tooltip.type=Type -tooltip.email-address=Email Address -tooltip.assertion-consumer-service-location=Assertion Consumer Service Location -tooltip.assertion-consumer-service-location-binding=Assertion Consumer Service Location Binding -tooltip.mark-as-default=Mark as Default -tooltip.protocol-support-enumeration=Protocol Support Enumeration -tooltip.nameid-format=Content is name identifier format which is added to all the applicable roles of the entities which match any of the following or {{}}elements. -tooltip.enable-this-service-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP -tooltip.authentication-requests-signed=Authentication Requests Signed -tooltip.want-assertions-signed=Want Assertions Signed -tooltip.certificate-name=Certificate Name -tooltip.certificate-type=Certificate Type -tooltip.certificate=Certificate -tooltip.logout-endpoints-url=Logout Endpoints Url -tooltip.logout-endpoints-binding-type=Logout Endpoints Binding Type -tooltip.mdui-display-name=Typically, the IdP Display Name field will be presented on IdP discovery service interfaces. -tooltip.mdui-information-url=The IdP Information URL is a link to a comprehensive information page about the IdP. This page should expand on the content of the IdP Description field. -tooltip.mdui-description=The IdP Description is a brief description of the IdP service. On a well-designed discovery interface, the IdP Description will be presented to the user in addition to the IdP Display Name, and so the IdP Description helps disambiguate duplicate or similar IdP Display Names. -tooltip.mdui-privacy-statement-url=The IdP Privacy Statement URL is a link to the IdP\u0027s Privacy Statement. The content of the Privacy Statement should be targeted at end users. -tooltip.mdui-logo-url=The IdP Logo URL in metadata points to an image file on a remote server. A discovery service, for example, may rely on a visual cue (i.e., a logo) instead of or in addition to the IdP Display Name. -tooltip.mdui-logo-width=The logo should have a minimum width of 100 pixels -tooltip.mdui-logo-height=The logo should have a minimum height of 75 pixels and a maximum height of 150 pixels (or the application will scale it proportionally) -tooltip.contact-name=Contact Name -tooltip.contact-type=Contact Type -tooltip.contact-email=Contact Email -tooltip.sign-assertion=Sign Assertion -tooltip.dont-sign-response=Don\u0027t Sign Response -tooltip.turn-off-encryption=Turn Off Encryption of Response -tooltip.usa-sha-algorithm=Use SHA1 Signing Algorithm -tooltip.authentication-methods-to-use=Authentication Methods to Use -tooltip.ignore-auth-method=Ignore any SP-Requested Authentication Method -tooltip.omit-not-before-condition=Omit Not Before Condition -tooltip.responder-id=ResponderId -tooltip.instruction=Information icon -tooltip.attribute-release-table=Attribute release table - select the attributes you want to release (default unchecked) -tooltip.metadata-filter-name=Metadata Filter Name -tooltip.metadata-filter-type=Metadata Filter Type -tooltip.connection-request-timeout=The maximum amount of time to wait for a connection to be returned from the HTTP client\u0027s connection pool manager. Set to PT0S to disable. This attribute is incompatible with httpClientRef. -tooltip.connection-timeout=The maximum amount of time to wait to establish a connection with the remote server. Set to PT0S to disable. This attribute is incompatible with httpClientRef. -tooltip.socket-timeout=The maximum amount of time to wait between two consecutive packets while reading from the socket connected to the remote server. Set to PT0S to disable. This attribute is incompatible with httpClientRef. -tooltip.disregard-tls-cert=If true, no TLS certificate checking will take place over an HTTPS connection. This attribute is incompatible with httpClientRef. (Be careful with this setting, it is typically only used during testing. See the HttpClientConfiguration topic for more information.) -tooltip.proxy-host=The hostname of the HTTP proxy through which connections will be made. This attribute is incompatible with httpClientRef. -tooltip.proxy-port=The port of the HTTP proxy through which connections will be made. This attribute is incompatible with httpClientRef. -tooltip.proxy-user=The username used with the HTTP proxy through which connections will be made. This attribute is incompatible with httpClientRef. -tooltip.proxy-password=The password used with the HTTP proxy through which connections will be made. This attribute is incompatible with httpClientRef. -tooltip.http-caching=The type of low-level HTTP caching to perform. There are three choices: 'none' indicates the HTTP response is not cached by the client library, 'file' indicates the HTTP response is written to disk (but will not survive a restart), 'memory' indicates the HTTP response is stored in memory. This attribute is incompatible with httpClientRef and its value may not be specified as a bean property. Some metadata providers, most notably the reloading 'batch-oriented' providers, implement HTTP caching at a higher layer and tend to work best with httpCaching='none'. -tooltip.http-caching-directory=If httpCaching='file', this attribute specifies where retrieved files are to be cached. This attribute is incompatible with httpClientRef. -tooltip.http-max-cache-entries=The maximum number of responses written to cache. This attribute is incompatible with httpClientRef. -tooltip.max-cache-entry-size=The maximum response body size that may be cached, in bytes. This attribute is incompatible with httpClientRef. - -tooltip.metadata-provider-name=Metadata Provider Name (for display on the Dashboard only) -tooltip.metadata-provider-type=Metadata Provider Type -tooltip.xml-id=Identifier for logging, identification for command line reload, etc. -tooltip.metadata-url=The URL that the metadata is served from. -tooltip.metadata-file=The absolute path to the local metadata file to be loaded. -tooltip.init-from-backup=Flag indicating whether initialization should first attempt to load metadata from the backup file. If true, foreground initialization will be performed by loading the backing file, and then a refresh from the remote HTTP server will be scheduled to execute in a background thread, after a configured delay. This can improve IdP startup times when the remote HTTP file is large in size. -tooltip.backing-file=Specifies where the backing file is located. If the remote server is unavailable at startup, the backing file is loaded instead. -tooltip.backup-file-init-refresh-delay=Delay duration after which to schedule next HTTP refresh when initialized from the backing file. -tooltip.require-valid-metadata=Whether candidate metadata found by the resolver must be valid in order to be returned (where validity is implementation specific, but in SAML cases generally depends on a validUntil attribute.) If this flag is true, then invalid candidate metadata will not be returned. -tooltip.fail-fast-init=Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. -tooltip.use-default-predicate-reg=Flag which determines whether the default CriterionPredicateRegistry will be used if a custom one is not supplied explicitly. -tooltip.satisfy-any-predicates=Flag which determines whether predicates used in filtering are connected by a logical 'OR' (true) or by logical 'AND' (false). -tooltip.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP - -tooltip.max-validity-interval=Defines the window within which the metadata is valid. -tooltip.require-signed-root=If true, this fails to load metadata with no signature on the root XML element. -tooltip.certificate-file=A path (on the local file system) to a certificate file whose key is used to verify the signature. Conflicts with trustEngineRef and both of the child elements. -tooltip.retained-roles=Note that property replacement cannot be used on this element. -tooltip.remove-roleless-entity-descriptors=Controls whether to keep entity descriptors that contain no roles. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one role descriptor. -tooltip.remove-empty-entities-descriptors=Controls whether to keep entities descriptors that contain no entity descriptors. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one child element, either an element or an element. - -tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. Setting this to 0 will result in the default value being used. -tooltip.max-refresh-delay=Upper bound on the next refresh from the time calculated based on the metadata\u0027s expiration. -tooltip.refresh-delay-factor=A factor applied to the initially determined refresh time in order to determine the next refresh time (typically to ensure refresh takes place prior to the metadata\u0027s expiration). Attempts to refresh metadata will generally begin around the product of this number and the maximum refresh delay. -tooltip.resolve-via-predicates-only=Flag indicating whether resolution may be performed solely by applying predicates to the entire metadata collection, when an entityID input criterion is not supplied. -tooltip.expiration-warning-threshold=For each attempted metadata refresh (whether or not fresh metadata is obtained), if requireValidMetadata is true, and there is a validUntil XML attribute on the document root element, and the difference between validUntil and the current time is less than expirationWarningThreshold, the system logs a warning about the impending expiration. - -tooltip.filter-name=Filter Name -tooltip.enable-filter=Enable Filter? -tooltip.enable-service=Enable Service? - -tooltip.min-cache-duration=The minimum duration for which metadata will be cached before it is refreshed. -tooltip.max-cache-duration=The maximum duration for which metadata will be cached before it is refreshed. -tooltip.max-idle-entity-data=The maximum duration for which metadata will be allowed to be idle (no requests for it) before it is removed from the cache. -tooltip.cleanup-task-interval=The interval at which the internal cleanup task should run. This task performs background maintenance tasks, such as the removal of expired and idle metadata. -tooltip.persistent-cache-manager-directory=The optional manager for the persistent cache store for resolved metadata. On metadata provider initialization, data present in the persistent cache will be loaded to memory, effectively restoring the state of the provider as closely as possible to that which existed before the previous shutdown. Each individual cache entry will only be loaded if 1) the entry is still valid as determined by the internal provider logic, and 2) the entry passes the (optional) predicate supplied via initializationFromCachePredicateRef. -tooltip.initialize-from-persistent-cache-in-background=Flag indicating whether should initialize from the persistent cache in the background. Initializing from the cache in the background will improve IdP startup times. -tooltip.background-init-from-cache-delay=The delay after which to schedule the background initialization from the persistent cache when initializeFromPersistentCacheInBackground=true. - -tooltip.source-directory=Convenience mechanism for wiring a FilesystemLoadSaveManager, loading from the specified source directory in the local filesystem. This attribute will be ignored if sourceManagerRef is also specified. Either this attribute or sourceManagerRef is required. -tooltip.remove-idle-entity-data=Flag indicating whether idle metadata should be removed. - -tooltip.do-resolver-initialization=Initialize this resolver? In the case of Filesystem resolvers, this will cause the system to read the file and index the resolver. -tooltip.md-request-type=Options are 1) Metadata Query Protocol, 2) Regex. -tooltip.md-request-value=Content of the element. -tooltip.transform-ref=A reference to a transform function for the entityID. If used, the child element must be empty. -tooltip.encoding-style=Determines whether and how the entityID value will be URL encoded prior to replacement. Allowed values are: 1) "none" - no encoding is performed, 2) "form" - encoded using URL form parameter encoding (for query parameters), 3) "path" - encoded using URL path encoding, or 4) "fragment" - encoded using URL fragment encoding. The precise definition of these terms is defined in the documentation for the methods of the Guava library\u0027s UrlEscapers class. -tooltip.velocity-engine=This attribute may be used to specify the name of the Velocity engine defined within the application. -tooltip.match=A regular expression against which the entityID is evaluated. - -tooltip.remove-existing-formats=Whether to remove any existing formats from a role if any are added by the filter (unmodified roles will be untouched regardless of this setting) -tooltip.nameid-formats-format=Format -tooltip.nameid-formats-value=Value -tooltip.nameid-formats-type=Type \ No newline at end of file From f5a59a7b73a6014fddc1b16313d5ba3991993206 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 27 Jul 2022 12:39:22 -0700 Subject: [PATCH 14/57] Fixed admin route --- ui/src/app/dashboard/view/Dashboard.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/src/app/dashboard/view/Dashboard.js b/ui/src/app/dashboard/view/Dashboard.js index e5f145572..b1d058eaf 100644 --- a/ui/src/app/dashboard/view/Dashboard.js +++ b/ui/src/app/dashboard/view/Dashboard.js @@ -112,6 +112,9 @@ export function Dashboard () { } /> + + + } From 7000cc0e77f7003e75cb77ee22f20646b614af04 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 27 Jul 2022 15:01:09 -0700 Subject: [PATCH 15/57] Updated spinners --- ui/src/app/metadata/hoc/MetadataSchema.js | 13 +++++++++++-- ui/src/app/metadata/hoc/MetadataVersionsLoader.js | 2 +- ui/src/app/metadata/view/MetadataWizard.js | 6 ++++-- .../app/metadata/wizard/MetadataProviderWizard.js | 6 +++++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ui/src/app/metadata/hoc/MetadataSchema.js b/ui/src/app/metadata/hoc/MetadataSchema.js index 025e7a415..d2d257623 100644 --- a/ui/src/app/metadata/hoc/MetadataSchema.js +++ b/ui/src/app/metadata/hoc/MetadataSchema.js @@ -9,6 +9,7 @@ export const MetadataDefinitionContext = React.createContext(); export function MetadataSchema({ type, children, wizard = false }) { const definition = React.useMemo(() => wizard ? getWizard(type) : getDefinition(type), [type, wizard]); + const [loading, setLoading] = React.useState(false); const { get, response } = useFetch(``, { cachePolicy: 'no-cache' @@ -21,18 +22,20 @@ export function MetadataSchema({ type, children, wizard = false }) { if (response.ok) { setSchema(source); } + setLoading(false); } /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { setSchema(null); loadSchema(definition); + setLoading(true); }, [definition]); return ( {type && definition && schema && - + {children} } @@ -41,7 +44,13 @@ export function MetadataSchema({ type, children, wizard = false }) { } export function useMetadataSchemaContext () { - return React.useContext(MetadataSchemaContext); + const {schema} = React.useContext(MetadataSchemaContext); + return schema; +} + +export function useMetadataSchemaLoading () { + const {loading} = React.useContext(MetadataSchemaContext); + return loading; } export function useMetadataDefinitionContext() { diff --git a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js index f552db8c4..d957903d9 100644 --- a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js +++ b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js @@ -52,8 +52,8 @@ export function MetadataVersionsLoader ({versions, children}) { return ( - {children(versions.map(v => list[v]).filter(v => !!v))} {loading &&
} + {children(versions.map(v => list[v]).filter(v => !!v))}
); } \ No newline at end of file diff --git a/ui/src/app/metadata/view/MetadataWizard.js b/ui/src/app/metadata/view/MetadataWizard.js index 8dc5a9d51..d48cc4330 100644 --- a/ui/src/app/metadata/view/MetadataWizard.js +++ b/ui/src/app/metadata/view/MetadataWizard.js @@ -58,11 +58,13 @@ export function MetadataWizard ({type, data, onCallback}) { /> {type === 'source' ? - + + + {loading &&
} +
: } - {loading &&
}
); diff --git a/ui/src/app/metadata/wizard/MetadataProviderWizard.js b/ui/src/app/metadata/wizard/MetadataProviderWizard.js index 7193c0573..72df681fd 100644 --- a/ui/src/app/metadata/wizard/MetadataProviderWizard.js +++ b/ui/src/app/metadata/wizard/MetadataProviderWizard.js @@ -2,7 +2,7 @@ import React from 'react'; import { WizardNav } from './WizardNav'; import { MetadataWizardForm } from './MetadataWizardForm'; import { setWizardIndexAction, useCurrentIndex, useIsLastPage, useWizardDispatcher } from './Wizard'; -import { useMetadataDefinitionContext, useMetadataDefinitionValidator, useMetadataSchemaContext } from '../hoc/MetadataSchema'; +import { useMetadataDefinitionContext, useMetadataDefinitionValidator, useMetadataSchemaContext, useMetadataSchemaLoading } from '../hoc/MetadataSchema'; import { checkChanges, useMetadataSchema } from '../hooks/schema'; import { useMetadataFormDispatcher, setFormDataAction, setFormErrorAction, useMetadataFormData, useMetadataFormErrors } from '../hoc/MetadataFormContext'; import { MetadataConfiguration } from '../component/MetadataConfiguration'; @@ -12,6 +12,7 @@ import { useMetadataProviders } from '../hooks/api'; import { removeNull } from '../../core/utility/remove_null'; import { useUserGroup } from '../../core/user/UserContext'; +import Spinner from '../../core/components/Spinner'; export function MetadataProviderWizard({onSave, loading, block}) { @@ -20,6 +21,7 @@ export function MetadataProviderWizard({onSave, loading, block}) { const definition = useMetadataDefinitionContext(); const schema = useMetadataSchemaContext(); + const schemaLoading = useMetadataSchemaLoading(); const processed = useMetadataSchema(definition, schema); @@ -49,6 +51,7 @@ export function MetadataProviderWizard({onSave, loading, block}) { return ( <> +

+ {schemaLoading &&
}
Date: Thu, 28 Jul 2022 07:57:21 -0700 Subject: [PATCH 16/57] Fixed issue with configuration loading --- ui/src/app/metadata/hoc/MetadataSchema.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ui/src/app/metadata/hoc/MetadataSchema.js b/ui/src/app/metadata/hoc/MetadataSchema.js index d2d257623..ea14361d9 100644 --- a/ui/src/app/metadata/hoc/MetadataSchema.js +++ b/ui/src/app/metadata/hoc/MetadataSchema.js @@ -5,6 +5,7 @@ import { useTranslator } from '../../i18n/hooks'; export const MetadataSchemaContext = React.createContext(); export const MetadataDefinitionContext = React.createContext(); +export const MetadataSchemaLoading = React.createContext(); export function MetadataSchema({ type, children, wizard = false }) { @@ -35,8 +36,10 @@ export function MetadataSchema({ type, children, wizard = false }) { return ( {type && definition && schema && - - {children} + + + {children} + } @@ -44,13 +47,11 @@ export function MetadataSchema({ type, children, wizard = false }) { } export function useMetadataSchemaContext () { - const {schema} = React.useContext(MetadataSchemaContext); - return schema; + return React.useContext(MetadataSchemaContext); } export function useMetadataSchemaLoading () { - const {loading} = React.useContext(MetadataSchemaContext); - return loading; + return React.useContext(MetadataSchemaLoading); } export function useMetadataDefinitionContext() { From c86215745ee2e3ce83b6ca3a93580d62f8607c7a Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 28 Jul 2022 09:50:01 -0700 Subject: [PATCH 17/57] Fixed loading spinner --- ui/src/app/metadata/view/MetadataWizard.js | 6 +----- ui/src/app/metadata/wizard/MetadataSourceWizard.js | 5 ++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ui/src/app/metadata/view/MetadataWizard.js b/ui/src/app/metadata/view/MetadataWizard.js index d48cc4330..a95ca777c 100644 --- a/ui/src/app/metadata/view/MetadataWizard.js +++ b/ui/src/app/metadata/view/MetadataWizard.js @@ -8,7 +8,6 @@ import { useMetadataEntity } from '../hooks/api'; import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { Prompt, useHistory } from 'react-router-dom'; import { useTranslator } from '../../i18n/hooks'; -import Spinner from '../../core/components/Spinner'; export function MetadataWizard ({type, data, onCallback}) { @@ -58,10 +57,7 @@ export function MetadataWizard ({type, data, onCallback}) { /> {type === 'source' ? - - - {loading &&
} -
+ : } diff --git a/ui/src/app/metadata/wizard/MetadataSourceWizard.js b/ui/src/app/metadata/wizard/MetadataSourceWizard.js index 5dae8319a..b14c5c6d4 100644 --- a/ui/src/app/metadata/wizard/MetadataSourceWizard.js +++ b/ui/src/app/metadata/wizard/MetadataSourceWizard.js @@ -8,7 +8,7 @@ import Col from 'react-bootstrap/Col'; import { WizardNav } from './WizardNav'; import { MetadataWizardForm } from './MetadataWizardForm'; import { setWizardIndexAction, useCurrentIndex, useIsFirstPage, useIsLastPage, useWizardDispatcher } from './Wizard'; -import { useMetadataDefinitionContext, useMetadataSchemaContext, useMetadataDefinitionValidator } from '../hoc/MetadataSchema'; +import { useMetadataDefinitionContext, useMetadataSchemaContext, useMetadataDefinitionValidator, useMetadataSchemaLoading } from '../hoc/MetadataSchema'; import { useMetadataFormDispatcher, setFormDataAction, setFormErrorAction, useMetadataFormData, useMetadataFormErrors } from '../hoc/MetadataFormContext'; import { MetadataConfiguration } from '../component/MetadataConfiguration'; import { Configuration } from '../hoc/Configuration'; @@ -17,6 +17,7 @@ import { useMetadataSources } from '../hooks/api'; import Translate from '../../i18n/components/translate'; import { checkChanges } from '../hooks/utility'; import { useCurrentUserLoader, useUserGroup } from '../../core/user/UserContext'; +import Spinner from '../../core/components/Spinner'; export function MetadataSourceWizard ({ onShowNav, onSave, block, loading }) { @@ -24,6 +25,7 @@ export function MetadataSourceWizard ({ onShowNav, onSave, block, loading }) { const group = useUserGroup(); const userLoader = useCurrentUserLoader(); + const schemaLoading = useMetadataSchemaLoading(); /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { @@ -75,6 +77,7 @@ export function MetadataSourceWizard ({ onShowNav, onSave, block, loading }) {

+ {schemaLoading &&
} {warnings && warnings.hasOwnProperty(current) && From 848626cf04fb39d46513e45c2184c44a5632963c Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 2 Aug 2022 08:25:55 -0700 Subject: [PATCH 18/57] Updated tooltips for FileBacked Provider --- backend/src/main/resources/i18n/messages.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index a9a0560be..12c4337ec 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -679,7 +679,7 @@ tooltip.http-max-cache-entries=The maximum number of responses written to cache. tooltip.max-cache-entry-size=The maximum response body size that may be cached, in bytes. This attribute is incompatible with httpClientRef. tooltip.metadata-provider-name=Metadata Provider Name (for display on the Dashboard only) -tooltip.metadata-provider-type=Metadata Provider Type +tooltip.metadata-provider-type=The precise behavior of any element is controlled by the xsi:type attribute. This specifies the exact type of provider to use. tooltip.xml-id=Identifier for logging, identification for command line reload, etc. tooltip.metadata-url=The URL that the metadata is served from. tooltip.metadata-file=The absolute path to the local metadata file to be loaded. @@ -707,7 +707,7 @@ tooltip.expiration-warning-threshold=For each attempted metadata refresh (whethe tooltip.filter-name=Filter Name tooltip.enable-filter=Enable Filter? -tooltip.enable-service=Enable Service? +tooltip.enable-service=A boolean value representing whether or not this metadata should be enabled within the Shibboleth IDP UI. tooltip.min-cache-duration=The minimum duration for which metadata will be cached before it is refreshed. tooltip.max-cache-duration=The maximum duration for which metadata will be cached before it is refreshed. From e85430311f1cefa0e9e2f6cb266788b4453a7111 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 2 Aug 2022 08:41:03 -0700 Subject: [PATCH 19/57] Updated tooltips for DynamicHttp Provider --- backend/src/main/resources/i18n/messages.properties | 4 ++-- ui/public/assets/schema/provider/filebacked-http.schema.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 12c4337ec..c3912d507 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -721,8 +721,8 @@ tooltip.source-directory=Convenience mechanism for wiring a FilesystemLoadSaveMa tooltip.remove-idle-entity-data=Flag indicating whether idle metadata should be removed. tooltip.do-resolver-initialization=Initialize this resolver? In the case of Filesystem resolvers, this will cause the system to read the file and index the resolver. -tooltip.md-request-type=Options are 1) Metadata Query Protocol, 2) Regex. -tooltip.md-request-value=Content of the element. +tooltip.md-request-type=Constructs the metadata request URL based on 1) Metadata Query Protocol, or 2) Regex (a regular expression). +tooltip.md-request-value=Content of the element based on the Metadata Request URL Construction Type. tooltip.transform-ref=A reference to a transform function for the entityID. If used, the child element must be empty. tooltip.encoding-style=Determines whether and how the entityID value will be URL encoded prior to replacement. Allowed values are: 1) "none" - no encoding is performed, 2) "form" - encoded using URL form parameter encoding (for query parameters), 3) "path" - encoded using URL path encoding, or 4) "fragment" - encoded using URL fragment encoding. The precise definition of these terms is defined in the documentation for the methods of the Guava library\u0027s UrlEscapers class. tooltip.velocity-engine=This attribute may be used to specify the name of the Velocity engine defined within the application. diff --git a/ui/public/assets/schema/provider/filebacked-http.schema.json b/ui/public/assets/schema/provider/filebacked-http.schema.json index dffeaa65e..e1b0d95c7 100644 --- a/ui/public/assets/schema/provider/filebacked-http.schema.json +++ b/ui/public/assets/schema/provider/filebacked-http.schema.json @@ -42,8 +42,8 @@ "const": "FileBackedHttpMetadataResolver" }, "enabled": { - "title": "label.enable-service", - "description": "tooltip.enable-service", + "title": "label.enable-provider-upon-saving", + "description": "tooltip.enable-provider-upon-saving", "type": "boolean", "default": false }, From 4206633171fe5c92f9f1e5b66e9e1fec8e0e43bd Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 2 Aug 2022 14:24:07 -0700 Subject: [PATCH 20/57] Updated tooltips for Metadata Sources and filters --- .../main/resources/i18n/messages.properties | 75 ++++++++++--------- .../resources/metadata-sources-ui-schema.json | 2 +- .../component/fields/FilterTargetField.js | 4 +- .../wizard/MetadataFilterTypeSelector.js | 4 +- 4 files changed, 43 insertions(+), 42 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index c3912d507..8da49adb7 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -615,34 +615,35 @@ message.session-timeout-heading=Session timed out message.session-timeout-body=Your session has timed out. Please login again. message.session-timeout=An error has occurred while saving. Your session may have timed out. -tooltip.entity-id=Entity ID +tooltip.entity-id=An entityID is the SAML identifier that uniquely names a service provider. tooltip.service-provider-name=Service Provider Name (Dashboard Display Only) -tooltip.force-authn=Disallows use (or reuse) of authentication results and login flows that don\u0027t provide a real-time proof of user presence in the login process +tooltip.force-authn=Disallows use (or reuse) of authentication results and login flows that don\u0027t provide a real-time proof of user presence in the login process. tooltip.service-provider-name-dashboard-display-only=Service Provider Name (Dashboard Display Only) tooltip.service-provider-entity-id=Service Provider Entity ID -tooltip.organization-name=Organization Name -tooltip.organization-display-name=Organization Display Name -tooltip.organization-url=Organization URL +tooltip.organization-name=Name of the organization standing up the entity. +tooltip.organization-display-name=Name of the organization standing up the entity to be used for display purposes. +tooltip.organization-url=URL of the organization standing up the entity. tooltip.name=Name tooltip.type=Type tooltip.email-address=Email Address -tooltip.assertion-consumer-service-location=Assertion Consumer Service Location -tooltip.assertion-consumer-service-location-binding=Assertion Consumer Service Location Binding -tooltip.mark-as-default=Mark as Default -tooltip.protocol-support-enumeration=Protocol Support Enumeration -tooltip.nameid-format=Content is name identifier format which is added to all the applicable roles of the entities which match any of the following or {{}}elements. -tooltip.enable-this-service-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP +tooltip.assertion-consumer-service-location=Path used to invoke handler (when appended to the base handlerURL). +tooltip.assertion-consumer-service-location-binding=The binding attribute of the element is a standard URI specified in the SAML 2.0 Binding specification. +tooltip.assertion-consumer-service-endpoints=An Assertion Consumer Service (or ACS) is SAML terminology for the location at a ServiceProvider that accepts messages (or SAML artifacts) for the purpose of establishing a session based on an assertion. +tooltip.mark-as-default=Whether to mark this endpoint as the default by setting the "isDefault" property. +tooltip.protocol-support-enumeration=This attribute contains a space-delimited collection of URIs that represent general classes of protocol support for the role in question. There are URIs defined by the various standards and profiles to represent the fact that an entity acting in a role "supports" a particular protocol family, such as SAML 2.0 or the Shibboleth profile of SAML 1.1. +tooltip.nameid-format=Content is name identifier format which is added to all the applicable roles of the entities which match any of the following or elements. +tooltip.enable-this-service-upon-saving=If checkbox is clicked, the metadata is enabled for integration with the IdP tooltip.is-there-a-x509-certificate=Is there a X509 Certificate? -tooltip.authentication-requests-signed=Authentication Requests Signed -tooltip.want-assertions-signed=Want Assertions Signed -tooltip.certificate-name=Certificate Name -tooltip.certificate-type=Certificate Type -tooltip.certificate=Certificate -tooltip.logout-endpoints=Logout Endpoints -tooltip.logout-endpoints-url=Logout Endpoints Url -tooltip.logout-endpoints-binding-type=Logout Endpoints Binding Type -tooltip.url=Logout Endpoints Url -tooltip.binding-type=Logout Endpoints Binding Type +tooltip.authentication-requests-signed=Whether to sign requests. +tooltip.want-assertions-signed=Whether to sign assertions. Element declares that the service provider wants the element to be digitally signed. +tooltip.certificate-name=Value used by the IDP UI to identify certificates. +tooltip.certificate-type=Describes the use to which the credential will be put (as defined by the SAML standard) +tooltip.certificate=A certificate containing a public key to use to require and verify an XML signature over the resource. +tooltip.logout-endpoints=If your SP supports SAML 2.0 Single Logout, you will need to include one or more endpoint elements in the metadata. +tooltip.logout-endpoints-url=The location of the handler (when combined with the base handlerURL). This is the location to which an IdP sends messages using whatever protocol and binding it shares with the SP. Each combination of SLO protocol and binding is installed at a unique location to improve efficiency. +tooltip.logout-endpoints-binding-type=Identifies the protocol binding supported by the handler. Bindings describe how the message is packaged by the IdP (or by the browser in some cases) for consumption by the handler. +tooltip.url=The location of the handler (when combined with the base handlerURL). This is the location to which an IdP sends messages using whatever protocol and binding it shares with the SP. Each combination of SLO protocol and binding is installed at a unique location to improve efficiency. +tooltip.binding-type=Identifies the protocol binding supported by the handler. Bindings describe how the message is packaged by the IdP (or by the browser in some cases) for consumption by the handler. tooltip.mdui-display-name=Typically, the IdP Display Name field will be presented on IdP discovery service interfaces. tooltip.mdui-information-url=The IdP Information URL is a link to a comprehensive information page about the IdP. This page should expand on the content of the IdP Description field. tooltip.mdui-description=The IdP Description is a brief description of the IdP service. On a well-designed discovery interface, the IdP Description will be presented to the user in addition to the IdP Display Name, and so the IdP Description helps disambiguate duplicate or similar IdP Display Names. @@ -650,21 +651,21 @@ tooltip.mdui-privacy-statement-url=The IdP Privacy Statement URL is a link to th tooltip.mdui-logo-url=The IdP Logo URL in metadata points to an image file on a remote server. A discovery service, for example, may rely on a visual cue (i.e., a logo) instead of or in addition to the IdP Display Name. tooltip.mdui-logo-width=The logo should have a minimum width of 100 pixels tooltip.mdui-logo-height=The logo should have a minimum height of 75 pixels and a maximum height of 150 pixels (or the application will scale it proportionally) -tooltip.contact-name=Contact Name -tooltip.contact-type=Contact Type -tooltip.contact-email=Contact Email -tooltip.sign-assertion=Sign Assertion -tooltip.dont-sign-response=Don\u0027t Sign Response -tooltip.turn-off-encryption=Turn Off Encryption of Response -tooltip.usa-sha-algorithm=Use SHA1 Signing Algorithm -tooltip.authentication-methods-to-use=Authentication Methods to Use -tooltip.ignore-auth-method=Ignore any SP-Requested Authentication Method -tooltip.omit-not-before-condition=Omit Not Before Condition -tooltip.responder-id=ResponderId +tooltip.contact-name=The given name of the contact. +tooltip.contact-type=Type / role of the contact. +tooltip.contact-email=Email address of the contact. +tooltip.sign-assertion=Sign Assertion declares that the service provider wants the element to be digitally signed. +tooltip.dont-sign-response=Don\u0027t Sign Response. +tooltip.turn-off-encryption=Whether to turn off encryption of the response. +tooltip.usa-sha-algorithm=Whether to use the SHA1 Signing Algorithm. +tooltip.authentication-methods-to-use=The method used to authenticate the subject. +tooltip.ignore-auth-method=Whether to ignore any SP-Requested Authentication Method. +tooltip.omit-not-before-condition=Whether to include a NotBefore attribute in assertions. +tooltip.responder-id=Identifier of the selected SAML IdP entity. tooltip.instruction=Information icon tooltip.attribute-release-table=Attribute release table - select the attributes you want to release (default unchecked) tooltip.metadata-filter-name=Metadata Filter Name -tooltip.metadata-filter-type=Metadata Filter Type +tooltip.metadata-filter-type=The precise behavior of any element is controlled by the xsi:type attribute. tooltip.connection-request-timeout=The maximum amount of time to wait for a connection to be returned from the HTTP client\u0027s connection pool manager. Set to PT0S to disable. This attribute is incompatible with httpClientRef. tooltip.connection-timeout=The maximum amount of time to wait to establish a connection with the remote server. Set to PT0S to disable. This attribute is incompatible with httpClientRef. tooltip.socket-timeout=The maximum amount of time to wait between two consecutive packets while reading from the socket connected to the remote server. Set to PT0S to disable. This attribute is incompatible with httpClientRef. @@ -690,7 +691,7 @@ tooltip.require-valid-metadata=Whether candidate metadata found by the resolver tooltip.fail-fast-init=Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. tooltip.use-default-predicate-reg=Flag which determines whether the default CriterionPredicateRegistry will be used if a custom one is not supplied explicitly. tooltip.satisfy-any-predicates=Flag which determines whether predicates used in filtering are connected by a logical 'OR' (true) or by logical 'AND' (false). -tooltip.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP +tooltip.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP. tooltip.max-validity-interval=Defines the window within which the metadata is valid. tooltip.require-signed-root=If true, this fails to load metadata with no signature on the root XML element. @@ -706,9 +707,9 @@ tooltip.resolve-via-predicates-only=Flag indicating whether resolution may be pe tooltip.expiration-warning-threshold=For each attempted metadata refresh (whether or not fresh metadata is obtained), if requireValidMetadata is true, and there is a validUntil XML attribute on the document root element, and the difference between validUntil and the current time is less than expirationWarningThreshold, the system logs a warning about the impending expiration. tooltip.filter-name=Filter Name -tooltip.enable-filter=Enable Filter? +tooltip.enable-filter=If checkbox is clicked, the metadata filter is enabled for integration with the IdP. tooltip.enable-service=A boolean value representing whether or not this metadata should be enabled within the Shibboleth IDP UI. - +tooltip.search-by=Indicates the type of search to be performed. tooltip.min-cache-duration=The minimum duration for which metadata will be cached before it is refreshed. tooltip.max-cache-duration=The maximum duration for which metadata will be cached before it is refreshed. tooltip.max-idle-entity-data=The maximum duration for which metadata will be allowed to be idle (no requests for it) before it is removed from the cache. @@ -739,4 +740,4 @@ tooltip.group-description=Group Description tooltip.role-name=Role Name tooltip.role-description=Role Description -tooltip.contact-information=Contact Information \ No newline at end of file +tooltip.contact-information=Contacts provide information about how to contact the organization responsible for standing up the entity. \ No newline at end of file diff --git a/backend/src/main/resources/metadata-sources-ui-schema.json b/backend/src/main/resources/metadata-sources-ui-schema.json index 09abb43c1..2d64f96bb 100644 --- a/backend/src/main/resources/metadata-sources-ui-schema.json +++ b/backend/src/main/resources/metadata-sources-ui-schema.json @@ -102,7 +102,7 @@ }, "assertionConsumerServices": { "title": "label.assertion-consumer-service-endpoints", - "description": "", + "description": "tooltip.assertion-consumer-service-endpoints", "type": "array", "items": { "$ref": "#/definitions/AssertionConsumerService" diff --git a/ui/src/app/form/component/fields/FilterTargetField.js b/ui/src/app/form/component/fields/FilterTargetField.js index 0cdaa50ce..afb4f7828 100644 --- a/ui/src/app/form/component/fields/FilterTargetField.js +++ b/ui/src/app/form/component/fields/FilterTargetField.js @@ -145,7 +145,7 @@ const FilterTargetField = ({ @@ -170,7 +170,7 @@ const FilterTargetField = ({ - +
diff --git a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js index 09260c018..8318bbda1 100644 --- a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js +++ b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js @@ -41,8 +41,8 @@ export function MetadataFilterTypeSelector({ types = [], children, actions}) { - - + + Date: Tue, 2 Aug 2022 14:36:26 -0700 Subject: [PATCH 21/57] Updated tooltips for Groups and Roles --- .../main/resources/i18n/messages.properties | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 8da49adb7..0f22d95b6 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -152,21 +152,21 @@ heading.shibboleth=Shibboleth label.source-configuration=Metadata Source Configuration label.provider-configuration=Metadata Provider Configuration label.entity-attribute-name=Custom Entity Attribute Name -tooltip.entity-attribute-name=Custom Entity Attribute Name +tooltip.entity-attribute-name=Name of the attribute that the service provider uses and requires from the identity provider. It corresponds to the element in the SAML assertion. label.entity-attribute-type=Attribute Type -tooltip.entity-attribute-type=Attribute Type +tooltip.entity-attribute-type=Data type of the attribute such as boolean or string. label.entity-attribute-help=Help Text -tooltip.entity-attribute-help=Help Text +tooltip.entity-attribute-help=Defines help text used in the Shibboleth IDP UI when adding the attribute. label.entity-attribute-default=Default Value -tooltip.entity-attribute-default=Default Value +tooltip.entity-attribute-default=The default value of the attribute. label.entity-attribute-list-options=List options -tooltip.entity-attribute-list-options=List options +tooltip.entity-attribute-list-options=A list of pre-defined selectable options for a user to select from in the Shibboleth IDP UI. label.entity-attribute-friendly-name=Friendly name -tooltip.entity-attribute-friendly-name=Friendly name +tooltip.entity-attribute-friendly-name=A descriptive or human-friendly name for users of the Shibboleth IDP UI. label.entity-attribute-attr-name=Attribute name -tooltip.entity-attribute-attr-name=This is normally a uri or urn +tooltip.entity-attribute-attr-name=Indicates how to interpret the attribute name. It corresponds to the element in the SAML assertion. This is normally a uri or urn. label.entity-attribute-display-name=Display name -tooltip.entity-attribute-display-name=Display name +tooltip.entity-attribute-display-name=Provides a human readable value that identifies the subject. This value is not guaranteed to be unique and is designed to be used only for display purposes. label.entity-attribute-persist-value=Persist Value label.entity-attribute-persist-type=Persist Type @@ -508,7 +508,7 @@ label.source=Metadata Source label.provider=Metadata Provider label.url-validation-regex=URL validation regular expression -tooltip.url-validation-regex=URL validation regular expression +tooltip.url-validation-regex=URL validation regular expression. This is used by the Shibboleth IDP UI to restrict entities that may be targetted by this group and is added as form validation. label.bundle-name=Bundle name label.bundle-disp=Bundle - {name} @@ -734,10 +734,10 @@ tooltip.nameid-formats-format=Format tooltip.nameid-formats-value=Value tooltip.nameid-formats-type=Type -tooltip.group-name=Group Name -tooltip.group-description=Group Description +tooltip.group-name=A user friendly name used to identify the group. +tooltip.group-description=A description of the purpose of the group. -tooltip.role-name=Role Name -tooltip.role-description=Role Description +tooltip.role-name=A user friendly name used to identify the role. +tooltip.role-description=A description of the purpose of the role. tooltip.contact-information=Contacts provide information about how to contact the organization responsible for standing up the entity. \ No newline at end of file From d054c4c20f2d8918b27d92c58ea81b2010e55761 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 2 Aug 2022 14:59:52 -0700 Subject: [PATCH 22/57] Fixed issue with scrollbar on dashboard --- .../domain/provider/component/ProviderList.js | 151 +++++++++--------- .../domain/source/component/SourceList.js | 9 +- 2 files changed, 83 insertions(+), 77 deletions(-) diff --git a/ui/src/app/metadata/domain/provider/component/ProviderList.js b/ui/src/app/metadata/domain/provider/component/ProviderList.js index 1b367a69d..9a9ac90d4 100644 --- a/ui/src/app/metadata/domain/provider/component/ProviderList.js +++ b/ui/src/app/metadata/domain/provider/component/ProviderList.js @@ -18,83 +18,86 @@ export function ProviderList({ children, entities, reorder = true, first, last, const translator = useTranslator(); return ( - - {(limited) =>
- - - - - - - - - - - - - {limited.map((provider, idx) => - - + + )} + +
OrderTitleProvider TypeAuthorCreated DateEnabled
-
- {reorder ? -
{idx + 1}
+ + + {(limited) =>
+ + + + + + + + + + + + + {limited.map((provider, idx) => + + + + + + + - - - - - - - )} - -
OrderTitleProvider TypeAuthorCreated DateEnabled
+
+ {reorder ? +
{idx + 1}
+ : +
+ } +   + + +
+
+ {provider.name} + { provider['@type'] }{ provider.createdBy } + + {onEnable && isAdmin ? + onEnable(provider, checked)} + checked={provider.enabled} + > + : -
+ + + } -   - - - -
- {provider.name} - { provider['@type'] }{ provider.createdBy } - - {onEnable && isAdmin ? - onEnable(provider, checked)} - checked={provider.enabled} - > - - : - - - - } - -
+ +
+
+ } +
{children} -
- } - + + ); } diff --git a/ui/src/app/metadata/domain/source/component/SourceList.js b/ui/src/app/metadata/domain/source/component/SourceList.js index 42af027dd..8e8a10825 100644 --- a/ui/src/app/metadata/domain/source/component/SourceList.js +++ b/ui/src/app/metadata/domain/source/component/SourceList.js @@ -23,7 +23,8 @@ export default function SourceList({ entities, onDelete, onEnable, onChangeGroup const canEnable = useCanEnable(); return ( - + + {(limited) =>
@@ -122,9 +123,11 @@ export default function SourceList({ entities, onDelete, onEnable, onChangeGroup
- {children}
} -
+
+ {children} + + ); } From 0658d872ce1104e6147020ebc5b7c4a005b44713 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 2 Aug 2022 19:15:09 -0400 Subject: [PATCH 23/57] SHIBUI-1978 Small test tweak for stability. --- .../integration/resources/SHIBUI-1732-4.side | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/backend/src/integration/resources/SHIBUI-1732-4.side b/backend/src/integration/resources/SHIBUI-1732-4.side index 6aab66e67..214a49cbd 100644 --- a/backend/src/integration/resources/SHIBUI-1732-4.side +++ b/backend/src/integration/resources/SHIBUI-1732-4.side @@ -992,6 +992,13 @@ ["xpath=//div[3]/div/div/div[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "14c486b1-bdff-4474-94e3-b4286303a8fd", + "comment": "", + "command": "pause", + "target": "5000", + "targets": [], + "value": "" }, { "id": "e3892564-1a1b-4ee6-bbab-49d3cb3079d7", "comment": "", @@ -999,21 +1006,21 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" - },{ - "id": "4ec2c493-85e4-403b-9b09-031c5728f498", - "comment": "", - "command": "open", - "target": "/api/heheheheheheheWipeout", - "targets": [], - "value": "" - }, { - "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", - "comment": "", - "command": "assertText", - "target": "css=body", - "targets": [], - "value": "yes, you did it" - }] + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "575d414c-556d-45f7-b2f2-c9971ad51348", From 2b6fd1da92221d20a85b03afb7ec3d793fb24dd6 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 4 Aug 2022 11:32:22 -0700 Subject: [PATCH 24/57] Set popover icons to placement auto --- ui/src/app/form/component/InfoIcon.js | 2 +- ui/src/app/form/component/fields/DescriptionField.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/app/form/component/InfoIcon.js b/ui/src/app/form/component/InfoIcon.js index 209e4f426..a9dbb9363 100644 --- a/ui/src/app/form/component/InfoIcon.js +++ b/ui/src/app/form/component/InfoIcon.js @@ -7,7 +7,7 @@ import Button from 'react-bootstrap/Button'; import Translate from '../../i18n/components/translate'; import { useTranslator } from '../../i18n/hooks'; -export function InfoIcon ({ value = '', placement='left', ...props }) { +export function InfoIcon ({ value = '', placement='auto', ...props }) { const translate = useTranslator(); return( { if (description) { - return ; + return ; } return null; From e9be73f2c7768c9dd30afe0abd99d4f0a34f5ce6 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Fri, 5 Aug 2022 08:49:47 -0400 Subject: [PATCH 25/57] added ignoreRequestSignatures --- backend/src/main/resources/application.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index ffeab970c..bf1367934 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -156,4 +156,10 @@ custom: displayType: boolean helpText: tooltip.force-authn attributeName: http://shibboleth.net/ns/profiles/forceAuthn - attributeFriendlyName: forceAuthn \ No newline at end of file + attributeFriendlyName: forceAuthn + - name: ignoreRequestSignatures + displayName: label.ignore-request-signatures + displayType: boolean + helpText: tooltip.ignore-request-signatures + attributeName: http://shibboleth.net/ns/profiles/ignoreRequestSignatures + attributeFriendlyName: ignoreRequestSignatures \ 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 26/57] 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 27/57] 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 28/57] 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 29/57] 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