[java-plugin-shibd] branch main updated: Flesh out docs and unit tests.
Codeberg
noreply at shibboleth.net
Tue Aug 18 16:56:16 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-plugin-shibd.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/216fd83b1298424d04e4b41fbe83efc5df84667a
The following commit(s) were added to refs/heads/main by this push:
new 216fd83 Flesh out docs and unit tests.
216fd83 is described below
commit 216fd83b1298424d04e4b41fbe83efc5df84667a
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Aug 18 12:56:00 2026 -0400
Flesh out docs and unit tests.
---
.../credential/impl/CredentialResolverBridge.java | 7 +-
.../impl/StaticMapCredentialResolver.java | 15 +++
.../sp/credential/impl/MockCredential.java | 37 +++++-
.../impl/StaticMapCredentialResolverTest.java | 127 ++++++++++++++++++++-
.../sp/credential/impl/staticmapresolver.xml | 79 ++++++++++++-
5 files changed, 252 insertions(+), 13 deletions(-)
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/CredentialResolverBridge.java b/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/CredentialResolverBridge.java
index 254a1fb..6c1953e 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/CredentialResolverBridge.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/CredentialResolverBridge.java
@@ -123,14 +123,11 @@ public class CredentialResolverBridge implements CredentialResolver {
if (arc != null) {
final Agent agent = arc.getAgent();
if (agent != null) {
- final String id = agent.getId();
- if (id != null) {
- finalCriteria.add(new AgentIDCriterion(id));
- }
+ finalCriteria.add(new AgentIDCriterion(agent));
}
final Application app = arc.getApplication();
if (app != null) {
- finalCriteria.add(new ApplicationIDCriterion(app.getApplicationId()));
+ finalCriteria.add(new ApplicationIDCriterion(app));
}
}
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolver.java b/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolver.java
index 1ecbfd4..4129d72 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolver.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolver.java
@@ -34,8 +34,11 @@ import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.Criterion;
import net.shibboleth.shared.resolver.ResolverException;
+import net.shibboleth.sp.Agent;
import net.shibboleth.sp.AgentIDCriterion;
+import net.shibboleth.sp.Application;
import net.shibboleth.sp.ApplicationIDCriterion;
import net.shibboleth.sp.credential.AbstractOrderedCredentialResolver;
@@ -47,6 +50,18 @@ import net.shibboleth.sp.credential.AbstractOrderedCredentialResolver;
* <p>The "exact" matching map is constructed as a nested three-level map, from
* Agent to Application to RelyingParty and finally to the list of credentials.
* Each layer uses a null key to signify "any" as a wildcard match.</p>
+ *
+ * <p>The resolver recognizes these {@link Criterion} types:</p>
+ *
+ * <ul>
+ * <li>{@link ProfileRequestContextCriterion} - used only for predicate evaluation</li>
+ * <li>{@link AgentIDCriterion} - used for {@link Agent}-indexed rules
+ * <li>{@link ApplicationIDCriterion} - used for {@link Application}-based rules
+ * <li>{@link EntityIdCriterion} - used for relying party-based rules</li>
+ * </ul>
+ *
+ * <p>The absence of a criterion for map-based rules does <strong>not</strong> prevent
+ * rules applying to "any" of an object being applied.</p>
*/
public class StaticMapCredentialResolver extends AbstractOrderedCredentialResolver {
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/MockCredential.java b/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/MockCredential.java
index 5d952c8..c4f4712 100644
--- a/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/MockCredential.java
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/MockCredential.java
@@ -27,21 +27,22 @@ import org.opensaml.security.credential.CredentialContextSet;
import org.opensaml.security.credential.UsageType;
import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
/**
* Testing class to supply a usable credential type.
*/
public class MockCredential implements Credential {
- @Nullable private final String entityID;
+ @Nonnull private final String entityID;
/**
* Constructor.
*
* @param id entityID for testing
*/
- public MockCredential(@Nullable final String id) {
- entityID = id;
+ public MockCredential(@Nonnull final String id) {
+ entityID = Constraint.isNotNull(id, "MockCredential ID cannot be null");
}
/** {@inheritDoc} */
@@ -84,4 +85,34 @@ public class MockCredential implements Credential {
return UsageType.UNSPECIFIED;
}
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull public String toString() {
+ return entityID;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return entityID.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj instanceof MockCredential) {
+ return entityID.equals(((MockCredential) obj).entityID);
+ }
+
+ return false;
+ }
+
}
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolverTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolverTest.java
index 30b535b..fe568a5 100644
--- a/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolverTest.java
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/credential/impl/StaticMapCredentialResolverTest.java
@@ -20,38 +20,159 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.profile.testing.RequestContextBuilder;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.resolver.ResolverException;
+import net.shibboleth.sp.AgentIDCriterion;
+import net.shibboleth.sp.ApplicationIDCriterion;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.criterion.ProfileRequestContextCriterion;
import org.opensaml.security.credential.Credential;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Unit tests for {@link StaticMapCredentialResolver}.
*/
- at SuppressWarnings("javadoc")
@ContextConfiguration(
locations = {
"/net/shibboleth/sp/credential/impl/staticmapresolver.xml",
}
)
@Configuration
+ at SuppressWarnings("javadoc")
public class StaticMapCredentialResolverTest extends AbstractTestNGSpringContextTests {
@Autowired
@Nonnull private StaticMapCredentialResolver resolver;
+
+ private ProfileRequestContext prc;
+
+ @BeforeMethod
+ public void setUp() throws ComponentInitializationException {
+ prc = new WebflowRequestContextProfileRequestContextLookup().apply(new RequestContextBuilder().buildRequestContext());
+ }
@Test public void testPredicates_NoCriteria() throws ResolverException {
final List<Credential> creds = resolve(null);
- Assert.assertEquals(creds.size(), 1);
- Assert.assertEquals(creds.get(0).getEntityId(), "alwaysTrue");
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
+ @Test public void testPredicates_PRCCriterion() throws ResolverException {
+ final List<Credential> creds = resolve(new CriteriaSet(new ProfileRequestContextCriterion(prc)));
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue"),
+ new MockCredential("nonNull")));
+ }
+
+ @Test
+ public void testAgent_NoRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("frobnitz"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
}
+ @Test
+ public void testAgent_WithRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("foo"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Foo_Any"),
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
+ @Test
+ public void testAgentApplication_NoRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("frobnitz"));
+ criteria.add(new ApplicationIDCriterion("frobnitz"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
+ @Test
+ public void testAgentApplication_WithRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("foo"));
+ criteria.add(new ApplicationIDCriterion("zorkmid"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Foo_Any"),
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
+ @Test
+ public void testAgentApplicationRP_NoRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("frobnitz"));
+ criteria.add(new ApplicationIDCriterion("frobnitz"));
+ criteria.add(new EntityIdCriterion("frobnitz"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
+ @Test
+ public void testAgentApplicationRP_WithRules() throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new AgentIDCriterion("foo"));
+ criteria.add(new ApplicationIDCriterion("zorkmid"));
+ criteria.add(new EntityIdCriterion("zork1"));
+
+ final List<Credential> creds = resolve(criteria);
+
+ Assert.assertEquals(creds,
+ CollectionSupport.listOf(
+ new MockCredential("Foo_Zork1"),
+ new MockCredential("Foo_Zork2"),
+ new MockCredential("Foo_Any"),
+ new MockCredential("Any_Zork1"),
+ new MockCredential("Any_Zork2"),
+ new MockCredential("Any_Any"),
+ new MockCredential("alwaysTrue")));
+ }
+
/**
* Wraps a resolve call to capture the output into a list for ease of test validation.
*
diff --git a/sp-server-impl/src/test/resources/net/shibboleth/sp/credential/impl/staticmapresolver.xml b/sp-server-impl/src/test/resources/net/shibboleth/sp/credential/impl/staticmapresolver.xml
index 31ff725..42eb06b 100644
--- a/sp-server-impl/src/test/resources/net/shibboleth/sp/credential/impl/staticmapresolver.xml
+++ b/sp-server-impl/src/test/resources/net/shibboleth/sp/credential/impl/staticmapresolver.xml
@@ -30,19 +30,94 @@
class="net.shibboleth.shared.logic.PredicateSupport" factory-method="not" abstract="true" />
<bean id="shibboleth.Conditions.OR"
class="net.shibboleth.shared.logic.PredicateSupport" factory-method="or" abstract="true" />
+
+ <bean id="shibboleth.Conditions.Expression"
+ class="net.shibboleth.profile.context.logic.SpringExpressionPredicate" abstract="true" />
<bean id="testResolver" class="net.shibboleth.sp.credential.impl.StaticMapCredentialResolver">
- <property name="predicateRules">
+ <!-- Map of agent rules, enclosing map(s) of relying party rules. -->
+ <property name="agentRules">
<map>
+ <!-- All Agents -->
+ <entry key="#{null}">
+ <map>
+ <!-- Any RP. -->
+ <entry key="#{null}">
+ <list>
+ <bean parent="Mock" c:_0="Any_Any" />
+ </list>
+ </entry>
+
+ <!-- Specific RPs. -->
+ <entry key="zork1">
+ <list>
+ <bean parent="Mock" c:_0="Any_Zork1" />
+ <bean parent="Mock" c:_0="Any_Zork2" />
+ </list>
+ </entry>
+ <entry key="zork3">
+ <list>
+ <bean parent="Mock" c:_0="Any_Zork3" />
+ </list>
+ </entry>
+ </map>
+ </entry>
+
+ <!-- Specific Agents... -->
+ <entry key="foo">
+ <map>
+ <!-- Any RP. -->
+ <entry key="#{null}">
+ <list>
+ <bean parent="Mock" c:_0="Foo_Any" />
+ </list>
+ </entry>
+ <!-- Specific RPs. -->
+ <entry key="zork1">
+ <list>
+ <bean parent="Mock" c:_0="Foo_Zork1" />
+ <bean parent="Mock" c:_0="Foo_Zork2" />
+ </list>
+ </entry>
+ <entry key="zork3">
+ <list>
+ <bean parent="Mock" c:_0="Foo_Zork3" />
+ </list>
+ </entry>
+ </map>
+ </entry>
+
+ <entry key="bar">
+ <map>
+ <!-- Any RP. -->
+ <entry key="#{null}">
+ <list>
+ <bean parent="Mock" c:_0="Bar_Any" />
+ </list>
+ </entry>
+ </map>
+ </entry>
+ </map>
+ </property>
+
+ <property name="predicateRules">
+ <!-- Use a typed map here to control order for tests. -->
+ <util:map map-class="java.util.LinkedHashMap">
<entry key-ref="shibboleth.Conditions.TRUE">
<bean parent="Mock" c:_0="alwaysTrue" />
</entry>
<entry key-ref="shibboleth.Conditions.FALSE">
<bean parent="Mock" c:_0="alwaysFalse" />
</entry>
- </map>
+ <entry>
+ <key>
+ <bean parent="shibboleth.Conditions.Expression" c:_0="#input != null" />
+ </key>
+ <bean parent="Mock" c:_0="nonNull" />
+ </entry>
+ </util:map>
</property>
</bean>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list