This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 4.0.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 92f01e05872f63a0212af9b73076ab8acda38cde Author: Dmytro Sylaiev <[email protected]> AuthorDate: Sun Nov 24 18:38:25 2024 +0200 CXF-9082: Allow to modify sensitive header list (#2150) * CXF-9082: Allow to modify sensitive header list * Fix any sensitive information is printed to the logs * CXF-9082: Make sensitive headers a contextual prop (cherry picked from commit 537d1ddcf883c398604346392b3af1d8404e1b09) --- .../org/apache/cxf/transport/http/Headers.java | 31 ++++++++++++--------- .../org/apache/cxf/transport/http/HeadersTest.java | 32 +++++++++++++++++++--- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Headers.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Headers.java index 012e9f9b49..174d590885 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Headers.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/Headers.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; import java.util.logging.Level; @@ -70,8 +71,9 @@ public class Headers { private static final TimeZone TIME_ZONE_GMT = TimeZone.getTimeZone("GMT"); private static final Logger LOG = LogUtils.getL7dLogger(Headers.class); - private static final List<String> SENSITIVE_HEADERS = Arrays.asList("Authorization", "Proxy-Authorization"); - private static final List<Object> SENSITIVE_HEADER_MARKER = Arrays.asList("***"); + private static final String SENSITIVE_HEADERS_PROP_NAME = "org.apache.http.sensitive.headers"; + private static final Set<String> DEFAULT_SENSITIVE_HEADERS = Set.of("Authorization", "Proxy-Authorization"); + private static final List<Object> SENSITIVE_HEADER_MARKER = Collections.singletonList("***"); private static final String ALLOW_LOGGING_SENSITIVE_HEADERS = "allow.logging.sensitive.headers"; private final Message message; @@ -107,11 +109,11 @@ public class Headers { * filtered keys), so it should be used sparingly - i.e. only when debug is * enabled. */ - static String toString(Map<String, List<Object>> headers, boolean logSensitiveHeaders) { + static String toString(Message message, boolean logSensitiveHeaders) { Map<String, List<Object>> filteredHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - filteredHeaders.putAll(headers); + filteredHeaders.putAll(CastUtils.cast(getSetProtocolHeaders(message))); if (!logSensitiveHeaders) { - for (String filteredKey : SENSITIVE_HEADERS) { + for (String filteredKey : getSensitiveHeaders(message)) { filteredHeaders.put(filteredKey, SENSITIVE_HEADER_MARKER); } } @@ -306,16 +308,17 @@ public class Headers { * * @param logger The Logger to log to. * @param level The Logging Level. - * @param headersMap The Message protocol headers. + * @param message The Message. * @param logSensitiveHeaders whether to log sensitive headers */ static void logProtocolHeaders(Logger logger, Level level, - Map<String, List<Object>> headersMap, + Message message, boolean logSensitiveHeaders) { if (logger.isLoggable(level)) { + Map<String, List<Object>> headersMap = CastUtils.cast(getSetProtocolHeaders(message)); for (Map.Entry<String, List<Object>> entry : headersMap.entrySet()) { String key = entry.getKey(); - boolean sensitive = !logSensitiveHeaders && SENSITIVE_HEADERS.contains(key); + boolean sensitive = !logSensitiveHeaders && getSensitiveHeaders(message).contains(key); List<Object> headerList = sensitive ? SENSITIVE_HEADER_MARKER : entry.getValue(); for (Object value : headerList) { logger.log(level, key + ": " @@ -366,8 +369,7 @@ public class Headers { transferProtocolHeadersToURLConnection(connection); - Map<String, List<Object>> theHeaders = CastUtils.cast(headers); - logProtocolHeaders(LOG, Level.FINE, theHeaders, logSensitiveHeaders()); + logProtocolHeaders(LOG, Level.FINE, message, logSensitiveHeaders()); } public String determineContentType() { @@ -451,9 +453,7 @@ public class Headers { headers.put(Message.CONTENT_TYPE, Collections.singletonList(req.getContentType())); } if (LOG.isLoggable(Level.FINE)) { - Map<String, List<Object>> theHeaders = CastUtils.cast(headers); - LOG.log(Level.FINE, "Request Headers: " + toString(theHeaders, - logSensitiveHeaders())); + LOG.log(Level.FINE, "Request Headers: " + toString(message, logSensitiveHeaders())); } } @@ -580,4 +580,9 @@ public class Headers { public static String toHttpLanguage(Locale locale) { return locale.toString().replace('_', '-'); } + + static Set<String> getSensitiveHeaders(Message message) { + return MessageUtils.getContextualStrings(message, SENSITIVE_HEADERS_PROP_NAME, + DEFAULT_SENSITIVE_HEADERS); + } } diff --git a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HeadersTest.java b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HeadersTest.java index 4caadf0c28..537893c6d0 100755 --- a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HeadersTest.java +++ b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HeadersTest.java @@ -94,13 +94,15 @@ public class HeadersTest { @Test public void sensitiveHeadersTest() { + Message message = new MessageImpl(); Map<String, List<Object>> headerMap = new HashMap<>(); headerMap.put("Authorization", Arrays.asList("FAIL")); headerMap.put("Proxy-Authorization", Arrays.asList("FAIL")); headerMap.put("Content-Type", Arrays.asList("application/xml")); headerMap.put("Accept", Arrays.asList("text/plain")); + message.put(Message.PROTOCOL_HEADERS, headerMap); - String loggedString = Headers.toString(headerMap, false); + String loggedString = Headers.toString(message, false); assertFalse("The value of a sensitive header could be logged: " + loggedString, loggedString.contains("FAIL")); assertTrue("The value of a non-sensitive header would not be logged: " + loggedString, loggedString.contains("application/xml") && loggedString.contains("text/plain")); @@ -109,6 +111,26 @@ public class HeadersTest { && loggedString.contains("Accept") && loggedString.contains("Content-Type")); } + @Test + public void customSensitiveHeadersTest() { + Message message = new MessageImpl(); + Map<String, List<Object>> headerMap = new HashMap<>(); + headerMap.put("Authorization", Arrays.asList("FAIL")); + headerMap.put("MyCustomHeader", Arrays.asList("Value1")); + headerMap.put("NotMyCustomHeader", Arrays.asList("Value2")); + message.put(Message.PROTOCOL_HEADERS, headerMap); + message.put("org.apache.http.sensitive.headers", "Authorization,MyCustomHeader"); + + String loggedString = Headers.toString(message, false); + + assertFalse("The value of a custom sensitive header should not be logged: " + + loggedString, loggedString.contains("FAIL")); + assertFalse("The value of a custom sensitive header should not be logged: " + + loggedString, loggedString.contains("Value1")); + assertTrue("The value of a not sensitive header should be logged: " + + loggedString, loggedString.contains("Value2")); + } + @Test public void logProtocolHeadersTest() { Map<String, List<Object>> headerMap = new HashMap<>(); @@ -116,6 +138,8 @@ public class HeadersTest { headerMap.put("Multivalue-Header", Arrays.asList("first", "second")); headerMap.put("Authorization", Arrays.asList("myPassword")); headerMap.put("Null-Header", Arrays.asList((String)null)); + Message message = new MessageImpl(); + message.put(Message.PROTOCOL_HEADERS, headerMap); //Set up test logger Logger logger = Logger.getAnonymousLogger(); @@ -159,7 +183,7 @@ public class HeadersTest { // no-op } }); - Headers.logProtocolHeaders(logger, Level.INFO, headerMap, false); + Headers.logProtocolHeaders(logger, Level.INFO, message, false); } @Test @@ -199,7 +223,7 @@ public class HeadersTest { assertEquals("Unexpected content-type determined - expected text/xml", "text/xml", headers.determineContentType()); } - + @Test public void httpLanguage() { Locale locale = new Locale("en", "US"); @@ -214,4 +238,4 @@ public class HeadersTest { locale = new Locale("es", ""); assertEquals("es", Headers.toHttpLanguage(locale)); } -} \ No newline at end of file +}
