This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.4.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 1011d8832f4762f4ed5cbbba8bedd53fdfb9b1c9 Author: Julien Greffe <[email protected]> AuthorDate: Mon May 9 14:41:09 2022 +0200 [CXF-8699] Abillity to set sensitive filters on LoggingFeature (#945) * [CXF-8699] Abillity to set sensitive filters on LoggingFeature * [CXF-8699] Set<String> with trimmed values --- .../ext/logging/AbstractLoggingInterceptor.java | 9 +++++ .../org/apache/cxf/ext/logging/LoggingFeature.java | 42 ++++++++++++++++++++ .../cxf/ext/logging/MaskSensitiveHelper.java | 6 +++ .../org/apache/cxf/ext/logging/osgi/Activator.java | 25 ++++++++++++ .../cxf/ext/logging/MaskSensitiveHelperTest.java | 46 +++++++++++++++++++++- 5 files changed, 126 insertions(+), 2 deletions(-) diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java index e823bbadc8..5fd0b28564 100644 --- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java +++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java @@ -86,10 +86,19 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto return threshold; } + public void setSensitiveElementNames(final Set<String> sensitiveElementNames) { + maskSensitiveHelper.setSensitiveElementNames(sensitiveElementNames); + } + public void addSensitiveElementNames(final Set<String> sensitiveElementNames) { maskSensitiveHelper.addSensitiveElementNames(sensitiveElementNames); } + public void setSensitiveProtocolHeaderNames(final Set<String> protocolHeaderNames) { + this.sensitiveProtocolHeaderNames.clear(); + addSensitiveProtocolHeaderNames(protocolHeaderNames); + } + public void addSensitiveProtocolHeaderNames(final Set<String> protocolHeaderNames) { this.sensitiveProtocolHeaderNames.addAll(protocolHeaderNames); } diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java index dff3e88bed..43bedc484a 100644 --- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java +++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java @@ -147,6 +147,22 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> { * </pre> * @param sensitiveElementNames set of sensitive element names to be replaced */ + public void setSensitiveElementNames(final Set<String> sensitiveElementNames) { + delegate.setSensitiveElementNames(sensitiveElementNames); + } + + /** + * Adds list of XML or JSON elements containing sensitive information to be masked. + * Corresponded data will be replaced with configured mask + * For example: + * <pre> + * sensitiveElementNames: {password} + * + * Initial logging statement: <user>my user</user><password>my secret password</password> + * Result logging statement: <user>my user</user><password>XXXX</password> + * </pre> + * @param sensitiveElementNames set of sensitive element names to be replaced + */ public void addSensitiveElementNames(final Set<String> sensitiveElementNames) { delegate.addSensitiveElementNames(sensitiveElementNames); } @@ -163,6 +179,22 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> { * </pre> * @param sensitiveProtocolHeaderNames set of sensitive element names to be replaced */ + public void setSensitiveProtocolHeaderNames(final Set<String> sensitiveProtocolHeaderNames) { + delegate.setSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); + } + + /** + * Adds list of protocol headers containing sensitive information to be masked. + * Corresponded data will be replaced with configured mask + * For example: + * <pre> + * sensitiveHeaders: {Authorization} + * + * Initial logging statement: {Authorization=Basic QWxhZGRpbjpPcGVuU2VzYW1l} + * Result logging statement: {Authorization=XXX} + * </pre> + * @param sensitiveProtocolHeaderNames set of sensitive element names to be replaced + */ public void addSensitiveProtocolHeaderNames(final Set<String> sensitiveProtocolHeaderNames) { delegate.addSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); } @@ -252,11 +284,21 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> { addOutBinaryContentMediaTypes(mediaTypes); } + public void setSensitiveElementNames(final Set<String> sensitiveElementNames) { + in.setSensitiveElementNames(sensitiveElementNames); + out.setSensitiveElementNames(sensitiveElementNames); + } + public void addSensitiveElementNames(final Set<String> sensitiveElementNames) { in.addSensitiveElementNames(sensitiveElementNames); out.addSensitiveElementNames(sensitiveElementNames); } + public void setSensitiveProtocolHeaderNames(final Set<String> sensitiveProtocolHeaderNames) { + in.setSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); + out.setSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); + } + public void addSensitiveProtocolHeaderNames(final Set<String> sensitiveProtocolHeaderNames) { in.addSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); out.addSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java index 811a541254..062a0e4d4b 100644 --- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java +++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java @@ -50,6 +50,12 @@ public class MaskSensitiveHelper { private final Set<ReplacementPair> replacementsXML = new HashSet<>(); private final Set<ReplacementPair> replacementsJSON = new HashSet<>(); + public void setSensitiveElementNames(final Set<String> inSensitiveElementNames) { + replacementsXML.clear(); + replacementsJSON.clear(); + addSensitiveElementNames(inSensitiveElementNames); + } + public void addSensitiveElementNames(final Set<String> inSensitiveElementNames) { for (final String sensitiveName : inSensitiveElementNames) { addReplacementPair(MATCH_PATTERN_XML_TEMPLATE, REPLACEMENT_XML_TEMPLATE, sensitiveName, replacementsXML); diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/osgi/Activator.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/osgi/Activator.java index 5845180add..6084bd7978 100644 --- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/osgi/Activator.java +++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/osgi/Activator.java @@ -18,8 +18,12 @@ */ package org.apache.cxf.ext.logging.osgi; +import java.util.Arrays; import java.util.Dictionary; +import java.util.HashSet; import java.util.Hashtable; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.cxf.ext.logging.LoggingFeature; import org.apache.cxf.feature.AbstractFeature; @@ -33,6 +37,8 @@ import org.osgi.service.cm.ManagedService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.util.function.Predicate.not; + public class Activator implements BundleActivator { private static final Logger LOG = LoggerFactory.getLogger(Activator.class); private static final String CONFIG_PID = "org.apache.cxf.features.logging"; @@ -71,6 +77,8 @@ public class Activator implements BundleActivator { Long inMemThreshold = Long.valueOf(getValue(config, "inMemThresHold", "-1")); Boolean logMultipart = Boolean.valueOf(getValue(config, "logMultipart", "true")); Boolean logBinary = Boolean.valueOf(getValue(config, "logBinary", "false")); + Set<String> sensitiveElementNames = getTrimmedSet(config, "sensitiveElementNames"); + Set<String> sensitiveProtocolHeaderNames = getTrimmedSet(config, "sensitiveProtocolHeaderNames"); if (limit != null) { logging.setLimit(limit); @@ -91,6 +99,14 @@ public class Activator implements BundleActivator { if (logBinary != null) { logging.setLogBinary(logBinary); } + + if (!sensitiveElementNames.isEmpty()) { + logging.setSensitiveElementNames(sensitiveElementNames); + } + + if (!sensitiveProtocolHeaderNames.isEmpty()) { + logging.setSensitiveProtocolHeaderNames(sensitiveProtocolHeaderNames); + } if (intentReg == null) { Dictionary<String, Object> properties = new Hashtable<>(); @@ -112,6 +128,15 @@ public class Activator implements BundleActivator { } } + @SuppressWarnings("rawtypes") + private Set<String> getTrimmedSet(Dictionary config, String propertyKey) { + return new HashSet<>( + Arrays.stream(String.valueOf(getValue(config, propertyKey, "")).split(",")) + .map(String::trim) + .filter(not(String::isEmpty)) + .collect(Collectors.toSet())); + } + @SuppressWarnings("rawtypes") private String getValue(Dictionary config, String key, String defaultValue) { if (config == null) { diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java index fae7bfca2b..514fcfa63a 100644 --- a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java +++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java @@ -92,7 +92,7 @@ public class MaskSensitiveHelperTest { } @Test - public void shouldReplaceSensitiveDataIn() { + public void shouldReplaceSensitiveDataInWithAdd() { // Arrange final LoggingInInterceptor inInterceptor = new LoggingInInterceptor(logEventSender); inInterceptor.addSensitiveElementNames(SENSITIVE_ELEMENTS); @@ -113,7 +113,28 @@ public class MaskSensitiveHelperTest { } @Test - public void shouldReplaceSensitiveDataOut() throws IOException { + public void shouldReplaceSensitiveDataInWithSet() { + // Arrange + final LoggingInInterceptor inInterceptor = new LoggingInInterceptor(logEventSender); + inInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS); + + final Message message = prepareInMessage(); + + // Act + Collection<PhaseInterceptor<? extends Message>> interceptors = inInterceptor.getAdditionalInterceptors(); + for (PhaseInterceptor intercept : interceptors) { + intercept.handleMessage(message); + } + inInterceptor.handleMessage(message); + + // Verify + LogEvent event = logEventSender.getLogEvent(); + assertNotNull(event); + assertEquals(maskedContent, event.getPayload()); + } + + @Test + public void shouldReplaceSensitiveDataOutWithAdd() throws IOException { // Arrange final LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor(logEventSender); outInterceptor.addSensitiveElementNames(SENSITIVE_ELEMENTS); @@ -133,6 +154,27 @@ public class MaskSensitiveHelperTest { assertEquals(maskedContent, event.getPayload()); } + @Test + public void shouldReplaceSensitiveDataOutWithSet() throws IOException { + // Arrange + final LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor(logEventSender); + outInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS); + + final Message message = prepareOutMessage(); + + // Act + outInterceptor.handleMessage(message); + byte[] payload = loggingContent.getBytes(StandardCharsets.UTF_8); + OutputStream out = message.getContent(OutputStream.class); + out.write(payload); + out.close(); + + // Verify + LogEvent event = logEventSender.getLogEvent(); + assertNotNull(event); + assertEquals(maskedContent, event.getPayload()); + } + @Test public void shouldNotReplaceSensitiveDataEmptyExpression() throws IOException { // Arrange
