[java-oidfed-common] 01/02: Add property to control maximum trust chain length to be locally resolved

Codeberg noreply at shibboleth.net
Fri Sep 18 06:59:24 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-oidfed-common.

View the commit online:
https://codeberg.org/Shibboleth/java-oidfed-common/commit/4f81e53561f037f32dbd61c7925baa456734f838

commit 4f81e53561f037f32dbd61c7925baa456734f838
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Sep 18 09:36:44 2026 +0300

    Add property to control maximum trust chain length to be locally resolved
    
    - idp.oidfed.cache.trustChain.maximumChainLength, defaults to 5
    - Cover in unit tests
---
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  7 +++
 .../DefaultTrustChainFetchingStrategy.java         | 37 +++++++++++++--
 .../oidfed/conf/oidfed/oidfed.properties           |  6 +++
 .../DefaultTrustChainFetchingStrategyTest.java     | 54 ++++++++++++++++++++--
 .../src/test/resources/logback-test.xml            | 20 ++++++++
 5 files changed, 116 insertions(+), 8 deletions(-)

diff --git a/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 5a58927..f22ca63 100644
--- a/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -405,6 +405,13 @@
                         </constructor-arg>
                     </bean>
                 </property>
+                <property name="criteriaToMaximumChainLengthStrategy">
+                    <bean parent="shibboleth.Functions.Constant">
+                        <constructor-arg>
+                            <bean class="java.lang.Integer" factory-method="parseInt" c:_0="%{idp.oidfed.cache.trustChain.maximumChainLength:5}" />
+                        </constructor-arg>
+                    </bean>
+                </property>
             </bean>
         </property>
     </bean>
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategy.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategy.java
index a6069b4..bf2b825 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategy.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategy.java
@@ -81,6 +81,9 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
     /** Strategy to fetch lifetime for container with invalid contents. */
     @NonnullAfterInit private Function<CriteriaSet, Duration> criteriaToInvalidContainerLifetimeStrategy;
 
+    /** Strategy to fetch maximum length for trust chains. */
+    @NonnullAfterInit private Function<CriteriaSet, Integer> criteriaToMaximumChainLengthStrategy;
+
     /**
      * Set the strategy for fetching entity ID from the criteria set.
      * 
@@ -142,11 +145,21 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
     public void setCriteriaToInvalidContainerLifetimeStrategy(
             @Nonnull final Function<CriteriaSet, Duration> strategy) {
         checkSetterPreconditions();
-
         criteriaToInvalidContainerLifetimeStrategy =
                 Constraint.isNotNull(strategy, "Criteria to invalid container lifetime strategy cannot be null");
     }
 
+    /**
+     * Set the strategy to fetch maximum length for trust chains.
+     * 
+     * @param strategy maximum length strategy
+     */
+    public void setCriteriaToMaximumChainLengthStrategy(@Nonnull final Function<CriteriaSet, Integer> strategy) {
+        checkSetterPreconditions();
+        criteriaToMaximumChainLengthStrategy =
+                Constraint.isNotNull(strategy, "Criteria to maximum trust chain length strategy cannot be null");
+    }
+
     /** {@inheritDoc} */
     @Override
     protected void doInitialize() throws ComponentInitializationException {
@@ -170,6 +183,10 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
             throw new ComponentInitializationException(
                     "Criteria to invalid container lifetime strategy cannot be null");
         }
+        if (criteriaToMaximumChainLengthStrategy == null) {
+            throw new ComponentInitializationException(
+                    "Criteria to maximum trust chain length strategy cannot be null");
+        }
     }
 
     /** {@inheritDoc} */
@@ -211,7 +228,11 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
         } else {
             entityConfiguration = subjectStatementCriterion.getValue() instanceof EntityConfiguration ec ? ec : null;
         }
-
+        final Integer maximumLength = criteriaToMaximumChainLengthStrategy.apply(criteria);
+        if (maximumLength == null || maximumLength.intValue() < 3) {
+            log.warn("Could not fetch valid maximum trust chain length, it must be greater than 2: {}", maximumLength);
+            return null;
+        }
         log.trace("Entity configuration found to build the trust chains on: {}", entityConfiguration != null);
         if (entityConfiguration == null) {
             return null;
@@ -225,7 +246,7 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
             return null;
         }
         final List<TrustChainWrapper> populatedWrappers = populateChain(
-                CollectionSupport.listOf(initialWrapper), preSelectedChain);
+                CollectionSupport.listOf(initialWrapper), preSelectedChain, maximumLength.intValue());
         final List<List<EntityStatement<?>>> result = populatedWrappers.stream()
                 .filter(wrapper -> wrapper.isComplete())
                 .map(wrapper -> wrapper.getTrustChain())
@@ -266,11 +287,12 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
      * 
      * @param entities the list of trust chains being populated.
      * @param preSelectedChain the pre-selected trust chain (containing entity IDs as String).
+     * @param maxChainLength the maximum length of trust chain, longer than this limit will be ignored
      * @return the list of trust chains being populated
      */
     @Nonnull @NonnullElements private List<TrustChainWrapper> populateChain(
             @Nonnull @NonnullElements final List<TrustChainWrapper> entities,
-            @Nonnull final List<String> preSelectedChain) {
+            @Nonnull final List<String> preSelectedChain, final int maxChainLength) {
         final List<TrustChainWrapper> result = new ArrayList<>();
         boolean hints = false;
         for (final TrustChainWrapper chainWrapper : entities) {
@@ -288,6 +310,11 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
             final List<String> authorityHints = entityStatement instanceof EntityConfiguration configuration ?
                     configuration.getParsedPayload().getAuthorityHints() : null;
             if (authorityHints != null && !authorityHints.isEmpty()) {
+                if (chain.size() == maxChainLength) {
+                    log.info("Maximum trust chain length limit has been met, ignoring authority hints {} of {}"
+                            + ", leaf {}", authorityHints, entityStatement.getSubject(), chain.get(0).getSubject());
+                    continue;
+                }
                 final List<Pair<EntityConfiguration, SubordinateStatement>> authorities = authorityHints.stream()
                         .filter(id -> verifyNoLoop(chain, id))
                         .filter(id -> verifyPreSelected(chain, id, preSelectedChain))
@@ -306,7 +333,7 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
             }
         }
         if (hints) {
-            return populateChain(result, preSelectedChain);
+            return populateChain(result, preSelectedChain, maxChainLength);
         }
         return result;
     }
diff --git a/oidfed-common-impl/src/main/resources/net/shibboleth/oidfed/conf/oidfed/oidfed.properties b/oidfed-common-impl/src/main/resources/net/shibboleth/oidfed/conf/oidfed/oidfed.properties
index 1ad624e..53beafa 100644
--- a/oidfed-common-impl/src/main/resources/net/shibboleth/oidfed/conf/oidfed/oidfed.properties
+++ b/oidfed-common-impl/src/main/resources/net/shibboleth/oidfed/conf/oidfed/oidfed.properties
@@ -54,6 +54,12 @@ idp.oidfed.entityConfiguration.authorityHints = https://your.authority.example.o
 #idp.oidfed.cache.subordinateStatement.maxJwtLifetime = PT24H
 #idp.oidfed.cache.subordinateStatement.critClaims = %{idp.oidfed.cache.default.critClaims:}
 
+# Maximum trust chain length to be locally resolved - must be greater than 2
+# Example lengths:
+# - only trust anchor: 3 (leaf configuration, subordinate statement about leaf, anchor configuration)
+# - trust anchor and intermediate: 4 (leaf configuration, subordinate statements about leaf and intermediate, anchor configuration)
+#idp.oidfed.cache.trustChain.maximumChainLength = 5
+
 #idp.oidfed.cache.trustChain.cleanupTaskInterval = PT5M
 #idp.oidfed.cache.trustChain.customFilterStrategies = 
 #idp.oidfed.cache.trustChain.validContainerLifetime = PT5M
diff --git a/oidfed-common-conf-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/test/DefaultTrustChainFetchingStrategyTest.java b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategyTest.java
similarity index 85%
rename from oidfed-common-conf-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/test/DefaultTrustChainFetchingStrategyTest.java
rename to oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategyTest.java
index a10cb6b..cf57464 100644
--- a/oidfed-common-conf-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/test/DefaultTrustChainFetchingStrategyTest.java
+++ b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/cache/trustchain/DefaultTrustChainFetchingStrategyTest.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.oidfed.metadata.cache.trustchain.test;
+package net.shibboleth.oidfed.metadata.cache.trustchain;
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
@@ -37,8 +37,6 @@ import net.shibboleth.oidfed.metadata.cache.configuration.EntityConfigurationCon
 import net.shibboleth.oidfed.metadata.cache.local.LocalKeyContainer;
 import net.shibboleth.oidfed.metadata.cache.subordinate.SubordinateStatementCacheIdentifier;
 import net.shibboleth.oidfed.metadata.cache.subordinate.SubordinateStatementContainer;
-import net.shibboleth.oidfed.metadata.cache.trustchain.DefaultTrustChainFetchingStrategy;
-import net.shibboleth.oidfed.metadata.cache.trustchain.TrustChainsContainer;
 import net.shibboleth.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.oidfed.metadata.util.EntityStatementHelper;
 import net.shibboleth.shared.collection.CollectionSupport;
@@ -59,6 +57,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     MetadataCache<Map<String, LocalKeyContainer>> localTrustAnchorsCache;
     Function<CriteriaSet, Duration> criteriaToValidContainerLifetimeStrategy;
     Function<CriteriaSet, Duration> criteriaToInvalidContainerLifetimeStrategy;
+    Function<CriteriaSet, Integer> criteriaToMaximumChainLengthStrategy;
 
     @SuppressWarnings("unchecked")
     public void initMocks() {
@@ -68,6 +67,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         localTrustAnchorsCache = mock(MetadataCache.class);
         criteriaToValidContainerLifetimeStrategy = mock(Function.class);
         criteriaToInvalidContainerLifetimeStrategy = mock(Function.class);
+        criteriaToMaximumChainLengthStrategy = mock(Function.class);
     }
 
     @BeforeMethod
@@ -80,6 +80,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         function.setLocalTrustAnchorsCache(localTrustAnchorsCache);
         function.setCriteriaToValidContainerLifetimeStrategy(criteriaToValidContainerLifetimeStrategy);
         function.setCriteriaToInvalidContainerLifetimeStrategy(criteriaToInvalidContainerLifetimeStrategy);
+        function.setCriteriaToMaximumChainLengthStrategy(criteriaToMaximumChainLengthStrategy);
         function.setId("mockFunction");
         try {
             function.initialize();
@@ -97,6 +98,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void noValidLifetimeCriteria_returnsNull() {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(null);
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         Assert.assertEquals(function.apply(new CriteriaSet()), null);
     }
 
@@ -104,6 +106,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void noInvalidLifetimeCriteria_returnsNull() {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(null);
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         Assert.assertEquals(function.apply(new CriteriaSet()), null);
     }
 
@@ -111,6 +114,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void noEntityConfigurationResolved_returnsNull() throws MetadataCacheException {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         when(entityConfigurationCache.get(any())).thenReturn(CollectionSupport.emptyList());
         Assert.assertEquals(function.apply(new CriteriaSet()), null);
     }
@@ -119,6 +123,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void entityConfigurationException_returnsNull() throws MetadataCacheException {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         when(entityConfigurationCache.get(any())).thenThrow(MetadataCacheException.class);
         Assert.assertEquals(function.apply(new CriteriaSet()), null);
     }
@@ -127,6 +132,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void entityConfigurationNoHints_returnsNull() throws MetadataCacheException {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer("mockEntityId", CollectionSupport.emptyList());
         when(entityConfigurationCache.get(any())).thenReturn(CollectionSupport.listOf(ecContainer));
@@ -137,6 +143,7 @@ public class DefaultTrustChainFetchingStrategyTest {
     public void entityConfigurationOneUnresolvableHint_returnsEmptyContainer() throws MetadataCacheException {
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer("mockEntityId", CollectionSupport.listOf("https://federation.local/immediate"));
         when(entityConfigurationCache.get(any())).thenReturn(CollectionSupport.listOf(ecContainer));
@@ -150,6 +157,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         final String anchor = "https://federation.local/immediate";
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(anchor, "https://federation.local/other"));
         final EntityConfigurationContainer authorityContainer =
@@ -177,6 +185,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         final String anchor = "https://federation.local/anchor";
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(immediate, "https://federation.local/other"));
         final EntityConfigurationContainer immediateContainer =
@@ -206,6 +215,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         final String anchor = "https://federation.local/anchor";
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(immediate));
         final EntityConfigurationContainer immediateContainer =
@@ -232,6 +242,40 @@ public class DefaultTrustChainFetchingStrategyTest {
                 List.of(leaf, immediate, anchor));
     }
 
+    @SuppressWarnings("unchecked")
+    @Test
+    public void entityConfigurationOneResolvableLocalAuthorityWithWorkingHint_maxlnght3_returnsContainerWithTwoChains()
+            throws MetadataCacheException {
+        final String leaf = "https://federation.local/leaf";
+        final String immediate = "https://federation.local/immediate";
+        final String anchor = "https://federation.local/anchor";
+        when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(3);
+        final EntityConfigurationContainer ecContainer =
+                ecContainer(leaf, CollectionSupport.listOf(immediate));
+        final EntityConfigurationContainer immediateContainer =
+                ecContainer(immediate, CollectionSupport.listOf(anchor));
+        final EntityConfigurationContainer authorityContainer =
+                ecContainer(anchor, CollectionSupport.emptyList());
+        when(entityConfigurationCache.get(any()))
+            .thenReturn(CollectionSupport.listOf(ecContainer), CollectionSupport.listOf(immediateContainer),
+                    CollectionSupport.listOf(authorityContainer), CollectionSupport.emptyList());
+        final SubordinateStatementContainer ssContainer1 = ssContainer(leaf, immediate);
+        final SubordinateStatementContainer ssContainer2 = ssContainer(immediate, anchor);
+        when(subordinateStatementCache.get(any())).thenReturn(CollectionSupport.listOf(ssContainer1),
+                CollectionSupport.listOf(ssContainer2), CollectionSupport.emptyList());
+        when(localTrustAnchorsCache.get(any())).thenReturn(
+                CollectionSupport.listOf(CollectionSupport.singletonMap(immediate, mock(LocalKeyContainer.class))),
+                CollectionSupport.emptyList());
+        final TrustChainsContainer result = function.apply(new CriteriaSet());
+        Assert.assertNotNull(result);
+        assert result != null;
+        Assert.assertEquals(result.getTrustChains().size(), 1);
+        Assert.assertEquals(EntityStatementHelper.getEntityIds(result.getTrustChains().get(0)),
+                List.of(leaf, immediate));
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void entityConfigurationOneResolvableHint_matchPreSelected_returnsContainerWithOneChain()
@@ -242,6 +286,7 @@ public class DefaultTrustChainFetchingStrategyTest {
                 new PreSelectedTrustChainCriterion(CollectionSupport.listOf(leaf, anchor));
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(anchor, "https://federation.local/other"));
         final EntityConfigurationContainer authorityContainer =
@@ -270,6 +315,7 @@ public class DefaultTrustChainFetchingStrategyTest {
                 new PreSelectedTrustChainCriterion(CollectionSupport.listOf(leaf, "https://federation.local/not"));
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(anchor, "https://federation.local/other"));
         final EntityConfigurationContainer authorityContainer =
@@ -291,6 +337,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         final String anchor2 = "https://federation.local/immediate2";
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(anchor1, anchor2));
         final EntityConfigurationContainer authorityContainer1 =
@@ -322,6 +369,7 @@ public class DefaultTrustChainFetchingStrategyTest {
         final String anchor2 = "https://federation.local/immediate2";
         when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
         when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
+        when(criteriaToMaximumChainLengthStrategy.apply(any())).thenReturn(4);
         final EntityConfigurationContainer ecContainer =
                 ecContainer(leaf, CollectionSupport.listOf(anchor1));
         final EntityConfigurationContainer authorityContainer1 =
diff --git a/oidfed-common-impl/src/test/resources/logback-test.xml b/oidfed-common-impl/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..83cf0c5
--- /dev/null
+++ b/oidfed-common-impl/src/test/resources/logback-test.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+    <logger name="PROTOCOL_MESSAGE" level="TRACE"/>
+    <logger name="net.shibboleth.oidfed" level="TRACE"/>
+    <logger name="net.shibboleth" level="DEBUG"/>
+    <logger name="org.springframework" level="DEBUG"/>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%level [%logger:%line] - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <root level="WARN">
+        <appender-ref ref="STDOUT" />
+    </root>
+    
+</configuration>
\ No newline at end of file

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


More information about the commits mailing list