[java-plugin-shibd] branch main updated: Add wiring for flat file resolver and unit test.

Codeberg noreply at shibboleth.net
Wed Nov 4 17:39:31 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/45e864440b98991df3fbf32da2e89c50b18b7f47

The following commit(s) were added to refs/heads/main by this push:
     new 45e8644  Add wiring for flat file resolver and unit test.
45e8644 is described below

commit 45e864440b98991df3fbf32da2e89c50b18b7f47
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Wed Nov 4 12:39:13 2026 -0500

    Add wiring for flat file resolver and unit test.
---
 .../net/shibboleth/idp/module/conf/sp/agents.xml   |  9 +++++++
 .../net/shibboleth/sp/conf/agents-system.xml       | 29 +++++++++++++++++++++-
 .../shibboleth/sp/service/AgentResolverTest.java   | 26 ++++++++++++++++---
 .../net/shibboleth/idp/module/conf/sp/agents.txt   |  6 +++++
 .../net/shibboleth/idp/module/conf/sp/agents.xml   |  6 +++++
 .../sp/impl/AbstractExternalAgentResolver.java     | 13 +++++-----
 .../sp/impl/FlatFileExternalAgentResolver.java     | 13 +++++++---
 7 files changed, 88 insertions(+), 14 deletions(-)

diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/agents.xml b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/agents.xml
index 994b4cd..0fa1f2c 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/agents.xml
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/agents.xml
@@ -21,6 +21,15 @@
 
     <bean p:id="localhost" parent="shibboleth.sp.Agent" />
 
+    <!-- Flatfile-sourced Agents -->
+    <!--
+    <util:list id="shibboleth.sp.ExternalAgentResolvers">
+        <bean p:id="my.BatchLoader" parent="shibboleth.sp.FlatFileAgentResolver"
+            p:resource="%{idp.home}/conf/sp/agents.txt"
+            p:reloadChanges="PT5M" />
+    </util:list>
+    -->
+
 
     <!-- ============ RelyingParty Overrides ============ -->
     
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
index 7b06b46..2062b08 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
@@ -32,7 +32,7 @@
         c:verified="false"
         c:metadataDriven="%{sp.service.agents.useMetadataDrivenProfiles:false}" />
 
-    <!-- Parent beans for Agents and Applications. -->
+    <!-- Parent beans for Agents and Applications -->
 
     <bean id="DefaultAllowedAddressRanges" parent="shibboleth.CommaDelimStringArray">
         <constructor-arg type="java.lang.String" value="%{sp.agent.authn.allowedAddressRanges:127.0.0.1/32,::1/128}" />
@@ -73,6 +73,33 @@
     <bean id="shibboleth.sp.Application" class="net.shibboleth.sp.impl.BasicApplication" abstract="true"
         p:metricName="net.shibboleth.sp.relyingparty.configurations" />
 
+    <!-- External Agent Resolvers -->
+    
+    <bean id="shibboleth.sp.AbstractExternalAgentResolver" abstract="true"
+        c:_0-ref="ProtocolSupportServiceManager"
+        p:authenticationMethod="basic"
+        p:allowedAddressRanges-ref="DefaultAllowedAddressRanges"
+        p:supportsCachedAuthentication="%{sp.agent.authn.cached:true}"
+        p:authorizedUtilityOperations-ref="DefaultAllowedOperations"
+        p:supportsPostPreservation="%{sp.postData.preservation:false}"
+        p:postLimit="%{sp.postData.limit:1048576}"
+        p:metricName="net.shibboleth.sp.relyingparty.configurations"
+        p:authenticatingAuthority="%{sp.defaultAuthority:}"
+        p:attributeTranscoderRegistry-ref="shibboleth.AttributeRegistryService"
+        p:attributeResolver-ref="shibboleth.AttributeResolverService"
+        p:attributeFilter-ref="shibboleth.AttributeFilterService"
+        p:issuer="#{'%{sp.issuer:}'.trim()}"
+        p:securityConfiguration-ref="#{'%{sp.security.config:shibboleth.sp.DefaultSecurityConfiguration}'.trim()}"
+        p:profileConfigurations="#{getObject('shibboleth.sp.DefaultProfileConfigurations') ?: getObject('VerifiedProfileConfigurations')}"
+        p:unverifiedConfiguration-ref="DefaultUnverifiedRelyingPartyConfiguration"
+        p:relyingPartyConfigurations-ref="shibboleth.sp.RelyingPartyOverrides"
+        p:discoveryServiceLookupStrategy="#{getObject('%{sp.discoveryURLFunction:DefaultDiscoveryServiceStrategy}'.trim())}"
+        p:stateManager-ref="#{'%{sp.stateToken.Manager:shibboleth.sp.CookieStateManager}'.trim()}"
+        p:credentialResolver-ref="shibboleth.sp.CredentialResolverBridge" />
+
+    <bean id="shibboleth.sp.FlatFileAgentResolver" parent="shibboleth.sp.AbstractExternalAgentResolver" abstract="true"
+        class="net.shibboleth.sp.impl.FlatFileExternalAgentResolver" />
+
     <!-- State Managers -->
 
     <bean id="shibboleth.sp.StateManager" abstract="true"
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
index 45aeadb..3041796 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
@@ -99,12 +99,31 @@ public class AgentResolverTest extends AbstractTestNGSpringContextTests {
         
         final Agent agent = resolveAgent("testsp.example.org");
         assert agent != null;
-        validateDefaults(agent);
+        validateDefaults(agent, "https://sp.example.org");
         final Map<String,String> creds = new HashMap<>();
         creds.put(null, "foo");
         Assert.assertEquals(agent.getCredentials(), creds);
         Assert.assertEquals(agent.getId(), "testsp.example.org");
     }
+    
+    /**
+     * Test use of flat file loader.
+     * 
+     * @throws ComponentInitializationException
+     * @throws ResolverException
+     */
+    @Test public void testLoader() throws ComponentInitializationException, ResolverException {
+        
+        resolver = getResolver("/net/shibboleth/idp/module/conf/sp/agents.xml");
+        
+        final Agent agent = resolveAgent("sa-flatfile");
+        assert agent != null;
+        validateDefaults(agent, "https://flatfile.example.org/sp");
+        final Map<String,String> creds = new HashMap<>();
+        creds.put(null, "sa-flatfile");
+        Assert.assertEquals(agent.getCredentials(), creds);
+        Assert.assertEquals(agent.getId(), "flatfile.example.org");
+    }
 
     /**
      * Test a more complex scenario involving inheritance and overrides.
@@ -258,7 +277,7 @@ public class AgentResolverTest extends AbstractTestNGSpringContextTests {
      * 
      * @throws ResolverException on error 
      */
-    private void validateDefaults(@Nonnull final Agent agent) throws ResolverException {
+    private void validateDefaults(@Nonnull final Agent agent, @Nonnull final String issuer) throws ResolverException {
         Assert.assertEquals(agent.getApplications().size(), 1);
         Assert.assertEquals(agent.getAllowedAddressRanges(),
                 CollectionSupport.setOf(IPRange.parseCIDRBlock("127.0.0.1/32"), IPRange.parseCIDRBlock("::1/128")));
@@ -271,7 +290,7 @@ public class AgentResolverTest extends AbstractTestNGSpringContextTests {
         Assert.assertTrue(app.getTokenConsumers(null).isEmpty());
         
         if (app instanceof BasicApplication basic) {
-            Assert.assertEquals(basic.getIssuer(null), "https://sp.example.org");
+            Assert.assertEquals(basic.getIssuer(null), issuer);
             Assert.assertTrue(basic.getProfileConfigurations(null).isEmpty());
         }
         
@@ -322,6 +341,7 @@ public class AgentResolverTest extends AbstractTestNGSpringContextTests {
             try (final InputStream in = resource.getInputStream()) {
                 props.load(in);
                 props.setProperty("sp.stateToken.sealed", "false");
+                props.setProperty("idp.home", "classpath:/net/shibboleth/idp/module");
             } catch (IOException e) {
                 Assert.fail(e.getMessage());
             }
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.txt b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.txt
new file mode 100644
index 0000000..ecff0f2
--- /dev/null
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.txt
@@ -0,0 +1,6 @@
+
+
+id: flatfile.example.org
+username: sa-flatfile
+issuer: https://flatfile.example.org/sp
+
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.xml b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.xml
index 701c19d..33c56f0 100644
--- a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.xml
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/agents.xml
@@ -30,6 +30,12 @@
     <bean p:id="unauthorized.example.org" parent="shibboleth.sp.Agent" p:authenticationMethod="basic"
         p:credentials="#{{'sa-unauthorized' : 'foo'}}" />
     
+    <!-- Flatfile-sourced Agents -->
+    <util:list id="shibboleth.sp.ExternalAgentResolvers">
+        <bean p:id="my.BatchLoader" parent="shibboleth.sp.FlatFileAgentResolver"
+            p:resource="%{idp.home}/conf/sp/agents.txt" />
+    </util:list>
+        
 
     <!-- ============ RelyingParty Overrides ============ -->
     
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/AbstractExternalAgentResolver.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/AbstractExternalAgentResolver.java
index edb20fb..8d826b9 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/AbstractExternalAgentResolver.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/AbstractExternalAgentResolver.java
@@ -19,7 +19,6 @@ import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -59,10 +58,10 @@ import net.shibboleth.shared.net.IPRange;
 import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 import net.shibboleth.shared.resolver.CriteriaSet;
-import net.shibboleth.shared.resolver.Resolver;
 import net.shibboleth.shared.resolver.ResolverException;
 import net.shibboleth.shared.service.ReloadableService;
 import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.AgentResolver;
 import net.shibboleth.sp.Application;
 import net.shibboleth.sp.criteria.AgentCredentialCriterion;
 import net.shibboleth.sp.criteria.AgentIDCriterion;
@@ -81,7 +80,7 @@ import net.shibboleth.sp.state.StateManager;
  * interfaces.</p>
  */
 public abstract class AbstractExternalAgentResolver extends AbstractIdentifiableInitializableComponent
-        implements Resolver<Agent,CriteriaSet> {
+        implements AgentResolver {
 
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractExternalAgentResolver.class);
@@ -91,9 +90,7 @@ public abstract class AbstractExternalAgentResolver extends AbstractIdentifiable
 
     /** Whether to enable caching. */
     private boolean cacheEnabled;
-    
-    // Agent fields.
-    
+
     /** Size of cache. */
     @Nonnull @Positive private Integer maximumCachedElements;
     
@@ -105,7 +102,9 @@ public abstract class AbstractExternalAgentResolver extends AbstractIdentifiable
     
     /** Agent resolution cache. */
     @Nullable private Cache<CriteriaSet,Agent> resultsCache;
-
+    
+    // Agent fields.
+    
     /** Allowed address ranges. */
     @Nonnull private Set<IPRange> allowedAddressRanges;
     
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/FlatFileExternalAgentResolver.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/FlatFileExternalAgentResolver.java
index 681b217..ac9842e 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/FlatFileExternalAgentResolver.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/FlatFileExternalAgentResolver.java
@@ -135,7 +135,7 @@ public class FlatFileExternalAgentResolver extends AbstractExternalAgentResolver
         super(protocolManager);
         
         lastModified = 0;
-        reloadInterval = Duration.ofMinutes(5);
+        reloadInterval = Duration.ZERO;
     }
     
     /**
@@ -311,6 +311,7 @@ public class FlatFileExternalAgentResolver extends AbstractExternalAgentResolver
             
             int lineno = 0;
             String line;
+            boolean startedRecord = false;
 
             String id = null;
             String issuer = null;
@@ -325,7 +326,7 @@ public class FlatFileExternalAgentResolver extends AbstractExternalAgentResolver
                 if (line.isEmpty() || line.isBlank()) {
                     if (id != null) {
                         installMappings(theMap, new AgentTemplate(id, issuer, authority, ranges, usernames));
-                    } else {
+                    } else if (startedRecord) {
                         log.error("Ignoring agent definition with no '{}' field", ID_FIELD);
                     }
                     
@@ -334,24 +335,30 @@ public class FlatFileExternalAgentResolver extends AbstractExternalAgentResolver
                     authority = null;
                     ranges.clear();
                     usernames.clear();
+                    startedRecord = false;
                     continue;
                 } else if (line.startsWith("#")) {
                     continue;
                 } else if (line.startsWith(ID_FIELD)) {
+                    startedRecord = true;
                     id = StringSupport.trimOrNull(line.substring(ID_FIELD.length()));
                 } else if (line.startsWith(ALLOWED_RANGE_FIELD)) {
+                    startedRecord = true;
                     final String temp = StringSupport.trimOrNull(line.substring(ALLOWED_RANGE_FIELD.length()));
                     if (temp != null) {
                         ranges.add(temp);
                     }
                 } else if (line.startsWith(USERNAME_FIELD)) {
+                    startedRecord = true;
                     final String temp = StringSupport.trimOrNull(line.substring(USERNAME_FIELD.length()));
                     if (temp != null) {
                         usernames.add(temp);
                     }
                 } else if (line.startsWith(ISSUER_FIELD)) {
+                    startedRecord = true;
                     issuer = StringSupport.trimOrNull(line.substring(ISSUER_FIELD.length()));
                 } else if (line.startsWith(AUTHORITY_FIELD)) {
+                    startedRecord = true;
                     authority = StringSupport.trimOrNull(line.substring(AUTHORITY_FIELD.length()));
                 } else {
                     log.info("Ignoring unrecognized line ({})", lineno);
@@ -360,7 +367,7 @@ public class FlatFileExternalAgentResolver extends AbstractExternalAgentResolver
             
             if (id != null) {
                 installMappings(theMap, new AgentTemplate(id, issuer, authority, ranges, usernames));
-            } else if (lineno > 0) {
+            } else if (startedRecord) {
                 log.error("Ignoring agent definition with no '{}' field", ID_FIELD);
             }
             

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


More information about the commits mailing list