[java-oidfed-common] 02/02: Add trust marks into the CLI and admin flow 'test-trust-chain-resolution'

Codeberg noreply at shibboleth.net
Thu Jun 4 10:58:29 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/9b352fdc1992e79b3e31fb528340412dc4bf3084

commit 9b352fdc1992e79b3e31fb528340412dc4bf3084
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Jun 4 13:57:38 2026 +0300

    Add trust marks into the CLI and admin flow 'test-trust-chain-resolution'
    
    - The webflow resolves trust marks for each resolved trust chain and stores the details into ScratchContext
      - Values are available in the view via 'trustMarkIds' and 'trustMarks': arrays with index matching 'trustChaintContext.getPolicyCompliantTrustChains()'
      - Each trust_chain item in the response JSON contains an array of "trust_mark_ids"
    - New option argument flags
      - 'includeTrustMark', defaults to false
        - Includes "trust_mark_details" item to each trust chain, containing a raw SignedJWT object
      - 'remoteTrustMarkValidation', defaults to false
        - To perform remote trust mark validation
---
 .../test-trust-chain-resolution-beans.xml          | 34 ++++++++++++++++++++++
 .../test-trust-chain-resolution-flow.xml           | 29 ++++++++++++++++--
 .../admin/oidfed/test-trust-chain-resolution.vm    | 22 +++++++++++---
 .../cli/TestTrustChainResolutionArguments.java     | 23 ++++++++++++++-
 4 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-beans.xml b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-beans.xml
index ba8058a..7a3d6ac 100644
--- a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-beans.xml
+++ b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-beans.xml
@@ -47,6 +47,40 @@
         c:expression="'true'.equalsIgnoreCase(#custom.get().getParameter('fallbackToLocalResolution'))"
         p:customObject-ref="shibboleth.HttpServletRequestSupplier" />
 
+    <bean id="TrustChainCandidatesExist" parent="shibboleth.Conditions.Expression"
+        c:expression="#input.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)) and #input.ensureInboundMessageContext().ensureSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getPolicyCompliantTrustChains() != null and #input.ensureInboundMessageContext().ensureSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getPolicyCompliantTrustChains().size() > # [...]
+
+    <bean id="SelectTrustChain" class="net.shibboleth.oidfed.profile.impl.SelectTrustChain"
+        scope="prototype"/>
+
+    <bean id="ResolveTrustMarks" class="net.shibboleth.oidfed.profile.impl.ResolveTrustMarks"
+        scope="prototype"
+        p:trustChainCache-ref="#{'%{idp.oidfed.authorize.TrustChainMetadataCache:shibboleth.oidfed.TrustChainMetadataCache}'.trim()}"
+        p:trustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.TrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
+        p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultDelegatedTrustMarkClaimsValidationLookupStrategy')}"
+        p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"
+        p:delegationTrustEngine-ref="shibboleth.oidfed.DefaultDelegatedTrustMarkTrustEngine">
+        <property name="trustChainTrustMarksParsingStrategy">
+            <bean class="net.shibboleth.oidfed.profile.navigate.DefaultTrustChainTrustMarksParsingStrategy"/>
+        </property>
+        <property name="trustedTrustMarkIssuersLookupStrategy">
+            <bean class="net.shibboleth.oidfed.profile.navigate.DefaultTrustChainTrustedTrustMarkIssuersLookupStrategy"/>
+        </property>
+        <property name="trustedTrustMarkOwnersLookupStrategy">
+            <bean class="net.shibboleth.oidfed.profile.navigate.DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy"/>
+        </property>
+    </bean>
+
+    <bean id="ValidateTrustMarks" class="net.shibboleth.oidfed.profile.impl.ValidateTrustMarks"
+        scope="prototype"
+        p:trustMarkStatusCache-ref="#{'%{idp.oidfed.authorize.TrustMarkStatusMetadataCache:shibboleth.oidfed.TrustMarkStatusMetadataCache}'.trim()}">
+        <property name="remoteTrustMarkValidationCondition">
+            <bean parent="shibboleth.Conditions.Expression"
+                c:expression="'true'.equalsIgnoreCase(#custom.get().getParameter('remoteTrustMarkValidation'))"
+                p:customObject-ref="shibboleth.HttpServletRequestSupplier" />
+        </property>
+    </bean>
+
     <bean id="oidc.messageEncoderFactory"
         class="net.shibboleth.oidc.profile.encoding.impl.OIDCResponseEncoderFactory"
         p:messageEncoder-ref="oidc.nimbusEncoder" scope="prototype" />
diff --git a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-flow.xml b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-flow.xml
index 8e6caf6..69ee418 100644
--- a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-flow.xml
+++ b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/oidfed/test-trust-chain-resolution/test-trust-chain-resolution-flow.xml
@@ -12,6 +12,8 @@
         <evaluate expression="T(net.shibboleth.shared.primitive.StringSupport).trimOrNull(externalContext.getNativeRequest().getParameter('includeJWT'))" result="flowScope.includeJWT" />
         <evaluate expression="T(net.shibboleth.shared.primitive.StringSupport).trimOrNull(externalContext.getNativeRequest().getParameter('includeMetadata'))" result="flowScope.includeMetadata" />
         <evaluate expression="T(net.shibboleth.shared.primitive.StringSupport).trimOrNull(externalContext.getNativeRequest().getParameter('useResolverApi'))" result="flowScope.useResolverApi" />
+        <evaluate expression="T(net.shibboleth.shared.primitive.StringSupport).trimOrNull(externalContext.getNativeRequest().getParameter('includeTrustMark'))" result="flowScope.includeTrustMark" />
+        <evaluate expression="T(net.shibboleth.shared.primitive.StringSupport).trimOrNull(externalContext.getNativeRequest().getParameter('remoteTrustMarkValidation'))" result="flowScope.remoteTrustMarkValidation" />
     </on-start>
     
     <action-state id="InitializeProfileRequestContext">
@@ -30,18 +32,39 @@
         <evaluate expression="CheckAccess" />
         <evaluate expression="'proceed'" />
         <transition on="proceed" to="ChooseResolutionMethod">
-            <set name="flowScope.transitionAfterTrustChainResolution" value="'ResponseView'" />
+            <set name="flowScope.transitionAfterTrustChainResolution" value="'CheckIfTrustChainCandidatesExist'" />
             <set name="flowScope.transitionOnNoTrustChainsResolved" value="'ResponseView'" />
-            <evaluate expression="opensamlProfileRequestContext.ensureInboundMessageContext()"/>
+            <evaluate expression="opensamlProfileRequestContext.ensureInboundMessageContext().ensureSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).setRejectedTrustChains(new java.util.ArrayList())"/>
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().put('TestTrustChainResolution.TrustMarks', new java.util.ArrayList())"/> 
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().put('TestTrustChainResolution.TrustMarkIds', new java.util.ArrayList())"/> 
         </transition>
     </action-state>
-    
+
+    <decision-state id="CheckIfTrustChainCandidatesExist">
+        <if test="TrustChainCandidatesExist.test(opensamlProfileRequestContext)"
+            then="ProcessTrustChainCandidate" else="ResponseView" />
+    </decision-state>
+
+    <action-state id="ProcessTrustChainCandidate">
+        <evaluate expression="SelectTrustChain" />
+        <evaluate expression="ResolveTrustMarks" />
+        <evaluate expression="ValidateTrustMarks" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="CheckIfTrustChainCandidatesExist">
+            <evaluate expression="opensamlProfileRequestContext.ensureInboundMessageContext().getSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getRejectedTrustChains().add(opensamlProfileRequestContext.ensureInboundMessageContext().getSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getSelectedTrustChain().getTrustChain())" />
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().get('TestTrustChainResolution.TrustMarks').add(opensamlProfileRequestContext.ensureInboundMessageContext().getSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getVerifiedTrustMarks().get(entityID))"/> 
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().get('TestTrustChainResolution.TrustMarkIds').add(opensamlProfileRequestContext.ensureInboundMessageContext().getSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext)).getVerifiedTrustMarkIds().get(entityID))"/> 
+        </transition>
+    </action-state>
+
     <end-state id="ResponseView" view="admin/oidfed/test-trust-chain-resolution">
         <on-entry>
             <evaluate expression="WriteAuditLog" />
             <evaluate expression="environment" result="requestScope.environment" />
             <evaluate expression="opensamlProfileRequestContext" result="requestScope.profileRequestContext" />
             <evaluate expression="opensamlProfileRequestContext.ensureInboundMessageContext().ensureSubcontext(T(net.shibboleth.oidfed.profile.context.RelyingPartyTrustChainContext))" result="requestScope.trustChaintContext" />
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().get('TestTrustChainResolution.TrustMarks')" result="requestScope.trustMarks" />
+            <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(org.opensaml.messaging.context.ScratchContext)).getMap().get('TestTrustChainResolution.TrustMarkIds')" result="requestScope.trustMarkIds" />
             <evaluate expression="T(org.opensaml.core.xml.util.XMLObjectSupport)" result="requestScope.XMLObjectSupport" />
             <evaluate expression="T(net.shibboleth.shared.xml.SerializeSupport)" result="requestScope.SerializeSupport" />
             <evaluate expression="T(net.shibboleth.shared.codec.HTMLEncoder)" result="requestScope.encoder" />
diff --git a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/views/admin/oidfed/test-trust-chain-resolution.vm b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/views/admin/oidfed/test-trust-chain-resolution.vm
index dce384c..0d8017d 100644
--- a/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/views/admin/oidfed/test-trust-chain-resolution.vm
+++ b/oidfed-common-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/views/admin/oidfed/test-trust-chain-resolution.vm
@@ -7,15 +7,19 @@
 ## response - HttpServletResponse
 ## profileRequestContext
 ## trustChaintContext
+## entityID
 ## includeJWT
 ## includeMetadata
+## includeTrustMark
+## trustMarks
+## trustMarkIds
 ## SerializeSupport
 ## environment - Spring Environment object for property resolution
 ## custom - arbitrary object injected by deployer
 ##
 [#if ($trustChaintContext and $trustChaintContext.getPolicyCompliantTrustChains() and !$trustChaintContext.getPolicyCompliantTrustChains().isEmpty())
-
-#foreach ($policyCompliantChain in $trustChaintContext.getPolicyCompliantTrustChains())
+#set ($index = 0)
+#foreach ($policyCompliantChain in $trustChaintContext.getPolicyCompliantTrustChains()) #set ($index = $index + 1)
     {
         "trust_chain" : [
 #foreach ($entityStatement in $policyCompliantChain.getTrustChain())
@@ -37,13 +41,23 @@
 #foreach ($metadataKey in $policyCompliantChain.getMetadata().getAllClaims().keySet())
             "$metadataKey"#if( $foreach.hasNext ),#end
 #end   
-        ]#if($includeMetadata),
+        ],#if($includeMetadata)
         "metadata_details" : [
 #foreach ($metadataKey in $policyCompliantChain.getMetadata().getAllClaims().keySet())
             "$metadataKey": $policyCompliantChain.getMetadata().getAllClaims().get($metadataKey)#if( $foreach.hasNext ),#end
 #end
-        ]
+        ],
+#end
+        "trust_mark_ids" : [
+#foreach ($trustMarkId in $trustMarkIds.get($index - 1))
+            "$trustMarkId"#if( $foreach.hasNext ),#end
+#end
+        ]#if($includeTrustMark),
+        "trust_mark_details" : [
+#foreach ($trustMark in $trustMarks.get($index - 1))
+            "$trustMark.serialize()"#if( $foreach.hasNext ),#end
 #end
+        ]#end
     }#if( $foreach.hasNext ),#end
 #end
 #end]
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/cli/TestTrustChainResolutionArguments.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/cli/TestTrustChainResolutionArguments.java
index e284642..a78208c 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/cli/TestTrustChainResolutionArguments.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/cli/TestTrustChainResolutionArguments.java
@@ -48,6 +48,12 @@ public class TestTrustChainResolutionArguments extends AbstractCommandLineArgume
     /** The URL parameter name for the flag to fallback to local resolution if resolver API fails. */
     public static final String URL_PARAM_FALLBACK_TO_LOCAL = "fallbackToLocalResolution";
 
+    /** The URL parameter name for the flag to signal full trust mark details to be included. */
+    public static final String URL_PARAM_INCLUDE_TRUST_MARK = "includeTrustMark";
+
+    /** The URL parameter name for the flag to signal remote trust mark validation. */
+    public static final String URL_PARAM_REMOTE_TRUST_MARK_VALIDATION = "remoteTrustMarkValidation";
+
     /** Metadata policy to embed in the token. */
     @Parameter(names = {"-id", "--entityID"}, required = false, description = "Entity ID to be resolved")
     @Nullable private String entityId;
@@ -72,6 +78,16 @@ public class TestTrustChainResolutionArguments extends AbstractCommandLineArgume
             description = "Flag to fallback to local resolution if resolve API resolution fails")
     private boolean fallbackToLocal;
 
+    /** Flag to signal full trust mark details to be included. */
+    @Parameter(names = {"-trustMark", "--includeTrustMark"}, required = false,
+            description = "Flag to include raw trust mark JWTs in the response")
+    private boolean includeTrustMark;
+
+    /** Flag to signal remote trust mark validation. */
+    @Parameter(names = {"-trustMarkValidation", "--remoteTrustMarkValidation"}, required = false,
+            description = "Flag to do remote trust mark validation")
+    private boolean remoteTrustMarkValidation;
+
     /** {@inheritDoc} */
     @Override
     public void validate() {
@@ -105,8 +121,13 @@ public class TestTrustChainResolutionArguments extends AbstractCommandLineArgume
             if (fallbackToLocal) {
                 builder.append("&" + URL_PARAM_FALLBACK_TO_LOCAL + "=true");
             }
+            if (includeTrustMark) {
+                builder.append("&" + URL_PARAM_INCLUDE_TRUST_MARK + "=true");
+            }
+            if (remoteTrustMarkValidation) {
+                builder.append("&" + URL_PARAM_REMOTE_TRUST_MARK_VALIDATION + "=true");
+            }
 
-            
         } catch (final UnsupportedEncodingException e) {
             // UTF-8 is a required encoding.
             throw new RuntimeException("URL encoding failed", e);

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


More information about the commits mailing list