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

masked sensitive data in logs #507

Merged
merged 4 commits into from
Jul 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions splunklib/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from __future__ import absolute_import

import io
import json
import logging
import socket
import ssl
Expand Down Expand Up @@ -60,12 +61,17 @@
"HTTPError"
]

SENSITIVE_KEYS = ['Authorization', 'Cookie', 'action.email.auth_password', 'auth', 'auth_password', 'clear_password', 'clientId',
'crc-salt', 'encr_password', 'oldpassword', 'passAuth', 'password', 'session', 'suppressionKey',
'token']

# If you change these, update the docstring
# on _authority as well.
DEFAULT_HOST = "localhost"
DEFAULT_PORT = "8089"
DEFAULT_SCHEME = "https"


def _log_duration(f):
@wraps(f)
def new_f(*args, **kwargs):
Expand All @@ -77,6 +83,28 @@ def new_f(*args, **kwargs):
return new_f


def mask_sensitive_data(data):
'''
Masked sensitive fields data for logging purpose
'''
if not isinstance(data, dict):
try:
data = json.loads(data)
except Exception as ex:
return data

# json.loads will return "123"(str) as 123(int), so return the data if it's not 'dict' type
if not isinstance(data, dict):
Copy link
Contributor

Choose a reason for hiding this comment

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

Duplicate to lines 87-91?

return data
mdata = {}
for k, v in data.items():
if k in SENSITIVE_KEYS:
mdata[k] = "******"
else:
mdata[k] = mask_sensitive_data(v)
return mdata


def _parse_cookies(cookie_str, dictionary):
"""Tries to parse any key-value pairs of cookies in a string,
then updates the the dictionary with any key-value pairs found.
Expand Down Expand Up @@ -630,7 +658,7 @@ def delete(self, path_segment, owner=None, app=None, sharing=None, **query):
"""
path = self.authority + self._abspath(path_segment, owner=owner,
app=app, sharing=sharing)
logger.debug("DELETE request to %s (body: %s)", path, repr(query))
logger.debug("DELETE request to %s (body: %s)", path, mask_sensitive_data(query))
response = self.http.delete(path, self._auth_headers, **query)
return response

Expand Down Expand Up @@ -693,7 +721,7 @@ def get(self, path_segment, owner=None, app=None, headers=None, sharing=None, **

path = self.authority + self._abspath(path_segment, owner=owner,
app=app, sharing=sharing)
logger.debug("GET request to %s (body: %s)", path, repr(query))
logger.debug("GET request to %s (body: %s)", path, mask_sensitive_data(query))
all_headers = headers + self.additional_headers + self._auth_headers
response = self.http.get(path, all_headers, **query)
return response
Expand Down Expand Up @@ -772,12 +800,7 @@ def post(self, path_segment, owner=None, app=None, sharing=None, headers=None, *

path = self.authority + self._abspath(path_segment, owner=owner, app=app, sharing=sharing)

# To avoid writing sensitive data in debug logs
endpoint_having_sensitive_data = ["/storage/passwords"]
if any(endpoint in path for endpoint in endpoint_having_sensitive_data):
logger.debug("POST request to %s ", path)
else:
logger.debug("POST request to %s (body: %s)", path, repr(query))
logger.debug("POST request to %s (body: %s)", path, mask_sensitive_data(query))
all_headers = headers + self.additional_headers + self._auth_headers
response = self.http.post(path, all_headers, **query)
return response
Expand Down Expand Up @@ -844,8 +867,7 @@ def request(self, path_segment, method="GET", headers=None, body={},

all_headers = headers + self.additional_headers + self._auth_headers
logger.debug("%s request to %s (headers: %s, body: %s)",
method, path, str(all_headers), repr(body))

method, path, str(mask_sensitive_data(dict(all_headers))), mask_sensitive_data(body))
if body:
body = _encode(**body)

Expand Down