Add method for getting redacted copy of context
There are times, such as in oslo.messaging notifications, when we'd like a context object to be stripped of any secrets. This adds a method to RequestContext, redacted_copy(), which returns a copy of that context, carrying over an allowlist of fields only, leaving secrets behind. Related-bug: 2030976 Change-Id: Ie4a8eb784c505c41ec5fcd4cba091cc555146763
This commit is contained in:
parent
5168ccdf01
commit
059f9ba16e
@ -387,6 +387,42 @@ class RequestContext(object):
|
||||
"""
|
||||
return self.global_request_id or self.request_id
|
||||
|
||||
def redacted_copy(self) -> 'RequestContext':
|
||||
"""Return a copy of the context with sensitive fields redacted.
|
||||
|
||||
This is useful for creating a context that can be safely logged.
|
||||
|
||||
:returns: A copy of the context with sensitive fields redacted.
|
||||
"""
|
||||
return self.__class__(
|
||||
user_id=self.user_id,
|
||||
project_id=self.project_id,
|
||||
domain_id=self.domain_id,
|
||||
user_domain_id=self.user_domain_id,
|
||||
project_domain_id=self.project_domain_id,
|
||||
request_id=self.request_id,
|
||||
roles=self.roles,
|
||||
user_name=self.user_name,
|
||||
project_name=self.project_name,
|
||||
domain_name=self.domain_name,
|
||||
user_domain_name=self.user_domain_name,
|
||||
project_domain_name=self.project_domain_name,
|
||||
service_user_id=self.service_user_id,
|
||||
service_user_domain_id=self.service_user_domain_id,
|
||||
service_user_domain_name=self.service_user_domain_name,
|
||||
service_project_id=self.service_project_id,
|
||||
service_project_name=self.service_project_name,
|
||||
service_project_domain_id=self.service_project_domain_id,
|
||||
service_project_domain_name=self.service_project_domain_name,
|
||||
service_roles=self.service_roles,
|
||||
global_request_id=self.global_request_id,
|
||||
system_scope=self.system_scope,
|
||||
user=self.user,
|
||||
domain=self.domain,
|
||||
user_domain=self.user_domain,
|
||||
project_domain=self.project_domain
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@_renamed_kwarg('user', 'user_id')
|
||||
@_renamed_kwarg('domain', 'domain_id')
|
||||
|
@ -518,11 +518,25 @@ class ContextTest(test_base.BaseTestCase):
|
||||
self.assertEqual(user_domain_name, d['user_domain_name'])
|
||||
self.assertEqual(project_domain_name, d['project_domain_name'])
|
||||
|
||||
def test_auth_token_info_removed(self):
|
||||
def test_auth_token_info_removed_logging_values(self):
|
||||
ctx = TestContext(auth_token_info={'auth_token': 'topsecret'})
|
||||
d = ctx.get_logging_values()
|
||||
self.assertNotIn('auth_token_info', d)
|
||||
|
||||
def test_auth_token_info_removed_redacted_context(self):
|
||||
userid = 'foo'
|
||||
ctx = TestContext(
|
||||
auth_token_info={'auth_token': 'topsecret'},
|
||||
service_token="1234567",
|
||||
auth_token="8901234",
|
||||
user_id=userid)
|
||||
safe_ctxt = ctx.redacted_copy()
|
||||
self.assertIsNone(safe_ctxt.auth_token_info)
|
||||
self.assertIsNone(safe_ctxt.service_token)
|
||||
self.assertIsNone(safe_ctxt.auth_token)
|
||||
self.assertEqual(userid, safe_ctxt.user_id)
|
||||
self.assertNotEqual(ctx, safe_ctxt)
|
||||
|
||||
def test_dict_empty_user_identity(self):
|
||||
ctx = context.RequestContext()
|
||||
d = ctx.to_dict()
|
||||
|
7
releasenotes/notes/redacted-copy-efd02c83c287451f.yaml
Normal file
7
releasenotes/notes/redacted-copy-efd02c83c287451f.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
features:
|
||||
- |
|
||||
Added ``redacted_copy`` method to ``RequestContext``. This returns a copy
|
||||
of the context with secrets redacted. This will allow downstreams that
|
||||
inherit and enhance the ``RequestContext`` can include the additional data
|
||||
in the redacted copy if they wish by overriding the ``redacted_copy``
|
||||
method.
|
Loading…
Reference in New Issue
Block a user