[java-shib-metadata] branch main updated: OSJ-439 - Add options for removal to Algorithm metadata filter
Codeberg
noreply at shibboleth.net
Wed Jan 21 18:17:04 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-shib-metadata.
View the commit online:
https://codeberg.org/Shibboleth/java-shib-metadata/commit/8b7d844c0cd75a3af804e81ed615df01543393f3
The following commit(s) were added to refs/heads/main by this push:
new 8b7d844c OSJ-439 - Add options for removal to Algorithm metadata filter
8b7d844c is described below
commit 8b7d844c0cd75a3af804e81ed615df01543393f3
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Jan 21 13:16:52 2026 -0500
OSJ-439 - Add options for removal to Algorithm metadata filter
https://shibboleth.atlassian.net/browse/OSJ-439
Add removal support to schema and Spring parser.
Add unit test.
---
.../metadata/filter/AlgorithmFilterParser.java | 20 +++-
.../main/resources/schema/shibboleth-metadata.xsd | 21 ++++
.../metadata/filter/AlgorithmFilterParserTest.java | 111 +++++++++++++--------
.../metadata/filter/algorithmRemovalOnly.xml | 83 +++++++++++++++
4 files changed, 195 insertions(+), 40 deletions(-)
diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParser.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParser.java
index 76d62d06..82bb8990 100644
--- a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParser.java
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParser.java
@@ -42,6 +42,7 @@ import org.w3c.dom.Element;
import net.shibboleth.shared.logic.ScriptedPredicate;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.spring.util.SpringSupport;
import net.shibboleth.shared.xml.ElementSupport;
import net.shibboleth.spring.ScriptTypeBeanParser;
import net.shibboleth.spring.metadata.AbstractMetadataProviderParser;
@@ -70,8 +71,25 @@ public class AlgorithmFilterParser extends AbstractMetadataFilterParser {
/** {@inheritDoc} */
@Override protected void doParse(@Nonnull final Element element, @Nonnull final ParserContext parserContext,
@Nonnull final BeanDefinitionBuilder builder) {
-
super.doParse(element, parserContext, builder);
+
+ if (element.hasAttributeNS(null, "removeExistingDigestMethods")) {
+ builder.addPropertyValue("removeExistingDigestMethods",
+ SpringSupport.getStringValueAsBoolean(element.getAttributeNS(null,
+ "removeExistingDigestMethods")));
+ }
+
+ if (element.hasAttributeNS(null, "removeExistingSigningMethods")) {
+ builder.addPropertyValue("removeExistingSigningMethods",
+ SpringSupport.getStringValueAsBoolean(element.getAttributeNS(null,
+ "removeExistingSigningMethods")));
+ }
+
+ if (element.hasAttributeNS(null, "removeExistingEncryptionMethods")) {
+ builder.addPropertyValue("removeExistingEncryptionMethods",
+ SpringSupport.getStringValueAsBoolean(element.getAttributeNS(null,
+ "removeExistingEncryptionMethods")));
+ }
final Unmarshaller digestUnmarshaller = XMLObjectSupport.getUnmarshaller(DigestMethod.DEFAULT_ELEMENT_NAME);
final Unmarshaller signingUnmarshaller =XMLObjectSupport.getUnmarshaller(SigningMethod.DEFAULT_ELEMENT_NAME);
diff --git a/shib-metadata-spring/src/main/resources/schema/shibboleth-metadata.xsd b/shib-metadata-spring/src/main/resources/schema/shibboleth-metadata.xsd
index cbee4b70..5bb023c5 100644
--- a/shib-metadata-spring/src/main/resources/schema/shibboleth-metadata.xsd
+++ b/shib-metadata-spring/src/main/resources/schema/shibboleth-metadata.xsd
@@ -1399,6 +1399,27 @@
</element>
</choice>
</sequence>
+ <attribute name="removeExistingDigestMethods" type="boolean">
+ <annotation>
+ <documentation>
+ Whether to remove any existing DigestMethods when adding new ones (default is false).
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="removeExistingSigningMethods" type="boolean">
+ <annotation>
+ <documentation>
+ Whether to remove any existing SigningMethods when adding new ones (default is false).
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="removeExistingEncryptionMethods" type="boolean">
+ <annotation>
+ <documentation>
+ Whether to remove any existing EncryptionMethods when adding new ones (default is false).
+ </documentation>
+ </annotation>
+ </attribute>
</extension>
</complexContent>
</complexType>
diff --git a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParserTest.java b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParserTest.java
index 04043d7c..b3f3f0a6 100644
--- a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParserTest.java
+++ b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/AlgorithmFilterParserTest.java
@@ -46,25 +46,30 @@ public class AlgorithmFilterParserTest extends AbstractMetadataParserTest {
@Test
public void test() throws ResolverException, IOException {
- doTest("filter/algorithm.xml");
+ doTest(false, "filter/algorithm.xml");
}
+ @Test
+ public void testRemovalOnly() throws ResolverException, IOException {
+ doTest(true, "filter/algorithmRemovalOnly.xml");
+ }
+
@Test
public void testRegex() throws ResolverException, IOException {
- doTest("filter/algorithmRegex.xml");
+ doTest(false, "filter/algorithmRegex.xml");
}
@Test
public void testFilterScript() throws ResolverException, IOException {
- doTest("filter/algorithmWithScript.xml");
+ doTest(false, "filter/algorithmWithScript.xml");
}
@Test
public void testFilterScriptResource() throws ResolverException, IOException {
- doTest("filter/algorithmWithScriptResource.xml");
+ doTest(false, "filter/algorithmWithScriptResource.xml");
}
- private void doTest(final String... files) throws ResolverException, IOException {
+ private void doTest(boolean removal, final String... files) throws ResolverException, IOException {
final MetadataResolver resolver = getBean(MetadataResolver.class, files);
@@ -73,12 +78,12 @@ public class AlgorithmFilterParserTest extends AbstractMetadataParserTest {
EntityIdCriterion crit = new EntityIdCriterion("https://sp.example.org/sp/shibboleth");
EntityDescriptor entity = resolver.resolveSingle(new CriteriaSet(crit));
- validate(entity);
+ validate(entity, removal);
crit = new EntityIdCriterion("https://sp4.example.org/sp/shibboleth");
entity = resolver.resolveSingle(new CriteriaSet(crit));
if (entity != null) {
- validate(entity);
+ validate(entity, removal);
}
crit = new EntityIdCriterion("https://sp2.example.org/sp/shibboleth");
@@ -86,45 +91,73 @@ public class AlgorithmFilterParserTest extends AbstractMetadataParserTest {
Assert.assertNotNull(entity);
assert entity != null;
final Extensions exts = entity.getExtensions();
- if (exts != null) {
- Assert.assertTrue(exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME).isEmpty());
- Assert.assertTrue(exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ // This test looks backwards because normally they're not added but when testing
+ // removal they're left in place.
+ if (removal) {
+ assert exts != null;
+ Assert.assertEquals(exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME).size(), 2);
+ Assert.assertEquals(exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME).size(), 2);
+ } else {
+ if (exts != null) {
+ Assert.assertTrue(exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ Assert.assertTrue(exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ }
}
}
- private void validate(final EntityDescriptor entity) {
- final Extensions exts = entity.getExtensions();
- assert exts != null;
-
- List<XMLObject> extElements = exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME);
- assertEquals(extElements.size(), 2);
+ private void validate(final EntityDescriptor entity, boolean removal) {
+ Extensions exts = entity.getExtensions();
- Iterator<XMLObject> digests = extElements.iterator();
- assertEquals(((DigestMethod) digests.next()).getAlgorithm(), SignatureConstants.ALGO_ID_DIGEST_SHA256);
- assertEquals(((DigestMethod) digests.next()).getAlgorithm(), SignatureConstants.ALGO_ID_DIGEST_SHA512);
-
- extElements = exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME);
- assertEquals(extElements.size(), 2);
+ if (removal ) {
+ if (exts != null) {
+ Assert.assertTrue(exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ Assert.assertTrue(exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ }
+ } else {
+ assert exts != null;
+ List<XMLObject> extElements = exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME);
+ assertEquals(extElements.size(), 2);
+
+ Iterator<XMLObject> digests = extElements.iterator();
+ assertEquals(((DigestMethod) digests.next()).getAlgorithm(), SignatureConstants.ALGO_ID_DIGEST_SHA256);
+ assertEquals(((DigestMethod) digests.next()).getAlgorithm(), SignatureConstants.ALGO_ID_DIGEST_SHA512);
+
+ extElements = exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME);
+ assertEquals(extElements.size(), 2);
+
+ Iterator<XMLObject> signings = extElements.iterator();
+ assertEquals(((SigningMethod) signings.next()).getAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
+ assertEquals(((SigningMethod) signings.next()).getAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512);
+ }
- Iterator<XMLObject> signings = extElements.iterator();
- assertEquals(((SigningMethod) signings.next()).getAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
- assertEquals(((SigningMethod) signings.next()).getAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512);
-
for (final RoleDescriptor role : entity.getRoleDescriptors()) {
+
+ if (removal) {
+ exts = role.getExtensions();
+ if (exts != null) {
+ Assert.assertTrue(exts.getUnknownXMLObjects(DigestMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ Assert.assertTrue(exts.getUnknownXMLObjects(SigningMethod.DEFAULT_ELEMENT_NAME).isEmpty());
+ }
+ }
+
for (final KeyDescriptor key : role.getKeyDescriptors()) {
- final List<EncryptionMethod> methods = key.getEncryptionMethods();
- assertEquals(methods.size(), 1);
- assertEquals(methods.get(0).getAlgorithm(), EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11);
-
- final List<XMLObject> encDigests = methods.get(0).getUnknownXMLObjects(
- org.opensaml.xmlsec.signature.DigestMethod.DEFAULT_ELEMENT_NAME);
- assertEquals(encDigests.size(), 1);
- assertEquals(((org.opensaml.xmlsec.signature.DigestMethod) encDigests.get(0)).getAlgorithm(),
- SignatureConstants.ALGO_ID_DIGEST_SHA256);
-
- final List<XMLObject> mgfs = methods.get(0).getUnknownXMLObjects(MGF.DEFAULT_ELEMENT_NAME);
- assertEquals(mgfs.size(), 1);
- assertEquals(((MGF) mgfs.get(0)).getAlgorithm(), EncryptionConstants.ALGO_ID_MGF1_SHA256);
+ if (removal) {
+ Assert.assertTrue(key.getEncryptionMethods().isEmpty());
+ } else {
+ final List<EncryptionMethod> methods = key.getEncryptionMethods();
+ assertEquals(methods.size(), 1);
+ assertEquals(methods.get(0).getAlgorithm(), EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11);
+
+ final List<XMLObject> encDigests = methods.get(0).getUnknownXMLObjects(
+ org.opensaml.xmlsec.signature.DigestMethod.DEFAULT_ELEMENT_NAME);
+ assertEquals(encDigests.size(), 1);
+ assertEquals(((org.opensaml.xmlsec.signature.DigestMethod) encDigests.get(0)).getAlgorithm(),
+ SignatureConstants.ALGO_ID_DIGEST_SHA256);
+
+ final List<XMLObject> mgfs = methods.get(0).getUnknownXMLObjects(MGF.DEFAULT_ELEMENT_NAME);
+ assertEquals(mgfs.size(), 1);
+ assertEquals(((MGF) mgfs.get(0)).getAlgorithm(), EncryptionConstants.ALGO_ID_MGF1_SHA256);
+ }
}
}
}
diff --git a/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/filter/algorithmRemovalOnly.xml b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/filter/algorithmRemovalOnly.xml
new file mode 100644
index 00000000..54169e33
--- /dev/null
+++ b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/filter/algorithmRemovalOnly.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata:MetadataProvider xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:metadata="urn:mace:shibboleth:2.0:metadata"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ 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: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 http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0.xsd
+ http://www.w3.org/2009/xmlenc11# http://www.w3.org/TR/2013/REC-xmlenc-core1-20130411/xenc-schema-11.xsd"
+
+ failFastInitialization="false" requireValidMetadata="false"
+
+ id="algorithms" xsi:type="metadata:InlineMetadataProvider">
+
+ <metadata:MetadataFilter xsi:type="metadata:Algorithm"
+ removeExistingDigestMethods="true"
+ removeExistingSigningMethods="true">
+ <metadata:Entity>https://sp.example.org/sp/shibboleth</metadata:Entity>
+ <metadata:Entity>https://sp3.example.org/sp/shibboleth</metadata:Entity>
+ <metadata:Entity>https://sp4.example.org/sp/shibboleth</metadata:Entity>
+ <metadata:ConditionScript language="javascript">
+ <metadata:Script>input.getEntityID().equals("https://sp3.example.org/sp/shibboleth");</metadata:Script>
+ </metadata:ConditionScript>
+ </metadata:MetadataFilter>
+
+ <EntitiesDescriptor Name="ukgroup">
+ <EntityDescriptor
+ entityID="https://sp.example.org/sp/shibboleth">
+ <Extensions>
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" />
+ </Extensions>
+ <SPSSODescriptor
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <AssertionConsumerService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
+ Location="https://sp.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"
+ index="5" />
+ </SPSSODescriptor>
+ </EntityDescriptor>
+
+ <EntityDescriptor
+ entityID="https://sp2.example.org/sp/shibboleth">
+ <Extensions>
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" />
+ </Extensions>
+ <SPSSODescriptor
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <AssertionConsumerService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
+ Location="https://sp2.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"
+ index="5" />
+ </SPSSODescriptor>
+ </EntityDescriptor>
+
+ <EntityDescriptor
+ entityID="https://sp4.example.org/sp/shibboleth">
+ <Extensions>
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
+ <alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
+ <alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" />
+ </Extensions>
+ <SPSSODescriptor
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <AssertionConsumerService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
+ Location="https://sp4.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"
+ index="5" />
+ </SPSSODescriptor>
+ </EntityDescriptor>
+ </EntitiesDescriptor>
+</metadata:MetadataProvider>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list