add initiator to v2 calls for additional auditing
currently notifications are emitted for v2 calls, but the initiator field is not filled in. Co-authored-by: sam leong <chio-fai-sam.leong@hpe.com> Change-Id: Ie2c3fe8d105d59ab89b7f6625e159d4eb6e923b0 Closes-Bug: #1485035
This commit is contained in:
committed by
chioleong
co-authored by
sam leong
parent
5e92e68431
commit
84b2285a1e
@@ -108,13 +108,15 @@ class Role(controller.V2Controller):
|
||||
role_id = uuid.uuid4().hex
|
||||
|
||||
role['id'] = role_id
|
||||
role_ref = self.role_api.create_role(role_id, role)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
role_ref = self.role_api.create_role(role_id, role, initiator)
|
||||
return {'role': role_ref}
|
||||
|
||||
@controller.v2_deprecated
|
||||
def delete_role(self, context, role_id):
|
||||
self.assert_admin(context)
|
||||
self.role_api.delete_role(role_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.role_api.delete_role(role_id, initiator)
|
||||
|
||||
@controller.v2_deprecated
|
||||
def get_roles(self, context):
|
||||
|
||||
@@ -47,7 +47,8 @@ class Service(controller.V2Controller):
|
||||
@controller.v2_deprecated
|
||||
def delete_service(self, context, service_id):
|
||||
self.assert_admin(context)
|
||||
self.catalog_api.delete_service(service_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.catalog_api.delete_service(service_id, initiator)
|
||||
|
||||
@controller.v2_deprecated
|
||||
def create_service(self, context, OS_KSADM_service):
|
||||
@@ -55,8 +56,9 @@ class Service(controller.V2Controller):
|
||||
service_id = uuid.uuid4().hex
|
||||
service_ref = OS_KSADM_service.copy()
|
||||
service_ref['id'] = service_id
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
new_service_ref = self.catalog_api.create_service(
|
||||
service_id, service_ref)
|
||||
service_id, service_ref, initiator)
|
||||
return {'OS-KSADM:service': new_service_ref}
|
||||
|
||||
|
||||
@@ -182,11 +184,12 @@ class Endpoint(controller.V2Controller):
|
||||
def delete_endpoint(self, context, endpoint_id):
|
||||
"""Delete up to three v3 endpoint refs based on a legacy ref ID."""
|
||||
self.assert_admin(context)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
|
||||
deleted_at_least_one = False
|
||||
for endpoint in self.catalog_api.list_endpoints():
|
||||
if endpoint['legacy_endpoint_id'] == endpoint_id:
|
||||
self.catalog_api.delete_endpoint(endpoint['id'])
|
||||
self.catalog_api.delete_endpoint(endpoint['id'], initiator)
|
||||
deleted_at_least_one = True
|
||||
|
||||
if not deleted_at_least_one:
|
||||
|
||||
@@ -82,8 +82,9 @@ class User(controller.V2Controller):
|
||||
|
||||
# The manager layer will generate the unique ID for users
|
||||
user_ref = self._normalize_domain_id(context, user.copy())
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
new_user_ref = self.v3_to_v2_user(
|
||||
self.identity_api.create_user(user_ref))
|
||||
self.identity_api.create_user(user_ref, initiator))
|
||||
|
||||
if default_project_id is not None:
|
||||
self.assignment_api.add_user_to_project(default_project_id,
|
||||
@@ -120,8 +121,9 @@ class User(controller.V2Controller):
|
||||
# user update.
|
||||
self.resource_api.get_project(default_project_id)
|
||||
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
user_ref = self.v3_to_v2_user(
|
||||
self.identity_api.update_user(user_id, user))
|
||||
self.identity_api.update_user(user_id, user, initiator))
|
||||
|
||||
# If 'tenantId' is in either ref, we might need to add or remove the
|
||||
# user from a project.
|
||||
@@ -166,7 +168,8 @@ class User(controller.V2Controller):
|
||||
@controller.v2_deprecated
|
||||
def delete_user(self, context, user_id):
|
||||
self.assert_admin(context)
|
||||
self.identity_api.delete_user(user_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.identity_api.delete_user(user_id, initiator)
|
||||
|
||||
@controller.v2_deprecated
|
||||
def set_user_enabled(self, context, user_id, user):
|
||||
|
||||
@@ -90,9 +90,11 @@ class Tenant(controller.V2Controller):
|
||||
|
||||
self.assert_admin(context)
|
||||
tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
tenant = self.resource_api.create_project(
|
||||
tenant_ref['id'],
|
||||
self._normalize_domain_id(context, tenant_ref))
|
||||
self._normalize_domain_id(context, tenant_ref),
|
||||
initiator)
|
||||
return {'tenant': self.v3_to_v2_project(tenant)}
|
||||
|
||||
@controller.v2_deprecated
|
||||
@@ -104,15 +106,17 @@ class Tenant(controller.V2Controller):
|
||||
clean_tenant = tenant.copy()
|
||||
clean_tenant.pop('domain_id', None)
|
||||
clean_tenant.pop('is_domain', None)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
tenant_ref = self.resource_api.update_project(
|
||||
tenant_id, clean_tenant)
|
||||
tenant_id, clean_tenant, initiator)
|
||||
return {'tenant': self.v3_to_v2_project(tenant_ref)}
|
||||
|
||||
@controller.v2_deprecated
|
||||
def delete_project(self, context, tenant_id):
|
||||
self.assert_admin(context)
|
||||
self._assert_not_is_domain_project(tenant_id)
|
||||
self.resource_api.delete_project(tenant_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.resource_api.delete_project(tenant_id, initiator)
|
||||
|
||||
|
||||
@dependency.requires('resource_api')
|
||||
|
||||
@@ -279,6 +279,16 @@ class BaseNotificationTest(test_v3.RestfulTestCase):
|
||||
self.assertEqual(event_type, audit['event_type'])
|
||||
self.assertTrue(audit['send_notification_called'])
|
||||
|
||||
def _assert_initiator_data_is_set(self, operation, resource_type, typeURI):
|
||||
self.assertTrue(len(self._audits) > 0)
|
||||
audit = self._audits[-1]
|
||||
payload = audit['payload']
|
||||
self.assertEqual(self.user_id, payload['initiator']['id'])
|
||||
self.assertEqual(self.project_id, payload['initiator']['project_id'])
|
||||
self.assertEqual(typeURI, payload['target']['typeURI'])
|
||||
action = '%s.%s' % (operation, resource_type)
|
||||
self.assertEqual(action, payload['action'])
|
||||
|
||||
def _assert_notify_not_sent(self, resource_id, operation, resource_type,
|
||||
public=True):
|
||||
unexpected = {
|
||||
@@ -633,11 +643,154 @@ class CADFNotificationsForEntities(NotificationsForEntities):
|
||||
resource_id = resp.result.get('domain').get('id')
|
||||
self._assert_last_audit(resource_id, CREATED_OPERATION, 'domain',
|
||||
cadftaxonomy.SECURITY_DOMAIN)
|
||||
self.assertTrue(len(self._audits) > 0)
|
||||
audit = self._audits[-1]
|
||||
payload = audit['payload']
|
||||
self.assertEqual(self.user_id, payload['initiator']['id'])
|
||||
self.assertEqual(self.project_id, payload['initiator']['project_id'])
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'domain',
|
||||
cadftaxonomy.SECURITY_DOMAIN)
|
||||
|
||||
|
||||
class V2Notifications(BaseNotificationTest):
|
||||
|
||||
def setUp(self):
|
||||
super(V2Notifications, self).setUp()
|
||||
self.config_fixture.config(notification_format='cadf')
|
||||
|
||||
def test_user(self):
|
||||
token = self.get_scoped_token()
|
||||
resp = self.admin_request(
|
||||
method='POST',
|
||||
path='/v2.0/users',
|
||||
body={
|
||||
'user': {
|
||||
'name': uuid.uuid4().hex,
|
||||
'password': uuid.uuid4().hex,
|
||||
'enabled': True,
|
||||
},
|
||||
},
|
||||
token=token,
|
||||
)
|
||||
user_id = resp.result.get('user').get('id')
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'user',
|
||||
cadftaxonomy.SECURITY_ACCOUNT_USER)
|
||||
# test for delete user
|
||||
self.admin_request(
|
||||
method='DELETE',
|
||||
path='/v2.0/users/%s' % user_id,
|
||||
token=token,
|
||||
)
|
||||
self._assert_initiator_data_is_set(DELETED_OPERATION,
|
||||
'user',
|
||||
cadftaxonomy.SECURITY_ACCOUNT_USER)
|
||||
|
||||
def test_role(self):
|
||||
token = self.get_scoped_token()
|
||||
resp = self.admin_request(
|
||||
method='POST',
|
||||
path='/v2.0/OS-KSADM/roles',
|
||||
body={
|
||||
'role': {
|
||||
'name': uuid.uuid4().hex,
|
||||
'description': uuid.uuid4().hex,
|
||||
},
|
||||
},
|
||||
token=token,
|
||||
)
|
||||
role_id = resp.result.get('role').get('id')
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'role',
|
||||
cadftaxonomy.SECURITY_ROLE)
|
||||
# test for delete role
|
||||
self.admin_request(
|
||||
method='DELETE',
|
||||
path='/v2.0/OS-KSADM/roles/%s' % role_id,
|
||||
token=token,
|
||||
)
|
||||
self._assert_initiator_data_is_set(DELETED_OPERATION,
|
||||
'role',
|
||||
cadftaxonomy.SECURITY_ROLE)
|
||||
|
||||
def test_service_and_endpoint(self):
|
||||
token = self.get_scoped_token()
|
||||
resp = self.admin_request(
|
||||
method='POST',
|
||||
path='/v2.0/OS-KSADM/services',
|
||||
body={
|
||||
'OS-KSADM:service': {
|
||||
'name': uuid.uuid4().hex,
|
||||
'type': uuid.uuid4().hex,
|
||||
'description': uuid.uuid4().hex,
|
||||
},
|
||||
},
|
||||
token=token,
|
||||
)
|
||||
service_id = resp.result.get('OS-KSADM:service').get('id')
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'service',
|
||||
cadftaxonomy.SECURITY_SERVICE)
|
||||
resp = self.admin_request(
|
||||
method='POST',
|
||||
path='/v2.0/endpoints',
|
||||
body={
|
||||
'endpoint': {
|
||||
'region': uuid.uuid4().hex,
|
||||
'service_id': service_id,
|
||||
'publicurl': uuid.uuid4().hex,
|
||||
'adminurl': uuid.uuid4().hex,
|
||||
'internalurl': uuid.uuid4().hex,
|
||||
},
|
||||
},
|
||||
token=token,
|
||||
)
|
||||
endpoint_id = resp.result.get('endpoint').get('id')
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'endpoint',
|
||||
cadftaxonomy.SECURITY_ENDPOINT)
|
||||
# test for delete endpoint
|
||||
self.admin_request(
|
||||
method='DELETE',
|
||||
path='/v2.0/endpoints/%s' % endpoint_id,
|
||||
token=token,
|
||||
)
|
||||
self._assert_initiator_data_is_set(DELETED_OPERATION,
|
||||
'endpoint',
|
||||
cadftaxonomy.SECURITY_ENDPOINT)
|
||||
# test for delete service
|
||||
self.admin_request(
|
||||
method='DELETE',
|
||||
path='/v2.0/OS-KSADM/services/%s' % service_id,
|
||||
token=token,
|
||||
)
|
||||
self._assert_initiator_data_is_set(DELETED_OPERATION,
|
||||
'service',
|
||||
cadftaxonomy.SECURITY_SERVICE)
|
||||
|
||||
def test_project(self):
|
||||
token = self.get_scoped_token()
|
||||
resp = self.admin_request(
|
||||
method='POST',
|
||||
path='/v2.0/tenants',
|
||||
body={
|
||||
'tenant': {
|
||||
'name': uuid.uuid4().hex,
|
||||
'description': uuid.uuid4().hex,
|
||||
'enabled': True
|
||||
},
|
||||
},
|
||||
token=token,
|
||||
)
|
||||
project_id = resp.result.get('tenant').get('id')
|
||||
self._assert_initiator_data_is_set(CREATED_OPERATION,
|
||||
'project',
|
||||
cadftaxonomy.SECURITY_PROJECT)
|
||||
# test for delete project
|
||||
self.admin_request(
|
||||
method='DELETE',
|
||||
path='/v2.0/tenants/%s' % project_id,
|
||||
token=token,
|
||||
)
|
||||
self._assert_initiator_data_is_set(DELETED_OPERATION,
|
||||
'project',
|
||||
cadftaxonomy.SECURITY_PROJECT)
|
||||
|
||||
|
||||
class TestEventCallbacks(test_v3.RestfulTestCase):
|
||||
|
||||
Reference in New Issue
Block a user