This is an automated email from the ASF dual-hosted git repository. ashakirin pushed a commit to branch feature/CXF-8099_mask_sensitive_logging_elements in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/feature/CXF-8099_mask_sensitive_logging_elements by this push: new 6cf4ea9 CXF-8099: introduced sensitive headers 6cf4ea9 is described below commit 6cf4ea9cc1340af99a3774e43c4064e58cc4e66b Author: ashakirin <49843238+ashakirin-tal...@users.noreply.github.com> AuthorDate: Mon Jul 6 02:00:17 2020 +0200 CXF-8099: introduced sensitive headers --- .../ext/logging/AbstractLoggingInterceptor.java | 12 ++++--- .../org/apache/cxf/ext/logging/LoggingFeature.java | 31 +++++++++++++--- .../cxf/ext/logging/MaskSensitiveHelper.java | 42 +++++++++++++++------- ...itiveTest.java => MaskSensitiveHelperTest.java} | 23 ++++++++---- 4 files changed, 79 insertions(+), 29 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 91a4adc..b4982c4 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 @@ -46,7 +46,7 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto protected LogEventSender sender; protected final DefaultLogEventMapper eventMapper = new DefaultLogEventMapper(); - private MaskSensitiveHelper maskSensitiveHelper; + final MaskSensitiveHelper maskSensitiveHelper = new MaskSensitiveHelper(); public AbstractLoggingInterceptor(String phase, LogEventSender sender) { super(phase); @@ -78,8 +78,12 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto return threshold; } - public void setSensitiveElementNames(final List<String> sensitiveElementNames) { - maskSensitiveHelper = new MaskSensitiveHelper(sensitiveElementNames); + public void addSensitiveElementNames(final List<String> sensitiveElementNames) { + maskSensitiveHelper.addSensitiveElementNames(sensitiveElementNames); + } + + public void addSensitiveHeaders(final List<String> sensitiveHeaders) { + maskSensitiveHelper.addSensitiveHeaders(sensitiveHeaders); } public void setPrettyLogging(boolean prettyLogging) { @@ -116,7 +120,7 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto } protected String maskSensitiveElements(final Message message, String originalLogString) { - return Optional.ofNullable(maskSensitiveHelper) + return Optional.of(maskSensitiveHelper) .map(h -> h.maskSensitiveElements(message, originalLogString)) .orElse(originalLogString); } 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 afd905f..c490588 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,8 +147,24 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> { * </pre> * @param sensitiveElementNames list of sensitive element names to be replaced */ - public void setSensitiveElementNames(final List<String> sensitiveElementNames) { - delegate.setSensitiveElementNames(sensitiveElementNames); + public void addSensitiveElementNames(final List<String> sensitiveElementNames) { + delegate.addSensitiveElementNames(sensitiveElementNames); + } + + /** + * Sets 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 sensitiveHeaders list of sensitive element names to be replaced + */ + public void addSensitiveHeaders(final List<String> sensitiveHeaders) { + delegate.addSensitiveHeaders(sensitiveHeaders); } public static class Portable implements AbstractPortableFeature { @@ -236,9 +252,14 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> { addOutBinaryContentMediaTypes(mediaTypes); } - public void setSensitiveElementNames(final List<String> sensitiveElementNames) { - in.setSensitiveElementNames(sensitiveElementNames); - out.setSensitiveElementNames(sensitiveElementNames); + public void addSensitiveElementNames(final List<String> sensitiveElementNames) { + in.addSensitiveElementNames(sensitiveElementNames); + out.addSensitiveElementNames(sensitiveElementNames); + } + + public void addSensitiveHeaders(final List<String> sensitiveHeaders) { + in.addSensitiveHeaders(sensitiveHeaders); + out.addSensitiveHeaders(sensitiveHeaders); } } } 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 4d50da6..029a561 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 @@ -18,7 +18,9 @@ */ package org.apache.cxf.ext.logging; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.apache.cxf.message.Message; @@ -26,44 +28,58 @@ public class MaskSensitiveHelper { private static final String ELEMENT_NAME_TEMPLATE = "-ELEMENT_NAME-"; private static final String MATCH_PATTERN_XML = "<-ELEMENT_NAME->(.*?)</-ELEMENT_NAME->"; private static final String MATCH_PATTERN_JSON = "\"-ELEMENT_NAME-\"[ \\t]*:[ \\t]*\"(.*?)\""; + private static final String MATCH_PATTERN_HEADER = "-ELEMENT_NAME-[ \\t]*=([^,}])+"; private static final String REPLACEMENT_PATTERN_XML = "<-ELEMENT_NAME->XXX</-ELEMENT_NAME->"; private static final String REPLACEMENT_PATTERN_JSON = "\"-ELEMENT_NAME-\": \"XXX\""; + private static final String REPLACEMENT_PATTERN_HEADER = "-ELEMENT_NAME-=XXX"; private static final String XML_CONTENT = "xml"; private static final String HTML_CONTENT = "html"; private static final String JSON_CONTENT = "json"; - final List<String> sensitiveElementNames; + final List<String> sensitiveElementNames = new ArrayList<>(); + final List<String> sensitiveHeaders = new ArrayList<>(); - public MaskSensitiveHelper(final List<String> sensitiveElementNames) { - this.sensitiveElementNames = sensitiveElementNames; + public void addSensitiveElementNames(final List<String> inSensitiveElementNames) { + this.sensitiveElementNames.addAll(inSensitiveElementNames); + } + + public void addSensitiveHeaders(final List<String> inSensitiveHeaders) { + this.sensitiveHeaders.addAll(inSensitiveHeaders); } public String maskSensitiveElements( final Message message, final String originalLogString) { - if ((sensitiveElementNames == null) || sensitiveElementNames.isEmpty()) { + if (sensitiveElementNames.isEmpty() || message == null) { return originalLogString; } - String contentType = (String) message.get(Message.CONTENT_TYPE); + final String contentType = (String) message.get(Message.CONTENT_TYPE); if (contentType.toLowerCase().contains(XML_CONTENT) || contentType.toLowerCase().contains(HTML_CONTENT)) { - return applyExpression(originalLogString, MATCH_PATTERN_XML, REPLACEMENT_PATTERN_XML); + return applyMasks(originalLogString, MATCH_PATTERN_XML, REPLACEMENT_PATTERN_XML); } else if (contentType.toLowerCase().contains(JSON_CONTENT)) { - return applyExpression(originalLogString, MATCH_PATTERN_JSON, REPLACEMENT_PATTERN_JSON); - } else { - return originalLogString; + return applyMasks(originalLogString, MATCH_PATTERN_JSON, REPLACEMENT_PATTERN_JSON); } + return originalLogString; + } + + private String applyMasks(String originalLogString, String matchElementPattern, String replacementElementPattern) { + return Optional.ofNullable(originalLogString) + .map(s -> applyExpression(s, MATCH_PATTERN_HEADER, REPLACEMENT_PATTERN_HEADER, sensitiveHeaders)) + .map(s -> applyExpression(s, matchElementPattern, replacementElementPattern, sensitiveElementNames)) + .orElse(originalLogString); } private String applyExpression( final String originalLogString, final String matchPatternTemplate, - final String replacementTemplate) { + final String replacementTemplate, + final List<String> sensitiveNames) { String resultString = originalLogString; - for (final String elementName : sensitiveElementNames) { - final String matchPattern = matchPatternTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, elementName); - final String replacement = replacementTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, elementName); + for (final String sensitiveName : sensitiveNames) { + final String matchPattern = matchPatternTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, sensitiveName); + final String replacement = replacementTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, sensitiveName); resultString = resultString.replaceAll(matchPattern, replacement); } return resultString; diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java similarity index 84% rename from rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java rename to rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java index 997dcb9..8e30d5f 100644 --- a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java +++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveHelperTest.java @@ -43,7 +43,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(Parameterized.class) -public class MaskSensitiveTest { +public class MaskSensitiveHelperTest { + + private static final String SENSITIVE_LOGGING_CONTENT_HEADER = + "{Accept=application/json, SessionId = sensitive data , Authorization=sensitive data}"; + private static final String MASKED_LOGGING_CONTENT_HEADER = + "{Accept=application/json, SessionId=XXX, Authorization=XXX}"; private static final String SENSITIVE_LOGGING_CONTENT_XML = "<user>testUser</user><password>my secret password</password>"; @@ -56,6 +61,7 @@ public class MaskSensitiveTest { "\"user\":\"testUser\", \"password\": \"XXX\""; private static final List<String> SENSITIVE_ELEMENTS = Arrays.asList("password"); + private static final List<String> SENSITIVE_HEADERS = Arrays.asList("SessionId", "Authorization"); private static final String APPLICATION_XML = "application/xml"; private static final String APPLICATION_JSON = "application/json"; @@ -63,7 +69,7 @@ public class MaskSensitiveTest { private final String maskedContent; private final String contentType; private LogEventSenderMock logEventSender = new LogEventSenderMock(); - public MaskSensitiveTest(String loggingContent, String maskedContent, String contentType) { + public MaskSensitiveHelperTest(String loggingContent, String maskedContent, String contentType) { this.loggingContent = loggingContent; this.maskedContent = maskedContent; this.contentType = contentType; @@ -71,17 +77,19 @@ public class MaskSensitiveTest { @Parameterized.Parameters public static Collection primeNumbers() { - return Arrays.asList(new Object[][]{ + return Arrays.asList(new Object[][] { {SENSITIVE_LOGGING_CONTENT_XML, MASKED_LOGGING_CONTENT_XML, APPLICATION_XML}, - {SENSITIVE_LOGGING_CONTENT_JSON, MASKED_LOGGING_CONTENT_JSON, APPLICATION_JSON} + {SENSITIVE_LOGGING_CONTENT_JSON, MASKED_LOGGING_CONTENT_JSON, APPLICATION_JSON}, + {SENSITIVE_LOGGING_CONTENT_HEADER, MASKED_LOGGING_CONTENT_HEADER, APPLICATION_JSON} }); } @Test - public void shouldReplaceSensitiveDataIn() throws IOException { + public void shouldReplaceSensitiveDataIn() { // Arrange final LoggingInInterceptor inInterceptor = new LoggingInInterceptor(logEventSender); - inInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS); + inInterceptor.addSensitiveElementNames(SENSITIVE_ELEMENTS); + inInterceptor.addSensitiveHeaders(SENSITIVE_HEADERS); final Message message = prepareInMessage(); @@ -102,7 +110,8 @@ public class MaskSensitiveTest { public void shouldReplaceSensitiveDataOut() throws IOException { // Arrange final LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor(logEventSender); - outInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS); + outInterceptor.addSensitiveElementNames(SENSITIVE_ELEMENTS); + outInterceptor.addSensitiveHeaders(SENSITIVE_HEADERS); final Message message = prepareOutMessage();