Always have username in CADF initiator

The current initiator object for CADF notifications does not include
the username of the user who initiated the action, which leads to
issues when using an LDAP backend and not having a direct way to
map a username to a user id.

This change makes it so that the initiator object for CADF
notifications always contains the username for a user as well
as the user id. This follows along with the CADF standard
for OpenStack[0].

[0] https://www.dmtf.org/sites/default/files/standards/documents/DSP2038_1.1.0.pdf#page=12

Closes-Bug: #1856904

Change-Id: I833e6e0d7792acf49f816050ad7a63e8ea4f702f
This commit is contained in:
Gage Hugo 2019-12-13 14:25:28 -06:00
parent 72cbaa91ff
commit 95edaaab06
3 changed files with 39 additions and 1 deletions

View File

@ -74,6 +74,7 @@ SAML_AUDIT_TYPE = 'http://docs.oasis-open.org/security/saml/v2.0'
_SUBSCRIBERS = {}
_notifier = None
SERVICE = 'identity'
PROVIDERS = provider_api.ProviderAPIs
ROOT_DOMAIN = '<<keystone.domain.root>>'
@ -529,6 +530,7 @@ def _get_request_audit_info(context, user_id=None):
if user_id:
initiator.user_id = user_id
initiator.id = utils.resource_uuid(user_id)
initiator = _add_username_to_initiator(initiator)
if project_id:
initiator.project_id = project_id
@ -565,6 +567,7 @@ class CadfNotificationWrapper(object):
target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
initiator = build_audit_initiator()
initiator.user_id = user_id
initiator = _add_username_to_initiator(initiator)
initiator.id = utils.resource_uuid(user_id)
try:
result = f(wrapped_self, user_id, *args, **kwargs)
@ -763,6 +766,8 @@ def _send_audit_notification(action, initiator, outcome, target,
service_id = i['id']
break
initiator = _add_username_to_initiator(initiator)
event = eventfactory.EventFactory().new_event(
eventType=cadftype.EVENTTYPE_ACTIVITY,
outcome=outcome,
@ -820,6 +825,19 @@ def _check_notification_opt_out(event_type, outcome):
return False
def _add_username_to_initiator(initiator):
"""Add the username to the initiator if missing."""
if hasattr(initiator, 'username'):
return initiator
try:
user_ref = PROVIDERS.identity_api.get_user(initiator.user_id)
initiator.username = user_ref['name']
except (exception.UserNotFound, AttributeError):
# Either user not found or no user_id, move along
pass
return initiator
emit_event = CadfNotificationWrapper

View File

@ -1156,7 +1156,7 @@ class CadfNotificationsWrapperTestCase(test_v3.RestfulTestCase):
'typeURI': 'service/security/account/user',
'host': {'address': 'localhost'},
'id': 'openstack:0a90d95d-582c-4efb-9cbc-e2ca7ca9c341',
'name': u'bccc2d9bfc2a46fd9e33bcf82f0b5c21'
'username': u'admin'
},
'target': {
'typeURI': 'service/security/account/user',
@ -1202,6 +1202,17 @@ class CadfNotificationsWrapperTestCase(test_v3.RestfulTestCase):
self.assertEqual(self.user_id, initiator.id)
self.assertEqual(self.user_id, initiator.user_id)
def test_initiator_always_contains_username(self):
# Clear notifications
while self._notifications:
self._notifications.pop()
self.get_scoped_token()
self.assertEqual(len(self._notifications), 1)
note = self._notifications.pop()
initiator = note['initiator']
self.assertEqual(self.user['name'], initiator.username)
def test_v3_authenticate_user_name_and_domain_id(self):
user_id = self.user_id
user_name = self.user['name']

View File

@ -0,0 +1,9 @@
---
fixes:
- |
[`Bug 1856904 <https://bugs.launchpad.net/keystone/+bug/1856904>`_]
The initiator object for CADF notifications now will always contain the
username for the user who initated the action. Previously, the initator
object only contained the user_id, which lead to issues mapping to users
when using LDAP-backed identity providers. This also helps the initiator
object better conform to the OpenStack standard for CADF.