Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redact HTTP headers on LoggingFeature #5025

Merged

Conversation

nunomsantos
Copy link
Contributor

@nunomsantos nunomsantos commented Apr 1, 2022

As talked on #5014, this allows configuring LoggingFeature with a list of HTTP headers to have their value redacted when printing to logs. By default, the Authorization header is redacted.

Example of a logged request/response with the Authorization header redacted (default behavior):

1 * Sending client request on thread main
1 > GET http://localhost:9998/echo-headers
1 > Authorization: [redacted]

1 * Client response received on thread main
1 < 200
1 < accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
1 < authorization: [redacted]
1 < connection: keep-alive
1 < Content-Length: 32
1 < Content-Type: text/plain
1 < host: localhost:9998
1 < user-agent: Jersey/2.36-SNAPSHOT (HttpUrlConnection 1.8.0_92)
This entity must (not) be logged

And an example with two headers configured to be redacted (overriding the default behavior of redacting the Authorization header):

1 * Sending client request on thread main
1 > GET http://localhost:9998/echo-headers
1 > Authorization: basic username:password
1 > X-Also-Redact-This-Header: [redacted]
1 > X-Redact-This-Header: [redacted]

1 * Client response received on thread main
1 < 200
1 < accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
1 < authorization: basic username:password
1 < connection: keep-alive
1 < Content-Length: 32
1 < Content-Type: text/plain
1 < host: localhost:9998
1 < user-agent: Jersey/2.36-SNAPSHOT (HttpUrlConnection 1.8.0_92)
1 < x-also-redact-this-header: [redacted]
1 < x-redact-this-header: [redacted]
This entity must (not) be logged

@nunomsantos
Copy link
Contributor Author

Hi, @senivam. Just noticed that I'm lowering the case on test assertions and I think that's not needed with the provided matcher. Please give me some time to check that.

ContainsHeaderMatcher is case-insensitive for header names.
@nunomsantos nunomsantos requested a review from senivam April 5, 2022 11:03
@nunomsantos
Copy link
Contributor Author

Hi, @senivam. Just noticed that I'm lowering the case on test assertions and I think that's not needed with the provided matcher. Please give me some time to check that.

Confirmed. Change pushed.

Copy link
Contributor

@senivam senivam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -165,6 +186,11 @@
* Client property for logging separator.
*/
public static final String LOGGING_FEATURE_SEPARATOR_CLIENT = LOGGING_FEATURE_CLIENT_PREFIX + SEPARATOR_POSTFIX;
/**
* Client property for configuring headers to be redacted.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add The headers are semicolon-separated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do. Please give me some time.

Copy link
Contributor Author

@nunomsantos nunomsantos Apr 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed changes to the Javadocs on the 3 variations of the property.

I checked if we could set a property multiple times and then get a collection, but it looked like that's not possible.
Can you confirm that? Please let me know if you think of a better way to do this.

@jansupol jansupol added this to the 2.36 milestone Apr 7, 2022
}

private static String normalize(String input) {
return input.trim().toLowerCase(Locale.ROOT);
Copy link
Contributor Author

@nunomsantos nunomsantos Apr 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just crossed my mind that maybe we should do a null check here. Not sure if it's possible for a null header ever to reach this point but could do it just to be on the safe side.
The problem would not be in the constructor usage, but when test(header) is called.

Thoughts, @jansupol @senivam?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's OK. This code final String header = headerEntry.getKey(); is NPE safe and this code

this.headersToRedact = headersToRedact.stream()
                   .filter(Objects::nonNull)
                   .filter(Predicates.not(String::isEmpty))
                   .map(RedactHeaderPredicate::normalize)
                   .collect(Collectors.toSet());

is NPE safe. Nothing else calls that predicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants