[java-plugin-shibd] branch main updated: JSHIBD-15 - Implement agent/application IDs as MDC fields
Codeberg
noreply at shibboleth.net
Tue Jan 27 21:44:18 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/f53b38d9b9485bfd33b5be8e993ca8fa1a26bdd1
The following commit(s) were added to refs/heads/main by this push:
new f53b38d JSHIBD-15 - Implement agent/application IDs as MDC fields
f53b38d is described below
commit f53b38d9b9485bfd33b5be8e993ca8fa1a26bdd1
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jan 27 16:43:31 2026 -0500
JSHIBD-15 - Implement agent/application IDs as MDC fields
https://shibboleth.atlassian.net/browse/JSHIBD-15
---
.../idp/flows/sp/abstract/sp-abstract-beans.xml | 6 +-
.../net/shibboleth/idp/module/conf/logback.xml | 225 +++++++++++++++++++++
.../shibboleth/sp/flows/AbstractSPFlowTest.java | 9 +-
.../sp/flows/SessionInitiatorFlowTest.java | 5 +-
.../shibboleth/sp/flows/TokenConsumerFlowText.java | 6 +-
.../sp/profile/AbstractAgentRequestAction.java | 33 ---
.../net/shibboleth/sp/profile/SPConstants.java | 6 +
.../authn/impl/InitializeAgentRequestContext.java | 29 ++-
.../sp/profile/impl/DecodeAgentRequest.java | 41 ++++
.../sp/profile/impl/ResolveApplication.java | 19 +-
10 files changed, 327 insertions(+), 52 deletions(-)
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml
index 6b83890..fd4d969 100644
--- a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml
@@ -30,7 +30,8 @@
<bean id="InitializeAgentRequestContext"
class="net.shibboleth.sp.authn.impl.InitializeAgentRequestContext" scope="prototype"
- p:agentResolver-ref="shibboleth.sp.AgentResolver" />
+ p:agentResolver-ref="shibboleth.sp.AgentResolver"
+ p:populateMDC="%{idp.logging.MDC.enabled:true}" />
<bean id="ValidateAgentAddress"
class="net.shibboleth.sp.authn.impl.ValidateAgentAddress" scope="prototype"
@@ -52,7 +53,8 @@
class="net.shibboleth.idp.authn.impl.ValidateCredentials.UsernamePasswordCleanupHook" />
<bean id="DecodeAgentRequest" class="net.shibboleth.sp.profile.impl.DecodeAgentRequest" scope="prototype"
- p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier" />
+ p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"
+ p:populateMDC="%{idp.logging.MDC.enabled:true}" />
<bean id="EncodeAgentResponse" class="net.shibboleth.sp.profile.impl.EncodeAgentResponse" scope="prototype"
p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/logback.xml b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/logback.xml
new file mode 100644
index 0000000..82c212c
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/logback.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <!--
+ Variables for simplifying logging configuration.
+ http://logback.qos.ch/manual/configuration.html#variableSubstitution
+ -->
+
+ <!--
+ If you want to use custom properties in this config file,
+ we load the main property file for you.
+ -->
+ <variable file="${idp.home}/conf/idp.properties" />
+
+ <!-- Location and retention. -->
+
+ <variable name="idp.logfiles" value="${idp.logfiles:-${idp.home}/logs}" />
+ <variable name="idp.loghistory" value="${idp.loghistory:-180}" />
+
+ <!-- Much higher performance if you operate on DEBUG. -->
+ <!-- <variable name="idp.process.appender" value="ASYNC_PROCESS" /> -->
+
+ <!-- Logging level shortcuts. -->
+ <variable name="idp.loglevel.idp" value="${idp.loglevel.idp:-INFO}" />
+ <variable name="idp.loglevel.ldap" value="${idp.loglevel.ldap:-WARN}" />
+ <variable name="idp.loglevel.messages" value="${idp.loglevel.messages:-INFO}" />
+ <variable name="idp.loglevel.encryption" value="${idp.loglevel.encryption:-INFO}" />
+ <variable name="idp.loglevel.opensaml" value="${idp.loglevel.opensaml:-INFO}" />
+ <variable name="idp.loglevel.shared" value="${idp.loglevel.shared:-INFO}" />
+ <variable name="idp.loglevel.props" value="${idp.loglevel.props:-INFO}" />
+ <variable name="idp.loglevel.httpclient" value="${idp.loglevel.httpclient:-INFO}" />
+
+ <variable name="idp.loglevel.sp" value="${idp.loglevel.sp:-DEBUG}" />
+
+ <!-- Don't turn these up unless you want a *lot* of noise. -->
+ <variable name="idp.loglevel.spring" value="${idp.loglevel.spring:-WARN}" />
+ <variable name="idp.loglevel.container" value="${idp.loglevel.container:-ERROR}" />
+ <variable name="idp.loglevel.xmlsec" value="${idp.loglevel.xmlsec:-INFO}" />
+
+ <!-- =========================================================== -->
+ <!-- ============== Logging Categories and Levels ============== -->
+ <!-- =========================================================== -->
+
+ <!-- Logs IdP, but not OpenSAML, messages -->
+ <logger name="net.shibboleth.idp" level="${idp.loglevel.idp}"/>
+
+ <!-- Logs OpenSAML, but not IdP, messages -->
+ <logger name="org.opensaml.saml" level="${idp.loglevel.opensaml}"/>
+
+ <!-- Logs supporting code. -->
+ <logger name="net.shibboleth.shared" level="${idp.loglevel.shared}"/>
+
+ <!-- Logs LDAP related messages -->
+ <logger name="org.ldaptive" level="${idp.loglevel.ldap}"/>
+
+ <!-- Logs embedded HTTP client messages -->
+ <logger name="org.apache.hc" level="${idp.loglevel.httpclient}"/>
+
+ <!-- Logs SP, but not OpenSAML, messages -->
+ <logger name="net.shibboleth.sp" level="${idp.loglevel.sp}"/>
+
+ <!-- Logs inbound and outbound protocols messages at DEBUG level -->
+ <logger name="PROTOCOL_MESSAGE" level="${idp.loglevel.messages}" />
+
+ <!-- Logs unencrypted SAML at DEBUG level -->
+ <logger name="org.opensaml.saml.saml2.encryption.Encrypter" level="${idp.loglevel.encryption}" />
+ <logger name="org.opensaml.saml.saml2.encryption.Decrypter" level="${idp.loglevel.encryption}" />
+
+ <!-- Logs system properties during startup at DEBUG level -->
+ <logger name="net.shibboleth.idp.admin.impl.LogImplementationDetails" level="${idp.loglevel.props}" />
+
+ <!-- Especially chatty. -->
+ <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec}" />
+ <logger name="org.springframework" level="${idp.loglevel.spring}"/>
+ <logger name="org.apache.catalina" level="${idp.loglevel.container}"/>
+ <logger name="org.eclipse.jetty" level="${idp.loglevel.container}"/>
+
+
+ <!-- =========================================================== -->
+ <!-- ============== Low Level Details or Changes =============== -->
+ <!-- =========================================================== -->
+
+ <!-- Process log. -->
+ <appender name="IDP_PROCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-process.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-process-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - TX:%mdc{sp.txid:-null} [%mdc{sp.agent_id}] [%mdc{sp.application_id}] - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+ </encoder>
+
+ <!-- Ignore Velocity status page error. -->
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator>
+ <matcher>
+ <Name>VelocityStatusMatcher</Name>
+ <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
+ </matcher>
+ <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+ </evaluator>
+ <OnMatch>DENY</OnMatch>
+ </filter>
+ </appender>
+
+ <appender name="ASYNC_PROCESS" class="ch.qos.logback.classic.AsyncAppender">
+ <appender-ref ref="IDP_PROCESS" />
+ <discardingThreshold>0</discardingThreshold>
+ </appender>
+
+ <appender name="IDP_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <!-- Suppress anything below WARN. -->
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+
+ <File>${idp.logfiles}/idp-warn.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-warn-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - TX:%mdc{sp.txid:-null} [%mdc{sp.agent_id}] [%mdc{sp.application_id}] - %level [%logger:%line] - %msg%n%ex{full}</Pattern>
+ </encoder>
+
+ <!-- Ignore Velocity status page error. -->
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator>
+ <matcher>
+ <Name>VelocityStatusMatcher</Name>
+ <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
+ </matcher>
+ <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+ </evaluator>
+ <OnMatch>DENY</OnMatch>
+ </filter>
+ </appender>
+
+ <!-- Audit log. -->
+ <appender name="IDP_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-audit.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <!-- Consent audit log. -->
+ <appender name="IDP_CONSENT_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-consent-audit.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-consent-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <!-- F-TICKS syslog destination. -->
+ <appender name="IDP_FTICKS" class="ch.qos.logback.classic.net.SyslogAppender">
+ <syslogHost>${idp.fticks.loghost:-localhost}</syslogHost>
+ <port>${idp.fticks.logport:-514}</port>
+ <facility>AUTH</facility>
+ <suffixPattern>[%thread] %logger %msg</suffixPattern>
+ </appender>
+
+ <!-- Top level loggers. -->
+
+ <logger name="Shibboleth-Audit" level="ALL">
+ <appender-ref ref="${idp.audit.appender:-IDP_AUDIT}"/>
+ </logger>
+
+ <logger name="Shibboleth-FTICKS" level="ALL" additivity="false">
+ <appender-ref ref="${idp.fticks.appender:-IDP_FTICKS}"/>
+ </logger>
+
+ <logger name="Shibboleth-Consent-Audit" level="ALL">
+ <appender-ref ref="${idp.consent.appender:-IDP_CONSENT_AUDIT}"/>
+ </logger>
+
+ <root level="${idp.loglevel.root:-INFO}">
+ <appender-ref ref="${idp.process.appender:-IDP_PROCESS}"/>
+ <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
+ </root>
+
+ <!-- Example routing Password flow auditing to separate location (extend to other flows as needed). -->
+
+ <!--
+ <appender name="IDP_PASSWORD_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-password-audit.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-password-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <logger name="Shibboleth-Audit.Password" level="ALL" additivity="false">
+ <appender-ref ref="IDP_PASSWORD_AUDIT"/>
+ </logger>
+ -->
+
+</configuration>
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
index 214d5d5..ada2399 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
@@ -38,9 +38,11 @@ import org.testng.annotations.BeforeMethod;
import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
import net.shibboleth.idp.test.PreferFileSystemApplicationContextInitializer;
import net.shibboleth.idp.test.flows.AbstractFlowTest;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy;
import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.profile.SPConstants;
import net.shibboleth.sp.profile.impl.ResolveApplication;
/**
@@ -78,6 +80,10 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
@Autowired
@Qualifier("shibboleth.ParserPool")
protected ParserPool parserPool;
+
+ @Autowired
+ @Qualifier("shibboleth.DefaultIdentifierGenerationStrategy")
+ protected IdentifierGenerationStrategy idGenerator;
protected AbstractSPFlowTest(final String id) {
this(id, END_STATE_ID);
@@ -155,7 +161,8 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
if (input == null || !input.isstruct()) {
input = new DDF(null).structure();
}
- input.addmember(ResolveApplication.APPLICATION_ID).string(applicationId);
+ input.addmember(SPConstants.APPLICATION).string(applicationId);
+ input.addmember(SPConstants.TXID).string(idGenerator.generateIdentifier(false));
setRequest("POST", input);
}
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SessionInitiatorFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SessionInitiatorFlowTest.java
index 1dc5512..98721f8 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SessionInitiatorFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SessionInitiatorFlowTest.java
@@ -26,7 +26,6 @@ import org.testng.annotations.Test;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.profile.SPConstants;
-import net.shibboleth.sp.profile.impl.ResolveApplication;
/**
* Unit test for the SP session-initiator flow (basics only).
@@ -63,7 +62,7 @@ public class SessionInitiatorFlowTest extends AbstractSPFlowTest {
setDefaultAuth();
final DDF input = new DDF(null).structure();
- input.addmember(ResolveApplication.APPLICATION_ID).string("foo");
+ input.addmember(SPConstants.APPLICATION).string("foo");
setRequest("POST", input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -81,7 +80,7 @@ public class SessionInitiatorFlowTest extends AbstractSPFlowTest {
setDefaultAuth();
final DDF input = new DDF(null).structure();
- input.addmember(ResolveApplication.APPLICATION_ID).string(APPLICATION_ID);
+ input.addmember(SPConstants.APPLICATION).string(APPLICATION_ID);
input.addmember(SPConstants.TARGET).unsafe_string("https://sp.example.org".getBytes(StandardCharsets.UTF_8));
setRequest("POST", input);
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TokenConsumerFlowText.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TokenConsumerFlowText.java
index d387d6c..2cb797d 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TokenConsumerFlowText.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TokenConsumerFlowText.java
@@ -24,7 +24,7 @@ import org.testng.annotations.Test;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.sp.ddf.DDF;
-import net.shibboleth.sp.profile.impl.ResolveApplication;
+import net.shibboleth.sp.profile.SPConstants;
/**
* Unit test for the SP token-consumer flow (basics only).
@@ -63,7 +63,7 @@ public class TokenConsumerFlowText extends AbstractSPFlowTest {
setDefaultAuth();
final DDF input = new DDF(null).structure();
- input.addmember(ResolveApplication.APPLICATION_ID).string("foo");
+ input.addmember(SPConstants.APPLICATION).string("foo");
setRequest("POST", input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -82,7 +82,7 @@ public class TokenConsumerFlowText extends AbstractSPFlowTest {
setDefaultAuth();
final DDF input = new DDF(null).structure();
- input.addmember(ResolveApplication.APPLICATION_ID).string(APPLICATION_ID);
+ input.addmember(SPConstants.APPLICATION).string(APPLICATION_ID);
setRequest("POST", input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
index 9218f2f..d12c6f9 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
@@ -29,8 +29,6 @@ import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.Agent;
-import net.shibboleth.sp.Application;
import net.shibboleth.sp.context.AgentRequestContext;
/**
@@ -47,9 +45,6 @@ public abstract class AbstractAgentRequestAction extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AbstractAgentRequestAction.class);
- /** Local copy of extended log prefix. */
- @Nullable private String logPrefix;
-
/** Lookup strategy for {@link AgentRequestContext}. */
@Nonnull private Function<ProfileRequestContext,AgentRequestContext> agentRequestContextLookupStrategy;
@@ -109,33 +104,5 @@ public abstract class AbstractAgentRequestAction extends AbstractProfileAction {
return true;
}
-
- /** {@inheritDoc} */
- @Override
- @Nonnull protected String getLogPrefix() {
-
- if (logPrefix != null) {
- return logPrefix;
- }
-
- final StringBuilder s = new StringBuilder();
- final AgentRequestContext ctx = getAgentRequestContext();
- if (ctx != null) {
- final Agent agent = ctx.getAgent();
- if (agent != null) {
- s.append("Agent ").append(agent.getId()).append(" - ");
- }
- final Application app = ctx.getApplication();
- if (app != null) {
- s.append(" Application ").append(app.getApplicationId()).append(" - ");
- }
- }
-
- s.append(super.getLogPrefix());
- logPrefix = s.toString();
-
- assert logPrefix != null;
- return logPrefix;
- }
}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/SPConstants.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/SPConstants.java
index 223713e..30b7ccf 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/SPConstants.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/SPConstants.java
@@ -23,6 +23,9 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
*/
public final class SPConstants {
+ /** Application parameter. */
+ @Nonnull @NotEmpty public static final String APPLICATION = "application";
+
/** Target parameter. */
@Nonnull @NotEmpty public static final String TARGET = "target";
@@ -32,6 +35,9 @@ public final class SPConstants {
/** Event parameter. */
@Nonnull @NotEmpty public static final String EVENT = "event";
+ /** Transaction ID parameter. */
+ @Nonnull @NotEmpty public static final String TXID = "txid";
+
/** Private constructor. */
private SPConstants() {
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java
index 76fc6ee..43df3dd 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java
@@ -23,6 +23,7 @@ import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
+import org.slf4j.MDC;
import net.shibboleth.idp.authn.AbstractAuthenticationAction;
import net.shibboleth.idp.authn.AuthnEventIds;
@@ -30,6 +31,7 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.UsernamePasswordContext;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -53,9 +55,13 @@ import net.shibboleth.sp.context.AgentRequestContext;
* @event {@link AuthnEventIds#UNKNOWN_USERNAME}
* @pre <pre>ProfileRequestContext.getSubcontext(AuthenticationContext.class) != null</pre>
* @post <pre>ProfileRequestContext.ensureSubcontext(AgentRequestContext.class).getAgent() != null</pre>
+ * @post <pre>An MDC logging attribute is created with the successfully resolved ID.</pre>
*/
public class InitializeAgentRequestContext extends AbstractAuthenticationAction {
+ /** MDC attribute name for agent ID. */
+ @Nonnull @NotEmpty public static final String AGENT_ID_MDC_ATTRIBUTE = "sp.agent_id";
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(InitializeAgentRequestContext.class);
@@ -66,7 +72,10 @@ public class InitializeAgentRequestContext extends AbstractAuthenticationAction
@Nonnull private Function<ProfileRequestContext,AgentRequestContext> agentRequestContextCreationStrategy;
/** The agent resolver. */
- @NonnullAfterInit ReloadableService<AgentResolver> agentResolver;
+ @NonnullAfterInit private ReloadableService<AgentResolver> agentResolver;
+
+ /** Whether to populate the MDC. */
+ private boolean populateMDC;
/** Cached agent credential ID from "username". */
@NonnullBeforeExec private String agentCredentialID;
@@ -77,6 +86,7 @@ public class InitializeAgentRequestContext extends AbstractAuthenticationAction
usernamePasswordContextLookupStrategy = new ChildContextLookup<>(UsernamePasswordContext.class).compose(
new ChildContextLookup<>(AuthenticationContext.class));
agentRequestContextCreationStrategy = new ChildContextLookup<>(AgentRequestContext.class, true);
+ populateMDC = true;
}
/**
@@ -116,6 +126,19 @@ public class InitializeAgentRequestContext extends AbstractAuthenticationAction
agentResolver = Constraint.isNotNull(service, "AgentResolver service cannot be null");
}
+ /**
+ * Sets whether to populate the agent ID into the logging MDC.
+ *
+ * <p>Defaults to true.</p>
+ *
+ * @param flag flag to set
+ */
+ public void setPopulateMDC(final boolean flag) {
+ checkSetterPreconditions();
+
+ populateMDC = flag;
+ }
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -172,6 +195,10 @@ public class InitializeAgentRequestContext extends AbstractAuthenticationAction
}
agentRequestContext.setAgent(agent);
+ if (populateMDC) {
+ MDC.put(AGENT_ID_MDC_ATTRIBUTE, agent.getId());
+ }
+ log.debug("{} Resolved requesting agent '{}'", getLogPrefix(), agent.getId());
} catch (final ServiceException e) {
log.error("{} Unable to obtain AgentResolver component", getLogPrefix(), e);
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DecodeAgentRequest.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DecodeAgentRequest.java
index 82e6a76..85bdf76 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DecodeAgentRequest.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DecodeAgentRequest.java
@@ -19,17 +19,23 @@ import java.io.InputStream;
import javax.annotation.Nonnull;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
+import org.slf4j.MDC;
import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernamePasswordContext;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.sp.context.AgentRequestContext;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
import net.shibboleth.sp.profile.AbstractAgentRequestAction;
+import net.shibboleth.sp.profile.SPConstants;
/**
* A profile action to decode an agent request and stash the resulting {@link DDF} in the
@@ -50,8 +56,35 @@ import net.shibboleth.sp.profile.AbstractAgentRequestAction;
*/
public class DecodeAgentRequest extends AbstractAgentRequestAction {
+ /** MDC attribute name for application ID. */
+ @Nonnull @NotEmpty public static final String APPLICATION_ID_MDC_ATTRIBUTE = "sp.application_id";
+
+ /** MDC attribute name for transaction ID. */
+ @Nonnull @NotEmpty public static final String TX_ID_MDC_ATTRIBUTE = "sp.txid";
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(DecodeAgentRequest.class);
+
+ /** Whether to populate the MDC. */
+ private boolean populateMDC;
+
+ /** Constructor. */
+ public DecodeAgentRequest() {
+ populateMDC = true;
+ }
+
+ /**
+ * Sets whether to populate the application and tx IDs into the logging MDC.
+ *
+ * <p>Defaults to true.</p>
+ *
+ * @param flag flag to set
+ */
+ public void setPopulateMDC(final boolean flag) {
+ checkSetterPreconditions();
+
+ populateMDC = flag;
+ }
/** {@inheritDoc} */
@Override
@@ -88,6 +121,14 @@ public class DecodeAgentRequest extends AbstractAgentRequestAction {
}
}
+ final String txid = msg.getmember(SPConstants.TXID).string();
+ log.debug("{} Decoded message with transaction ID '{}'", getLogPrefix(), txid);
+
+ if (populateMDC) {
+ MDC.put(TX_ID_MDC_ATTRIBUTE, txid);
+ MDC.put(APPLICATION_ID_MDC_ATTRIBUTE, msg.getmember(SPConstants.APPLICATION).string());
+ }
+
} catch (final IOException e) {
log.warn("{} Unable to parse input message from HttpServletRequest", getLogPrefix(), e);
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ResolveApplication.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ResolveApplication.java
index db1e4ca..4876527 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ResolveApplication.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ResolveApplication.java
@@ -21,12 +21,12 @@ import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.sp.Agent;
import net.shibboleth.sp.Application;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.profile.AbstractAgentAction;
+import net.shibboleth.sp.profile.SPConstants;
/**
* An action that maps a message request from an agent to the corresponding {@link Application}
@@ -35,12 +35,10 @@ import net.shibboleth.sp.profile.AbstractAgentAction;
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_MESSAGE}
* @post <pre>AgentRequestContext.getApplication() != null</pre>
+ * @post <pre>An MDC logging attribute is created with the successfully resolved ID.</pre>
*/
public class ResolveApplication extends AbstractAgentAction {
-
- /** Field member carrying application ID. */
- @Nonnull @NotEmpty public static final String APPLICATION_ID = "application";
-
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(ResolveApplication.class);
@@ -51,19 +49,22 @@ public class ResolveApplication extends AbstractAgentAction {
final Agent agent = ensureAgent();
final DDF input = ensureAgentRequestContext().getInput();
- final String applicationId = input != null ? input.getmember(APPLICATION_ID).string() : null;
+ final String applicationId = input != null ? input.getmember(SPConstants.APPLICATION).string() : null;
if (applicationId == null) {
- log.warn("{} Request from agent '{}' missing {} specifier", getLogPrefix(), agent.getId(), APPLICATION_ID);
+ log.warn("{} Request from agent '{}' missing {} specifier", getLogPrefix(), agent.getId(),
+ SPConstants.APPLICATION);
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
return;
}
final Application app = agent.getApplication(applicationId);
if (app != null) {
- log.debug("{} Request from agent '{}' mapped to application '{}'", getLogPrefix(), agent.getId(), app.getId());
ensureAgentRequestContext().setApplication(app);
+ log.debug("{} Request from agent '{}' mapped to application '{}'", getLogPrefix(), agent.getId(),
+ app.getApplicationId());
} else {
- log.warn("{} Request from agent '{}' with unknown application '{}'", getLogPrefix(), agent.getId(), applicationId);
+ log.warn("{} Request from agent '{}' with unknown application '{}'", getLogPrefix(), agent.getId(),
+ applicationId);
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list