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

GitHub#454 Sanitise HTTP message logs #457

Merged
merged 26 commits into from
Sep 27, 2019

Conversation

OwenLindsell
Copy link
Contributor

Added two new configuration options to hide headers and cookies in request logging:

    request-logging:
      hideHeaders:
          - Content-Type
      hideCookies:
          - sessionID
          - samlToken

The hideHeaders and hideCookies options take a list of header or cookie names. Any header or cookie in these lists will be obfuscated in the logged message output e.g.

headers=[Content-Type:****, Cookie:sessionID=****;samlToken=****]

Owen Lindsell added 2 commits September 6, 2019 16:47
 - removed formatting from everywhere except HttpErrorStatusCauseLogger and HttpRequestMessageLogger
 - removed singleton
 - static import for emptyList
@mikkokar
Copy link
Contributor

mikkokar commented Sep 9, 2019

Fixes #454.

Owen Lindsell added 4 commits September 16, 2019 15:56
header toString reverted to use '=' instead of ':'
request toString reverted to use 'uri' instead of 'url'
added null checks for HttpMessageFormatter
made HttpMessageFormatter an interface and added default implementation
some other general tidying
 - added null checks for HttpMessageFormatter
 - added default value for HttpMessageFormatter
 - removed redundant null checks
 - removed redundant HttpMessageFormatter
 - general tidying
Owen Lindsell added 13 commits September 17, 2019 09:04
 - removed formatting from everywhere except HttpErrorStatusCauseLogger and HttpRequestMessageLogger
 - removed singleton
 - static import for emptyList
header toString reverted to use '=' instead of ':'
request toString reverted to use 'uri' instead of 'url'
added null checks for HttpMessageFormatter
made HttpMessageFormatter an interface and added default implementation
some other general tidying
 - added null checks for HttpMessageFormatter
 - added default value for HttpMessageFormatter
 - removed redundant null checks
 - removed redundant HttpMessageFormatter
 - general tidying
…itise-http-messages

# Conflicts:
#	components/common/src/main/java/com/hotels/styx/common/format/DefaultHttpMessageFormatter.java
Copy link
Contributor

@mikkokar mikkokar left a comment

Choose a reason for hiding this comment

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

Hi. It is pretty good. However I spotted an issue with access logging I feel we need to address before merging.

Also, please add a small Kotlin functional test to exercise this feature. Something as simple as configuring this feature to remove a header and a cookie, and then checking the access logs that they has been masked.

@@ -112,10 +112,10 @@ class HttpOutboundMessageLoggingSpec extends FunSpec
assertThat(logger.log.size(), is(2))

assertThat(logger.log(), hasItem(loggingEvent(INFO,
"requestId=[-a-z0-9]+, request=\\{method=GET, uri=http://localhost:[0-9]+/foobar, origin=\"localhost:[0-9]+\", headers=\\[.*\\]}")))
"requestId=[-a-z0-9]+, request=LiveHttpRequest\\{version=HTTP/1.1, method=GET, uri=http://localhost:[0-9]+/foobar, headers=\\[.*\\], id=[-a-z0-9]+}, origin=appOne:generic-app-01:localhost:[0-9]+")))
Copy link
Contributor

Choose a reason for hiding this comment

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

I see we are now exposing class names (implementation detail) in our access logs (a documented feature).

Let's remove them from the access logs. The class names are okay for error logs etc but not here. As a documented feature we need to consider the access logs like any other external interface with possible backwards compatibility implications.

Therefore please remove the class name from this message.

Also, I'd move the origin either in its original place, or in front of the request message. My reasoning is:

  1. Trying to keep the message format as similar as possible

  2. Headers field is often really large, and therefore should appear after all "fixed size" attributes. This is because it is difficult to find and see the fixed size attributes after a large body of header text.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The origin isn't part of the request, so I moved it out. Good point about long headers field. I'll move it to in front.

Copy link
Contributor

Choose a reason for hiding this comment

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

The origin isn't part of the request, so I moved it out.

Yeah, it was a right thing to do.

Copy link
Contributor Author

@OwenLindsell OwenLindsell Sep 18, 2019

Choose a reason for hiding this comment

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

moved to front and removed class name

Owen Lindsell and others added 2 commits September 18, 2019 09:24
…order of logging items so request is at end - added headers to StaticResponseHandler to support kotlin test
return new StaticResponseHandler(config.status, config.response, nettyHeaders);
}

private HttpHeaders buildNettyHeaders(StaticResponseConfig config) {
Copy link
Contributor

Choose a reason for hiding this comment

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

A small comment: "Netty headers".

Copy link
Contributor

@mikkokar mikkokar left a comment

Choose a reason for hiding this comment

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

Looks good 🥇

Please fix the static analysis failures, and also consider couple of small small cosmetic comments.

Approving now.

feature("Styx request/response logging") {

scenario("Logger should hide cookies and headers") {
val proxyHost = "${styxServer.proxyHttpAddress().hostName}:${styxServer.proxyHttpAddress().port}"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use StyxServer.proxyHttpHostHeader extension method from support/styxServerProvider.kt to simplify proxyHost.

val proxyHost = "${styxServer.proxyHttpAddress().hostName}:${styxServer.proxyHttpAddress().port}"

client.send(HttpRequest.get("/a/path")
.header(HttpHeaderNames.HOST, proxyHost)
Copy link
Contributor

Choose a reason for hiding this comment

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

Static imports x2 ^^^.


val styxServer = StyxServer(StyxServerComponents.Builder()
.styxConfig(StyxConfig.fromYaml(yamlText))
.build())
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a class called StyxServerProvider in support/StyxServerProvider.kt. It provides a unique reference point to a Styx server while allowing it to be restarted, and thus cleared from any acquired state`, between the tests.

You don't really have to use it in this test, but could make this more consistent with others.

.header("cookie", "cookie1=c1;cookie2=c2")
.build())
.toMono()
.block()!!
Copy link
Contributor

Choose a reason for hiding this comment

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

There is also a wait extension method that combines .toMono().block()!!.

@OwenLindsell OwenLindsell merged commit ed1b6fd into ExpediaGroup:master Sep 27, 2019
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