[java-shib-metadata] branch main updated: JSMD-14 - Filter to add/remove Scope extension

Codeberg noreply at shibboleth.net
Wed Jan 21 15:46:19 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/852efc140f6ef29e5cf4f7a9e395da9677b4ec36

The following commit(s) were added to refs/heads/main by this push:
     new 852efc14 JSMD-14 - Filter to add/remove Scope extension
852efc14 is described below

commit 852efc140f6ef29e5cf4f7a9e395da9677b4ec36
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Jan 21 10:39:53 2026 -0500

    JSMD-14 - Filter to add/remove Scope extension
    
    https://shibboleth.atlassian.net/browse/JSMD-14
    
    Switch filter back to adding extensions at top level and not roles.
---
 .../idp/saml/metadata/impl/ScopeFilter.java        | 70 ++++++++++-----------
 .../idp/saml/metadata/impl/ScopeFilterTest.java    | 73 ++++++++++------------
 .../metadata/filter/ScopeFilterParserTest.java     | 48 +++++++-------
 3 files changed, 94 insertions(+), 97 deletions(-)

diff --git a/shib-metadata-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilter.java b/shib-metadata-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilter.java
index 14317469..11c0c722 100644
--- a/shib-metadata-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilter.java
+++ b/shib-metadata-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilter.java
@@ -46,15 +46,14 @@ import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
- * A filter that adds the {@link Scope} extension to roles in order to drive software
+ * A filter that adds the {@link Scope} extension to entities in order to drive software
  * behavior based on them.
  * 
  * <p>The entities to annotate are identified with a {@link Predicate}, and multiple scopes can be
  * associated with each, with and without the regexp flag.</p>
  * 
- * <p>Note that this filter only operates on extensions defined at the {@link RoleDescriptor} level.
- * When removing existing extensions, it will strip any found at both the top level and on each role.
- * All roles are modified, regardless of type, though this is not always sensible.</p>
+ * <p>Note that this filter only operates on extensions defined at the {@link EntityDescriptor} level.
+ * When removing existing extensions, it will strip any found at both the top level and on each role.</p>
  * 
  * @since 5.2.0
  */
@@ -138,6 +137,7 @@ public class ScopeFilter extends AbstractMetadataFilter {
         return metadata;
     }
     
+// Checkstyle: CyclomaticComplexity OFF
     /**
      * Filters entity descriptor.
      * 
@@ -146,9 +146,8 @@ public class ScopeFilter extends AbstractMetadataFilter {
     protected void filterEntityDescriptor(@Nonnull final EntityDescriptor descriptor) {
         for (final Map.Entry<Predicate<EntityDescriptor>,Collection<Scope>> entry : applyMap.asMap().entrySet()) {
             if (entry.getKey().test(descriptor)) {
-                // Since we only add to the roles, we need to delete anything at the entity level.
+                Extensions exts = descriptor.getExtensions();
                 if (removeExistingScopes) {
-                    final Extensions exts = descriptor.getExtensions();
                     if (exts != null) {
                         final Collection<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
                         if (!scopes.isEmpty()) {
@@ -157,14 +156,37 @@ public class ScopeFilter extends AbstractMetadataFilter {
                             scopes.clear();
                         }
                     }
+                    for (final RoleDescriptor role : descriptor.getRoleDescriptors()) {
+                        assert role != null;
+                        filterRoleDescriptor(role);
+                    }
                 }
-                for (final RoleDescriptor role : descriptor.getRoleDescriptors()) {
-                    assert role != null;
-                    filterRoleDescriptor(role, entry.getValue());
+                
+                for (final Scope scope : entry.getValue()) {
+                    if (GUARD_VALUE.equals(scope.getValue())) {
+                        // Skip guard value for empty collections.
+                        continue;
+                    }
+                    
+                    if (exts == null) {
+                        // Need to add Extensions element.
+                        exts = extBuilder.buildObject();
+                        descriptor.setExtensions(exts);
+                    }
+
+                    try {
+                        log.info("Adding Scope '{}' to EntityDescriptor '{}'", scope.getValue(),
+                                descriptor.getEntityID());
+                        exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).add(
+                                XMLObjectSupport.cloneXMLObject(scope));
+                    } catch (final MarshallingException | UnmarshallingException e) {
+                        log.error("Error cloning Scope", e);
+                    }
                 }
             }
         }
     }
+// Checkstyle: CyclomaticComplexity ON
             
     /**
      * Filters entities descriptor.
@@ -187,12 +209,11 @@ public class ScopeFilter extends AbstractMetadataFilter {
     }
 
     /**
-     * Filters role descriptor.
+     * Filters role descriptor to remove extensions.
      * 
      * @param role role descriptor to filter
-     * @param scopes scopes to add
      */
-    protected void filterRoleDescriptor(@Nonnull final RoleDescriptor role, @Nonnull final Collection<Scope> scopes) {
+    protected void filterRoleDescriptor(@Nonnull final RoleDescriptor role) {
         final String entityID;
         if (role.getParent() instanceof EntityDescriptor entity) {
             entityID = entity.getEntityID();
@@ -200,33 +221,12 @@ public class ScopeFilter extends AbstractMetadataFilter {
             entityID = null;
         }
         
-        Extensions exts = role.getExtensions();
-        if (exts != null && removeExistingScopes) {
+        final Extensions exts = role.getExtensions();
+        if (exts != null && !exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty()) {
             log.debug("Removing existing Scope extensions from {} role in EntityDescriptor '{}'",
                     role.getElementQName(), entityID);
             exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).clear();
         }
-        
-        for (final Scope scope : scopes) {
-            if (GUARD_VALUE.equals(scope.getValue())) {
-                // Skip guard value for empty collections.
-                continue;
-            }
-            
-            if (exts == null) {
-                // Need to add Extensions element.
-                exts = extBuilder.buildObject();
-                role.setExtensions(exts);
-            }
-
-            try {
-                log.info("Adding Scope '{}' to {} role in EntityDescriptor '{}'", scope.getValue(),
-                        role.getElementQName(), entityID);
-                exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).add(XMLObjectSupport.cloneXMLObject(scope));
-            } catch (final MarshallingException | UnmarshallingException e) {
-                log.error("Error cloning Scope", e);
-            }
-        }
     }
     
 }
\ No newline at end of file
diff --git a/shib-metadata-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilterTest.java b/shib-metadata-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilterTest.java
index 63192a73..d114df96 100644
--- a/shib-metadata-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilterTest.java
+++ b/shib-metadata-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/ScopeFilterTest.java
@@ -92,29 +92,26 @@ public class ScopeFilterTest extends XMLObjectBaseTestCase implements Predicate<
         EntityDescriptor entity = metadataProvider.resolveSingle(new CriteriaSet(key));
         assert entity != null;
      
+        Extensions exts = entity.getExtensions();
+        assert exts != null;
+        final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
+        Assert.assertEquals(scopes.size(), 2);
+        if (scopes.get(0) instanceof Scope s) {
+            Assert.assertEquals(s.getValue(), "scope1.org");
+            Assert.assertEquals(s.getRegexp(), true);
+        } else {
+            Assert.fail("Scope was of unexpected type");
+        }
+        if (scopes.get(1) instanceof Scope s) {
+            Assert.assertEquals(s.getValue(), "scope2.org");
+            Assert.assertEquals(s.getRegexp(), false);
+        } else {
+            Assert.fail("Scope was of unexpected type");
+        }
+        
         for (final RoleDescriptor role : entity.getRoleDescriptors()) {
-            final Extensions exts = role.getExtensions();
-            assert exts != null;
-            final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
-            Assert.assertEquals(scopes.size(), 3);
-            if (scopes.get(0) instanceof Scope s) {
-                Assert.assertEquals(s.getValue(), "osu.edu");
-                Assert.assertEquals(s.getRegexp(), false);
-            } else {
-                Assert.fail("Scope was of unexpected type");
-            }
-            if (scopes.get(1) instanceof Scope s) {
-                Assert.assertEquals(s.getValue(), "scope1.org");
-                Assert.assertEquals(s.getRegexp(), true);
-            } else {
-                Assert.fail("Scope was of unexpected type");
-            }
-            if (scopes.get(2) instanceof Scope s) {
-                Assert.assertEquals(s.getValue(), "scope2.org");
-                Assert.assertEquals(s.getRegexp(), false);
-            } else {
-                Assert.fail("Scope was of unexpected type");
-            }
+            exts = role.getExtensions();
+            Assert.assertTrue(exts != null && exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).size() == 1);
         }
     }
 
@@ -163,27 +160,25 @@ public class ScopeFilterTest extends XMLObjectBaseTestCase implements Predicate<
         assert entity != null;
         
         Extensions exts = entity.getExtensions();
-        if (exts != null) {
-            Assert.assertTrue(exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty());
+        assert exts != null;
+        final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
+        Assert.assertEquals(scopes.size(), 2);
+        if (scopes.get(0) instanceof Scope s) {
+            Assert.assertEquals(s.getValue(), "scope1.org");
+            Assert.assertEquals(s.getRegexp(), true);
+        } else {
+            Assert.fail("Scope was of unexpected type");
+        }
+        if (scopes.get(1) instanceof Scope s) {
+            Assert.assertEquals(s.getValue(), "scope2.org");
+            Assert.assertEquals(s.getRegexp(), false);
+        } else {
+            Assert.fail("Scope was of unexpected type");
         }
 
         for (final RoleDescriptor role : entity.getRoleDescriptors()) {
             exts = role.getExtensions();
-            assert exts != null;
-            final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
-            Assert.assertEquals(scopes.size(), 2);
-            if (scopes.get(0) instanceof Scope s) {
-                Assert.assertEquals(s.getValue(), "scope1.org");
-                Assert.assertEquals(s.getRegexp(), true);
-            } else {
-                Assert.fail("Scope was of unexpected type");
-            }
-            if (scopes.get(1) instanceof Scope s) {
-                Assert.assertEquals(s.getValue(), "scope2.org");
-                Assert.assertEquals(s.getRegexp(), false);
-            } else {
-                Assert.fail("Scope was of unexpected type");
-            }
+            Assert.assertTrue(exts == null || exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty());
         }
         
     }
diff --git a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/ScopeFilterParserTest.java b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/ScopeFilterParserTest.java
index 09150598..e3f312e0 100644
--- a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/ScopeFilterParserTest.java
+++ b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/filter/ScopeFilterParserTest.java
@@ -37,16 +37,16 @@ import org.testng.annotations.Test;
 @SuppressWarnings("javadoc")
 public class ScopeFilterParserTest extends AbstractMetadataParserTest {
 
-    @Test
-    public void testRemoveOnly() throws ResolverException, IOException {
-        doTest(true, "filter/scopeRemoveOnly.xml");
-    }
-    
     @Test
     public void test() throws ResolverException, IOException {
         doTest(false, "filter/scope.xml");
     }
 
+    @Test
+    public void testRemoveOnly() throws ResolverException, IOException {
+        doTest(true, "filter/scopeRemoveOnly.xml");
+    }
+    
     private void doTest(boolean removed, final String... files) throws ResolverException, IOException {
 
         final MetadataResolver resolver = getBean(MetadataResolver.class, files);
@@ -75,25 +75,27 @@ public class ScopeFilterParserTest extends AbstractMetadataParserTest {
     }
     
     private void validate(final EntityDescriptor entity, boolean removed) {
+        
+        Extensions exts = entity.getExtensions();
+        if (removed) {
+            Assert.assertTrue(exts == null || exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty());
+        } else {
+            final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
+            
+            assertEquals(scopes.size(), 2);
+            
+            final Scope scope1 = (Scope) scopes.get(0);
+            Assert.assertEquals(scope1.getValue(), "example.org");
+            Assert.assertEquals(scope1.getRegexp(), false);
+
+            final Scope scope2 = (Scope) scopes.get(1);
+            Assert.assertEquals(scope2.getValue(), "sub.example.org");
+            Assert.assertEquals(scope2.getRegexp(), true);
+        }
+        
         for (final RoleDescriptor role : entity.getRoleDescriptors()) {
-            final Extensions exts = role.getExtensions();
-            if (removed) {
-                Assert.assertTrue(exts == null || exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty());
-            } else {
-                assert exts != null;
-                
-                final List<XMLObject> scopes = exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME);
-                
-                assertEquals(scopes.size(), 2);
-                
-                final Scope scope1 = (Scope) scopes.get(0);
-                Assert.assertEquals(scope1.getValue(), "example.org");
-                Assert.assertEquals(scope1.getRegexp(), false);
-    
-                final Scope scope2 = (Scope) scopes.get(1);
-                Assert.assertEquals(scope2.getValue(), "sub.example.org");
-                Assert.assertEquals(scope2.getRegexp(), true);
-            }
+            exts = role.getExtensions();
+            Assert.assertTrue(exts == null || exts.getUnknownXMLObjects(Scope.DEFAULT_ELEMENT_NAME).isEmpty());
         }        
     }
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list