[java-shib-attribute] 02/02: JSATTR-39 Implement wildcard support in attribute filter
Rod Widdowson
rdw at steadingsoftware.com
Thu Apr 17 15:23:19 UTC 2025
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch main
in repository java-shib-attribute.
View the commit online:
http://git.shibboleth.net/view/?p=java-shib-attribute.git;a=commit;h=a033b3b3b5597ed913f5019c85037d436a1b6159
commit a033b3b3b5597ed913f5019c85037d436a1b6159
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Thu Apr 17 16:22:26 2025 +0100
JSATTR-39 Implement wildcard support in attribute filter
https://shibboleth.atlassian.net/browse/JSATTR-39
Implement default processing with test.
---
.../filter/context/AttributeFilterContext.java | 19 +++
.../attribute/filter/impl/AttributeFilterImpl.java | 22 +++-
.../filter/impl/AttributeFilterImplTest.java | 139 +++++++++++++++++++++
3 files changed, 179 insertions(+), 1 deletion(-)
diff --git a/shib-attribute-filter-api/src/main/java/net/shibboleth/idp/attribute/filter/context/AttributeFilterContext.java b/shib-attribute-filter-api/src/main/java/net/shibboleth/idp/attribute/filter/context/AttributeFilterContext.java
index 3c0ad4c46..ee507a4ed 100644
--- a/shib-attribute-filter-api/src/main/java/net/shibboleth/idp/attribute/filter/context/AttributeFilterContext.java
+++ b/shib-attribute-filter-api/src/main/java/net/shibboleth/idp/attribute/filter/context/AttributeFilterContext.java
@@ -87,6 +87,9 @@ public final class AttributeFilterContext extends BaseContext {
/** The attribute recipient's group identity. */
@Nullable private String attributeRecipientGroupID;
+ /** Do we include unfiltered attributes into the resolution? */
+ private boolean includeUnfilteredAttributes;
+
/** Cache of issuer metadata context. */
@Nullable private SAMLMetadataContext issuerMetadataContext;
@@ -154,6 +157,22 @@ public final class AttributeFilterContext extends BaseContext {
return this;
}
+
+ /**
+ * Will we include unfiltered attributes in the result?
+ * @return whether unfilter attributes are to be included
+ */
+ public boolean isIncludeUnfilteredAttributes() {
+ return includeUnfilteredAttributes;
+ }
+
+ /**
+ * Control whether we will include unfiltered attributes in the result.
+ * @param what if true then we will include unfiltered attributes in the result
+ */
+ public void setIncludeUnfilteredAttributes(boolean what) {
+ includeUnfilteredAttributes = what;
+ }
/**
* Gets the lookup strategy for locating the profile request context.
diff --git a/shib-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImpl.java b/shib-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImpl.java
index 05162e5da..2f716f172 100644
--- a/shib-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImpl.java
+++ b/shib-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImpl.java
@@ -110,7 +110,7 @@ public class AttributeFilterImpl extends AbstractIdentifiableInitializableCompon
final Map<String, IdPAttribute> prefilteredAttributes = filterContext.getPrefilteredIdPAttributes();
// Create work context to hold intermediate results.
- filterContext.ensureSubcontext(AttributeFilterWorkContext.class);
+ final AttributeFilterWorkContext workContext = filterContext.ensureSubcontext(AttributeFilterWorkContext.class);
log.debug("{} Beginning process of filtering the following {} attributes: {}", new Object[] {getLogPrefix(),
prefilteredAttributes.size(), prefilteredAttributes.keySet(),});
@@ -121,6 +121,26 @@ public class AttributeFilterImpl extends AbstractIdentifiableInitializableCompon
policy.apply(filterContext);
}
+ if (filterContext.isIncludeUnfilteredAttributes()) {
+
+ log.debug("{} Including unfiltered attributes (if any)", getLogPrefix());
+ for (final Entry<String, IdPAttribute> entry : filterContext.getPrefilteredIdPAttributes().entrySet()) {
+ if (workContext.getFilteredAttributeIds().contains(entry.getKey())) {
+ log.trace("{} Attribute {} has already been considered for filtering", getLogPrefix(), entry.getKey());
+ } else {
+ final List<IdPAttributeValue> values = entry.getValue().getValues();
+ if (values.isEmpty()) {
+ log.debug("{} Attribute {} had not valuues", getLogPrefix(), entry.getKey());
+ } else {
+ log.debug("{} adding {} values for attribute '{}'", getLogPrefix(),
+ values.size(), entry.getKey());
+ log.trace("{} values {} ", getLogPrefix(), values);
+ workContext.addPermittedIdPAttributeValues(entry.getKey(), values);
+ }
+ }
+ }
+ }
+
for (final Entry<String, IdPAttribute> entry : filterContext.getPrefilteredIdPAttributes().entrySet()) {
assert entry!=null;
final String key = entry.getKey();
diff --git a/shib-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImplTest.java b/shib-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImplTest.java
index 4f28b4ae3..1c23a99a7 100644
--- a/shib-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImplTest.java
+++ b/shib-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/impl/AttributeFilterImplTest.java
@@ -14,6 +14,10 @@
package net.shibboleth.idp.attribute.filter.impl;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
import java.util.List;
import java.util.Map;
@@ -107,6 +111,141 @@ public class AttributeFilterImplTest {
}
}
+ @Test public void testIncludeUnfilteredAttributes() throws Exception {
+ final IdPAttribute attribute1 = new IdPAttribute("attribute1");
+ attribute1.setValues(CollectionSupport.listOf(new StringAttributeValue("one"), new StringAttributeValue("two")));
+
+ final IdPAttribute attribute2 = new IdPAttribute("attribute2");
+ attribute2.setValues(CollectionSupport.listOf(new StringAttributeValue("a"), new StringAttributeValue("b")));
+
+ final IdPAttribute attribute3 = new IdPAttribute("attribute3");
+ attribute3.setValues(CollectionSupport.listOf(new StringAttributeValue("un"), new StringAttributeValue("deux")));
+
+ final IdPAttribute attribute4 = new IdPAttribute("attribute4");
+ attribute4.setValues(CollectionSupport.listOf(new StringAttributeValue("ein"), new StringAttributeValue("svo")));
+
+ final List<IdPAttribute> attributes = CollectionSupport.listOf(attribute1, attribute2, attribute3, attribute4);
+
+ //
+ // Always on policy attribute 1 which only releases one value
+ //
+ final MockMatcher attribute1Matcher = new MockMatcher();
+ attribute1Matcher.setMatchingAttribute("attribute1");
+ attribute1Matcher.setMatchingValues(CollectionSupport.singleton(attribute1.getValues().get(0)));
+
+ final AttributeRule attribute1Rule = new AttributeRule();
+ attribute1Rule.setId("attribute1Rule");
+ attribute1Rule.setAttributeId(attribute1.getId());
+ attribute1Rule.setMatcher(attribute1Matcher);
+ attribute1Rule.setIsDenyRule(false);
+ attribute1Rule.initialize();
+
+ final AttributeFilterPolicy policy1 =
+ new AttributeFilterPolicy("attribute1Policy", PolicyRequirementRule.MATCHES_ALL,
+ CollectionSupport.singletonList(attribute1Rule));
+ policy1.initialize();
+
+ //
+ // Never on policy attribute 2 which would release everything
+ //
+ final MockMatcher attribute2Matcher = new MockMatcher();
+ attribute2Matcher.setMatchingAttribute("attribute2");
+ attribute2Matcher.setMatchingValues(null);
+
+ final AttributeRule attribute2Rule = new AttributeRule();
+ attribute2Rule.setId("attribute2Rule");
+ attribute2Rule.setAttributeId(attribute2.getId());
+ attribute2Rule.setMatcher(attribute2Matcher);
+ attribute2Rule.setIsDenyRule(false);
+ attribute2Rule.initialize();
+
+ final AttributeFilterPolicy policy2 =
+ new AttributeFilterPolicy("attribute2Policy", PolicyRequirementRule.MATCHES_NONE,
+ CollectionSupport.singletonList(attribute2Rule));
+ policy2.initialize();
+
+ //
+ // Always on policy attribute 3 which denies everything
+ //
+ final MockMatcher attribute3Matcher = new MockMatcher();
+ attribute3Matcher.setMatchingAttribute("attribute3");
+ attribute3Matcher.setMatchingValues(null);
+
+ final AttributeRule attribute3Rule = new AttributeRule();
+ attribute3Rule.setId("attribute3Rule");
+ attribute3Rule.setAttributeId(attribute3.getId());
+ attribute3Rule.setMatcher(attribute3Matcher);
+ attribute3Rule.setIsDenyRule(true);
+ attribute3Rule.initialize();
+
+ final AttributeFilterPolicy policy3 =
+ new AttributeFilterPolicy("attribute3Policy", PolicyRequirementRule.MATCHES_ALL,
+ CollectionSupport.singletonList(attribute3Rule));
+ policy3.initialize();
+
+ final AttributeFilterImpl engine = new AttributeFilterImpl("engine",
+ CollectionSupport.listOf(policy1, policy2, policy3));
+ engine.initialize();
+
+ //
+ // Try with default behavior
+ // Attribute1 - filter everything but value "one"
+ // Attribute2 - policy excludes the attribute
+ // Attribute3 - rule denies all values
+ // Attribute4 - not mentioned, so not present
+ //
+ AttributeFilterContext filterContext = new AttributeFilterContext();
+ filterContext.setPrefilteredIdPAttributes(attributes);
+ engine.filterAttributes(filterContext);
+
+ Map<String, IdPAttribute> filteredAttributes = filterContext.getFilteredIdPAttributes();
+ assertEquals(filteredAttributes.size(), 1);
+ IdPAttribute result = filteredAttributes.get(attribute1.getId());
+ assertNotNull(result);
+ List<IdPAttributeValue> values = result.getValues();
+ assertEquals(values.size(), 1);
+ assertEquals(values.get(0).getDisplayValue(), "one");
+
+ //
+ // Now with include unfiltered attributes
+ //
+ filterContext = new AttributeFilterContext();
+ filterContext.setPrefilteredIdPAttributes(attributes);
+ filterContext.setIncludeUnfilteredAttributes(true);
+ //
+ // Attribute1 - filter everything but value "one"
+ // Only this stuff included
+ // Attribute2 - policy excludes the only attributeRules which mention the attribute
+ // So it is included
+ // Attribute3 - rule denies all values
+ // So it is NOT included
+ // Attribute4 - not mentioned, so not present
+ // So it is included
+ engine.filterAttributes(filterContext);
+
+ filteredAttributes = filterContext.getFilteredIdPAttributes();
+ assertEquals(filteredAttributes.size(), 3);
+ result = filteredAttributes.get(attribute1.getId());
+ assertNotNull(result);
+ values = result.getValues();
+ assertEquals(values.size(), 1);
+ assertEquals(values.get(0).getDisplayValue(), "one");
+
+ result = filteredAttributes.get(attribute2.getId());
+ assertNotNull(result);
+ values = result.getValues();
+ assertEquals(values.size(), 2);
+
+ result = filteredAttributes.get(attribute3.getId());
+ assertNull(result);
+
+ result = filteredAttributes.get(attribute4.getId());
+ assertNotNull(result);
+ values = result.getValues();
+ assertEquals(values.size(), 2);
+ }
+
+
/**
* Test filtering attributes.
*
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list