|
5 | 5 | # the file COPYING, distributed as part of this software.
|
6 | 6 | # -----------------------------------------------------------------------------
|
7 | 7 | import json
|
| 8 | +from urllib.parse import urlparse, urlunparse |
8 | 9 |
|
9 | 10 | from tornado.log import access_log
|
10 | 11 |
|
11 | 12 | from .prometheus.log_functions import prometheus_log_method
|
12 | 13 |
|
| 14 | +# url params to be scrubbed if seen |
| 15 | +# any url param that *contains* one of these |
| 16 | +# will be scrubbed from logs |
| 17 | +_SCRUB_PARAM_KEYS = {"token", "auth", "key", "code", "state", "xsrf"} |
| 18 | + |
| 19 | + |
| 20 | +def _scrub_uri(uri: str) -> str: |
| 21 | + """scrub auth info from uri""" |
| 22 | + parsed = urlparse(uri) |
| 23 | + if parsed.query: |
| 24 | + # check for potentially sensitive url params |
| 25 | + # use manual list + split rather than parsing |
| 26 | + # to minimally perturb original |
| 27 | + parts = parsed.query.split("&") |
| 28 | + changed = False |
| 29 | + for i, s in enumerate(parts): |
| 30 | + key, sep, value = s.partition("=") |
| 31 | + for substring in _SCRUB_PARAM_KEYS: |
| 32 | + if substring in key: |
| 33 | + parts[i] = f"{key}{sep}[secret]" |
| 34 | + changed = True |
| 35 | + if changed: |
| 36 | + parsed = parsed._replace(query="&".join(parts)) |
| 37 | + return urlunparse(parsed) |
| 38 | + return uri |
| 39 | + |
13 | 40 |
|
14 | 41 | def log_request(handler):
|
15 | 42 | """log a bit more information about each request than tornado's default
|
@@ -41,13 +68,13 @@ def log_request(handler):
|
41 | 68 | status=status,
|
42 | 69 | method=request.method,
|
43 | 70 | ip=request.remote_ip,
|
44 |
| - uri=request.uri, |
| 71 | + uri=_scrub_uri(request.uri), |
45 | 72 | request_time=request_time,
|
46 | 73 | )
|
47 | 74 | msg = "{status} {method} {uri} ({ip}) {request_time:.2f}ms"
|
48 | 75 | if status >= 400:
|
49 | 76 | # log bad referers
|
50 |
| - ns["referer"] = request.headers.get("Referer", "None") |
| 77 | + ns["referer"] = _scrub_uri(request.headers.get("Referer", "None")) |
51 | 78 | msg = msg + " referer={referer}"
|
52 | 79 | if status >= 500 and status != 502:
|
53 | 80 | # Log a subset of the headers if it caused an error.
|
|
0 commit comments