Move audit initiator creation to request

The audit initiator is basically a context with all the information
about the current operation available. This information is all gathered
from the request and context so we can simplify its generation by moving
it onto the request object.

Change-Id: If91eacd3e07e0d9cd825f92b06c0ac819b3daf8c
This commit is contained in:
Jamie Lennox 2016-07-15 17:53:12 +10:00
parent 5046ba01d8
commit 9117e45d6e
11 changed files with 165 additions and 152 deletions

View File

@ -30,7 +30,6 @@ from keystone.common import wsgi
import keystone.conf import keystone.conf
from keystone import exception from keystone import exception
from keystone.i18n import _ from keystone.i18n import _
from keystone import notifications
CONF = keystone.conf.CONF CONF = keystone.conf.CONF
@ -106,15 +105,15 @@ class Role(controller.V2Controller):
role_id = uuid.uuid4().hex role_id = uuid.uuid4().hex
role['id'] = role_id role['id'] = role_id
initiator = notifications._get_request_audit_info(request.context_dict) role_ref = self.role_api.create_role(role_id,
role_ref = self.role_api.create_role(role_id, role, initiator) role,
request.audit_initiator)
return {'role': role_ref} return {'role': role_ref}
@controller.v2_deprecated @controller.v2_deprecated
def delete_role(self, request, role_id): def delete_role(self, request, role_id):
self.assert_admin(request) self.assert_admin(request)
initiator = notifications._get_request_audit_info(request.context_dict) self.role_api.delete_role(role_id, request.audit_initiator)
self.role_api.delete_role(role_id, initiator)
@controller.v2_deprecated @controller.v2_deprecated
def get_roles(self, request): def get_roles(self, request):
@ -319,12 +318,12 @@ class RoleV3(controller.V3Controller):
@controller.protected() @controller.protected()
def create_role(self, request, role): def create_role(self, request, role):
validation.lazy_validate(schema.role_create, role) validation.lazy_validate(schema.role_create, role)
return self._create_role(request.context_dict, role) return self._create_role(request, role)
@controller.protected() @controller.protected()
def create_domain_role(self, request, role): def create_domain_role(self, request, role):
validation.lazy_validate(schema.role_create, role) validation.lazy_validate(schema.role_create, role)
return self._create_role(request.context_dict, role) return self._create_role(request, role)
def list_roles_wrapper(self, request): def list_roles_wrapper(self, request):
if request.params.get('domain_id'): if request.params.get('domain_id'):
@ -348,11 +347,11 @@ class RoleV3(controller.V3Controller):
@controller.protected() @controller.protected()
def get_role(self, request, role_id): def get_role(self, request, role_id):
return self._get_role(request.context_dict, role_id) return self._get_role(request, role_id)
@controller.protected() @controller.protected()
def get_domain_role(self, request, role_id): def get_domain_role(self, request, role_id):
return self._get_role(request.context_dict, role_id) return self._get_role(request, role_id)
def update_role_wrapper(self, context, role_id, role): def update_role_wrapper(self, context, role_id, role):
# Since we don't allow you change whether a role is global or domain # Since we don't allow you change whether a role is global or domain
@ -367,12 +366,12 @@ class RoleV3(controller.V3Controller):
@controller.protected() @controller.protected()
def update_role(self, request, role_id, role): def update_role(self, request, role_id, role):
validation.lazy_validate(schema.role_update, role) validation.lazy_validate(schema.role_update, role)
return self._update_role(request.context_dict, role_id, role) return self._update_role(request, role_id, role)
@controller.protected() @controller.protected()
def update_domain_role(self, request, role_id, role): def update_domain_role(self, request, role_id, role):
validation.lazy_validate(schema.role_update, role) validation.lazy_validate(schema.role_update, role)
return self._update_role(request.context_dict, role_id, role) return self._update_role(request, role_id, role)
def delete_role_wrapper(self, context, role_id): def delete_role_wrapper(self, context, role_id):
if self._is_domain_role_target(role_id): if self._is_domain_role_target(role_id):
@ -382,13 +381,13 @@ class RoleV3(controller.V3Controller):
@controller.protected() @controller.protected()
def delete_role(self, request, role_id): def delete_role(self, request, role_id):
return self._delete_role(request.context_dict, role_id) return self._delete_role(request, role_id)
@controller.protected() @controller.protected()
def delete_domain_role(self, request, role_id): def delete_domain_role(self, request, role_id):
return self._delete_role(request.context_dict, role_id) return self._delete_role(request, role_id)
def _create_role(self, context, role): def _create_role(self, request, role):
if role['name'] == CONF.member_role_name: if role['name'] == CONF.member_role_name:
# Use the configured member role ID when creating the configured # Use the configured member role ID when creating the configured
# member role name. This avoids the potential of creating a # member role name. This avoids the potential of creating a
@ -398,29 +397,27 @@ class RoleV3(controller.V3Controller):
role = self._assign_unique_id(role) role = self._assign_unique_id(role)
ref = self._normalize_dict(role) ref = self._normalize_dict(role)
ref = self.role_api.create_role(ref['id'],
initiator = notifications._get_request_audit_info(context) ref,
ref = self.role_api.create_role(ref['id'], ref, initiator) request.audit_initiator)
return RoleV3.wrap_member(context, ref) return RoleV3.wrap_member(request.context_dict, ref)
def _list_roles(self, request, filters): def _list_roles(self, request, filters):
hints = RoleV3.build_driver_hints(request, filters) hints = RoleV3.build_driver_hints(request, filters)
refs = self.role_api.list_roles(hints=hints) refs = self.role_api.list_roles(hints=hints)
return RoleV3.wrap_collection(request.context_dict, refs, hints=hints) return RoleV3.wrap_collection(request.context_dict, refs, hints=hints)
def _get_role(self, context, role_id): def _get_role(self, request, role_id):
ref = self.role_api.get_role(role_id) ref = self.role_api.get_role(role_id)
return RoleV3.wrap_member(context, ref) return RoleV3.wrap_member(request.context_dict, ref)
def _update_role(self, context, role_id, role): def _update_role(self, request, role_id, role):
self._require_matching_id(role_id, role) self._require_matching_id(role_id, role)
initiator = notifications._get_request_audit_info(context) ref = self.role_api.update_role(role_id, role, request.audit_initiator)
ref = self.role_api.update_role(role_id, role, initiator) return RoleV3.wrap_member(request.context_dict, ref)
return RoleV3.wrap_member(context, ref)
def _delete_role(self, context, role_id): def _delete_role(self, request, role_id):
initiator = notifications._get_request_audit_info(context) self.role_api.delete_role(role_id, request.audit_initiator)
self.role_api.delete_role(role_id, initiator)
@classmethod @classmethod
def build_driver_hints(cls, request, supported_filters): def build_driver_hints(cls, request, supported_filters):

View File

@ -81,7 +81,7 @@ def handle_scoped_token(request, auth_payload, auth_context, token_ref,
group_ids = token_ref.federation_group_ids group_ids = token_ref.federation_group_ids
send_notification = functools.partial( send_notification = functools.partial(
notifications.send_saml_audit_notification, 'authenticate', notifications.send_saml_audit_notification, 'authenticate',
request.context_dict, user_id, group_ids, identity_provider, protocol, request, user_id, group_ids, identity_provider, protocol,
token_audit_id) token_audit_id)
utils.assert_enabled_identity_provider(federation_api, identity_provider) utils.assert_enabled_identity_provider(federation_api, identity_provider)
@ -171,7 +171,7 @@ def handle_unscoped_token(request, auth_payload, auth_context,
# after sending the notification # after sending the notification
outcome = taxonomy.OUTCOME_FAILURE outcome = taxonomy.OUTCOME_FAILURE
notifications.send_saml_audit_notification('authenticate', notifications.send_saml_audit_notification('authenticate',
request.context_dict, request,
user_id, group_ids, user_id, group_ids,
identity_provider, identity_provider,
protocol, token_id, protocol, token_id,
@ -180,7 +180,7 @@ def handle_unscoped_token(request, auth_payload, auth_context,
else: else:
outcome = taxonomy.OUTCOME_SUCCESS outcome = taxonomy.OUTCOME_SUCCESS
notifications.send_saml_audit_notification('authenticate', notifications.send_saml_audit_notification('authenticate',
request.context_dict, request,
user_id, group_ids, user_id, group_ids,
identity_provider, identity_provider,
protocol, token_id, protocol, token_id,

View File

@ -50,8 +50,7 @@ class Service(controller.V2Controller):
@controller.v2_deprecated @controller.v2_deprecated
def delete_service(self, request, service_id): def delete_service(self, request, service_id):
self.assert_admin(request) self.assert_admin(request)
initiator = notifications._get_request_audit_info(request.context_dict) self.catalog_api.delete_service(service_id, request.audit_initiator)
self.catalog_api.delete_service(service_id, initiator)
@controller.v2_deprecated @controller.v2_deprecated
def create_service(self, request, OS_KSADM_service): def create_service(self, request, OS_KSADM_service):
@ -60,9 +59,8 @@ class Service(controller.V2Controller):
service_id = uuid.uuid4().hex service_id = uuid.uuid4().hex
service_ref = OS_KSADM_service.copy() service_ref = OS_KSADM_service.copy()
service_ref['id'] = service_id service_ref['id'] = service_id
initiator = notifications._get_request_audit_info(request.context_dict)
new_service_ref = self.catalog_api.create_service( new_service_ref = self.catalog_api.create_service(
service_id, service_ref, initiator) service_id, service_ref, request.audit_initiator)
return {'OS-KSADM:service': new_service_ref} return {'OS-KSADM:service': new_service_ref}
@ -147,14 +145,12 @@ class Endpoint(controller.V2Controller):
if interface_url: if interface_url:
utils.check_endpoint_url(interface_url) utils.check_endpoint_url(interface_url)
initiator = notifications._get_request_audit_info(request.context_dict)
if endpoint.get('region') is not None: if endpoint.get('region') is not None:
try: try:
self.catalog_api.get_region(endpoint['region']) self.catalog_api.get_region(endpoint['region'])
except exception.RegionNotFound: except exception.RegionNotFound:
region = dict(id=endpoint['region']) region = dict(id=endpoint['region'])
self.catalog_api.create_region(region, initiator) self.catalog_api.create_region(region, request.audit_initiator)
legacy_endpoint_ref = endpoint.copy() legacy_endpoint_ref = endpoint.copy()
@ -178,8 +174,9 @@ class Endpoint(controller.V2Controller):
endpoint_ref['interface'] = interface endpoint_ref['interface'] = interface
endpoint_ref['url'] = url endpoint_ref['url'] = url
endpoint_ref['region_id'] = endpoint_ref.pop('region') endpoint_ref['region_id'] = endpoint_ref.pop('region')
self.catalog_api.create_endpoint(endpoint_ref['id'], endpoint_ref, self.catalog_api.create_endpoint(endpoint_ref['id'],
initiator) endpoint_ref,
request.audit_initiator)
legacy_endpoint_ref['id'] = legacy_endpoint_id legacy_endpoint_ref['id'] = legacy_endpoint_id
return {'endpoint': legacy_endpoint_ref} return {'endpoint': legacy_endpoint_ref}
@ -188,12 +185,12 @@ class Endpoint(controller.V2Controller):
def delete_endpoint(self, request, endpoint_id): def delete_endpoint(self, request, endpoint_id):
"""Delete up to three v3 endpoint refs based on a legacy ref ID.""" """Delete up to three v3 endpoint refs based on a legacy ref ID."""
self.assert_admin(request) self.assert_admin(request)
initiator = notifications._get_request_audit_info(request.context_dict)
deleted_at_least_one = False deleted_at_least_one = False
for endpoint in self.catalog_api.list_endpoints(): for endpoint in self.catalog_api.list_endpoints():
if endpoint['legacy_endpoint_id'] == endpoint_id: if endpoint['legacy_endpoint_id'] == endpoint_id:
self.catalog_api.delete_endpoint(endpoint['id'], initiator) self.catalog_api.delete_endpoint(endpoint['id'],
request.audit_initiator)
deleted_at_least_one = True deleted_at_least_one = True
if not deleted_at_least_one: if not deleted_at_least_one:
@ -228,8 +225,7 @@ class RegionV3(controller.V3Controller):
if not ref.get('id'): if not ref.get('id'):
ref = self._assign_unique_id(ref) ref = self._assign_unique_id(ref)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.create_region(ref, request.audit_initiator)
ref = self.catalog_api.create_region(ref, initiator)
return wsgi.render_response( return wsgi.render_response(
RegionV3.wrap_member(request.context_dict, ref), RegionV3.wrap_member(request.context_dict, ref),
status=(http_client.CREATED, status=(http_client.CREATED,
@ -252,14 +248,15 @@ class RegionV3(controller.V3Controller):
def update_region(self, request, region_id, region): def update_region(self, request, region_id, region):
validation.lazy_validate(schema.region_update, region) validation.lazy_validate(schema.region_update, region)
self._require_matching_id(region_id, region) self._require_matching_id(region_id, region)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.update_region(region_id,
ref = self.catalog_api.update_region(region_id, region, initiator) region,
request.audit_initiator)
return RegionV3.wrap_member(request.context_dict, ref) return RegionV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_region(self, request, region_id): def delete_region(self, request, region_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.catalog_api.delete_region(region_id,
return self.catalog_api.delete_region(region_id, initiator) request.audit_initiator)
@dependency.requires('catalog_api') @dependency.requires('catalog_api')
@ -275,8 +272,9 @@ class ServiceV3(controller.V3Controller):
def create_service(self, request, service): def create_service(self, request, service):
validation.lazy_validate(schema.service_create, service) validation.lazy_validate(schema.service_create, service)
ref = self._assign_unique_id(self._normalize_dict(service)) ref = self._assign_unique_id(self._normalize_dict(service))
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.create_service(ref['id'],
ref = self.catalog_api.create_service(ref['id'], ref, initiator) ref,
request.audit_initiator)
return ServiceV3.wrap_member(request.context_dict, ref) return ServiceV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('type', 'name') @controller.filterprotected('type', 'name')
@ -296,14 +294,15 @@ class ServiceV3(controller.V3Controller):
def update_service(self, request, service_id, service): def update_service(self, request, service_id, service):
validation.lazy_validate(schema.service_update, service) validation.lazy_validate(schema.service_update, service)
self._require_matching_id(service_id, service) self._require_matching_id(service_id, service)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.update_service(service_id,
ref = self.catalog_api.update_service(service_id, service, initiator) service,
request.audit_initiator)
return ServiceV3.wrap_member(request.context_dict, ref) return ServiceV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_service(self, request, service_id): def delete_service(self, request, service_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.catalog_api.delete_service(service_id,
return self.catalog_api.delete_service(service_id, initiator) request.audit_initiator)
@dependency.requires('catalog_api') @dependency.requires('catalog_api')
@ -327,7 +326,7 @@ class EndpointV3(controller.V3Controller):
ref = cls.filter_endpoint(ref) ref = cls.filter_endpoint(ref)
return super(EndpointV3, cls).wrap_member(context, ref) return super(EndpointV3, cls).wrap_member(context, ref)
def _validate_endpoint_region(self, endpoint, context=None): def _validate_endpoint_region(self, endpoint, request):
"""Ensure the region for the endpoint exists. """Ensure the region for the endpoint exists.
If 'region_id' is used to specify the region, then we will let the If 'region_id' is used to specify the region, then we will let the
@ -346,8 +345,7 @@ class EndpointV3(controller.V3Controller):
self.catalog_api.get_region(endpoint['region_id']) self.catalog_api.get_region(endpoint['region_id'])
except exception.RegionNotFound: except exception.RegionNotFound:
region = dict(id=endpoint['region_id']) region = dict(id=endpoint['region_id'])
initiator = notifications._get_request_audit_info(context) self.catalog_api.create_region(region, request.audit_initiator)
self.catalog_api.create_region(region, initiator)
return endpoint return endpoint
@ -356,9 +354,10 @@ class EndpointV3(controller.V3Controller):
validation.lazy_validate(schema.endpoint_create, endpoint) validation.lazy_validate(schema.endpoint_create, endpoint)
utils.check_endpoint_url(endpoint['url']) utils.check_endpoint_url(endpoint['url'])
ref = self._assign_unique_id(self._normalize_dict(endpoint)) ref = self._assign_unique_id(self._normalize_dict(endpoint))
ref = self._validate_endpoint_region(ref, request.context_dict) ref = self._validate_endpoint_region(ref, request)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.create_endpoint(ref['id'],
ref = self.catalog_api.create_endpoint(ref['id'], ref, initiator) ref,
request.audit_initiator)
return EndpointV3.wrap_member(request.context_dict, ref) return EndpointV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('interface', 'service_id', 'region_id') @controller.filterprotected('interface', 'service_id', 'region_id')
@ -380,17 +379,17 @@ class EndpointV3(controller.V3Controller):
self._require_matching_id(endpoint_id, endpoint) self._require_matching_id(endpoint_id, endpoint)
endpoint = self._validate_endpoint_region(endpoint.copy(), endpoint = self._validate_endpoint_region(endpoint.copy(),
request.context_dict) request)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.update_endpoint(endpoint_id,
ref = self.catalog_api.update_endpoint(endpoint_id, endpoint, endpoint,
initiator) request.audit_initiator)
return EndpointV3.wrap_member(request.context_dict, ref) return EndpointV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_endpoint(self, request, endpoint_id): def delete_endpoint(self, request, endpoint_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.catalog_api.delete_endpoint(endpoint_id,
return self.catalog_api.delete_endpoint(endpoint_id, initiator) request.audit_initiator)
@dependency.requires('catalog_api', 'resource_api') @dependency.requires('catalog_api', 'resource_api')

View File

@ -12,11 +12,15 @@
import logging import logging
from pycadf import cadftaxonomy as taxonomy
from pycadf import host
from pycadf import resource
import webob import webob
from webob.descriptors import environ_getter from webob.descriptors import environ_getter
from keystone.common import authorization from keystone.common import authorization
from keystone.common import context from keystone.common import context
from keystone.common import utils
import keystone.conf import keystone.conf
from keystone import exception from keystone import exception
from keystone.i18n import _, _LW from keystone.i18n import _, _LW
@ -90,6 +94,26 @@ class Request(webob.Request):
# auth_context didn't decode anything we can use # auth_context didn't decode anything we can use
raise exception.Unauthorized() raise exception.Unauthorized()
@property
def audit_initiator(self):
"""A pyCADF initiator describing the current authenticated context."""
pycadf_host = host.Host(address=self.remote_addr,
agent=self.user_agent)
initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER,
host=pycadf_host)
if self.context.user_id:
initiator.id = utils.resource_uuid(self.context.user_id)
initiator.user_id = self.context.user_id
if self.context.project_id:
initiator.project_id = self.context.project_id
if self.context.domain_id:
initiator.domain_id = self.context.domain_id
return initiator
auth_type = environ_getter('AUTH_TYPE', None) auth_type = environ_getter('AUTH_TYPE', None)
remote_domain = environ_getter('REMOTE_DOMAIN', None) remote_domain = environ_getter('REMOTE_DOMAIN', None)
context = environ_getter(context.REQUEST_CONTEXT_ENV, None) context = environ_getter(context.REQUEST_CONTEXT_ENV, None)

View File

@ -23,7 +23,6 @@ import keystone.conf
from keystone import exception from keystone import exception
from keystone.i18n import _LW from keystone.i18n import _LW
from keystone.identity import schema from keystone.identity import schema
from keystone import notifications
CONF = keystone.conf.CONF CONF = keystone.conf.CONF
@ -77,9 +76,8 @@ class User(controller.V2Controller):
# The manager layer will generate the unique ID for users # The manager layer will generate the unique ID for users
user_ref = self._normalize_domain_id(request, user.copy()) user_ref = self._normalize_domain_id(request, user.copy())
initiator = notifications._get_request_audit_info(request.context_dict)
new_user_ref = self.v3_to_v2_user( new_user_ref = self.v3_to_v2_user(
self.identity_api.create_user(user_ref, initiator)) self.identity_api.create_user(user_ref, request.audit_initiator))
if default_project_id is not None: if default_project_id is not None:
self.assignment_api.add_user_to_project(default_project_id, self.assignment_api.add_user_to_project(default_project_id,
@ -113,9 +111,10 @@ class User(controller.V2Controller):
# user update. # user update.
self.resource_api.get_project(default_project_id) self.resource_api.get_project(default_project_id)
initiator = notifications._get_request_audit_info(request.context_dict) user_ref = self.identity_api.update_user(user_id,
user_ref = self.v3_to_v2_user( user,
self.identity_api.update_user(user_id, user, initiator)) request.audit_initiator)
user_ref = self.v3_to_v2_user(user_ref)
# If 'tenantId' is in either ref, we might need to add or remove the # If 'tenantId' is in either ref, we might need to add or remove the
# user from a project. # user from a project.
@ -160,8 +159,7 @@ class User(controller.V2Controller):
@controller.v2_deprecated @controller.v2_deprecated
def delete_user(self, request, user_id): def delete_user(self, request, user_id):
self.assert_admin(request) self.assert_admin(request)
initiator = notifications._get_request_audit_info(request.context_dict) self.identity_api.delete_user(user_id, request.audit_initiator)
self.identity_api.delete_user(user_id, initiator)
@controller.v2_deprecated @controller.v2_deprecated
def set_user_enabled(self, request, user_id, user): def set_user_enabled(self, request, user_id, user):
@ -213,8 +211,7 @@ class UserV3(controller.V3Controller):
# The manager layer will generate the unique ID for users # The manager layer will generate the unique ID for users
ref = self._normalize_dict(user) ref = self._normalize_dict(user)
ref = self._normalize_domain_id(request, ref) ref = self._normalize_domain_id(request, ref)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.identity_api.create_user(ref, request.audit_initiator)
ref = self.identity_api.create_user(ref, initiator)
return UserV3.wrap_member(request.context_dict, ref) return UserV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('domain_id', 'enabled', 'name') @controller.filterprotected('domain_id', 'enabled', 'name')
@ -236,23 +233,25 @@ class UserV3(controller.V3Controller):
ref = self.identity_api.get_user(user_id) ref = self.identity_api.get_user(user_id)
return UserV3.wrap_member(request.context_dict, ref) return UserV3.wrap_member(request.context_dict, ref)
def _update_user(self, context, user_id, user): def _update_user(self, request, user_id, user):
self._require_matching_id(user_id, user) self._require_matching_id(user_id, user)
self._require_matching_domain_id( self._require_matching_domain_id(
user_id, user, self.identity_api.get_user) user_id, user, self.identity_api.get_user)
initiator = notifications._get_request_audit_info(context) ref = self.identity_api.update_user(user_id,
ref = self.identity_api.update_user(user_id, user, initiator) user,
return UserV3.wrap_member(context, ref) request.audit_initiator)
return UserV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def update_user(self, request, user_id, user): def update_user(self, request, user_id, user):
validation.lazy_validate(schema.user_update, user) validation.lazy_validate(schema.user_update, user)
return self._update_user(request.context_dict, user_id, user) return self._update_user(request, user_id, user)
@controller.protected(callback=_check_user_and_group_protection) @controller.protected(callback=_check_user_and_group_protection)
def add_user_to_group(self, request, user_id, group_id): def add_user_to_group(self, request, user_id, group_id):
initiator = notifications._get_request_audit_info(request.context_dict) self.identity_api.add_user_to_group(user_id,
self.identity_api.add_user_to_group(user_id, group_id, initiator) group_id,
request.audit_initiator)
@controller.protected(callback=_check_user_and_group_protection) @controller.protected(callback=_check_user_and_group_protection)
def check_user_in_group(self, request, user_id, group_id): def check_user_in_group(self, request, user_id, group_id):
@ -260,13 +259,13 @@ class UserV3(controller.V3Controller):
@controller.protected(callback=_check_user_and_group_protection) @controller.protected(callback=_check_user_and_group_protection)
def remove_user_from_group(self, request, user_id, group_id): def remove_user_from_group(self, request, user_id, group_id):
initiator = notifications._get_request_audit_info(request.context_dict) self.identity_api.remove_user_from_group(user_id,
self.identity_api.remove_user_from_group(user_id, group_id, initiator) group_id,
request.audit_initiator)
@controller.protected() @controller.protected()
def delete_user(self, request, user_id): def delete_user(self, request, user_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.identity_api.delete_user(user_id, request.audit_initiator)
return self.identity_api.delete_user(user_id, initiator)
@controller.protected() @controller.protected()
def change_password(self, request, user_id, user): def change_password(self, request, user_id, user):
@ -306,8 +305,7 @@ class GroupV3(controller.V3Controller):
# The manager layer will generate the unique ID for groups # The manager layer will generate the unique ID for groups
ref = self._normalize_dict(group) ref = self._normalize_dict(group)
ref = self._normalize_domain_id(request, ref) ref = self._normalize_domain_id(request, ref)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.identity_api.create_group(ref, request.audit_initiator)
ref = self.identity_api.create_group(ref, initiator)
return GroupV3.wrap_member(request.context_dict, ref) return GroupV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('domain_id', 'name') @controller.filterprotected('domain_id', 'name')
@ -334,11 +332,11 @@ class GroupV3(controller.V3Controller):
self._require_matching_id(group_id, group) self._require_matching_id(group_id, group)
self._require_matching_domain_id( self._require_matching_domain_id(
group_id, group, self.identity_api.get_group) group_id, group, self.identity_api.get_group)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.identity_api.update_group(group_id,
ref = self.identity_api.update_group(group_id, group, initiator) group,
request.audit_initiator)
return GroupV3.wrap_member(request.context_dict, ref) return GroupV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_group(self, request, group_id): def delete_group(self, request, group_id):
initiator = notifications._get_request_audit_info(request.context_dict) self.identity_api.delete_group(group_id, request.audit_initiator)
self.identity_api.delete_group(group_id, initiator)

View File

@ -481,19 +481,18 @@ class CadfNotificationWrapper(object):
def __call__(self, f): def __call__(self, f):
@functools.wraps(f) @functools.wraps(f)
def wrapper(wrapped_self, request, user_id, *args, **kwargs): def wrapper(wrapped_self, request, user_id, *args, **kwargs):
# Always send a notification. """Alway send a notification."""
initiator = _get_request_audit_info(request.context_dict, user_id)
target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER) target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
try: try:
result = f(wrapped_self, request, user_id, *args, **kwargs) result = f(wrapped_self, request, user_id, *args, **kwargs)
except Exception: except Exception:
# For authentication failure send a cadf event as well # For authentication failure send a cadf event as well
_send_audit_notification(self.action, initiator, _send_audit_notification(self.action, request.audit_initiator,
taxonomy.OUTCOME_FAILURE, taxonomy.OUTCOME_FAILURE,
target, self.event_type) target, self.event_type)
raise raise
else: else:
_send_audit_notification(self.action, initiator, _send_audit_notification(self.action, request.audit_initiator,
taxonomy.OUTCOME_SUCCESS, taxonomy.OUTCOME_SUCCESS,
target, self.event_type) target, self.event_type)
return result return result
@ -603,15 +602,15 @@ class CadfRoleAssignmentNotificationWrapper(object):
return wrapper return wrapper
def send_saml_audit_notification(action, context, user_id, group_ids, def send_saml_audit_notification(action, request, user_id, group_ids,
identity_provider, protocol, token_id, identity_provider, protocol, token_id,
outcome): outcome):
"""Send notification to inform observers about SAML events. """Send notification to inform observers about SAML events.
:param action: Action being audited :param action: Action being audited
:type action: str :type action: str
:param context: Current request context to collect request info from :param request: Current request to collect request info from
:type context: dict :type request: keystone.common.request.Request
:param user_id: User ID from Keystone token :param user_id: User ID from Keystone token
:type user_id: str :type user_id: str
:param group_ids: List of Group IDs from Keystone token :param group_ids: List of Group IDs from Keystone token
@ -625,7 +624,7 @@ def send_saml_audit_notification(action, context, user_id, group_ids,
:param outcome: One of :class:`pycadf.cadftaxonomy` :param outcome: One of :class:`pycadf.cadftaxonomy`
:type outcome: str :type outcome: str
""" """
initiator = _get_request_audit_info(context) initiator = request.audit_initiator
target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER) target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
audit_type = SAML_AUDIT_TYPE audit_type = SAML_AUDIT_TYPE
user_id = user_id or taxonomy.UNKNOWN user_id = user_id or taxonomy.UNKNOWN

View File

@ -65,8 +65,8 @@ class ConsumerCrudV3(controller.V3Controller):
def create_consumer(self, request, consumer): def create_consumer(self, request, consumer):
validation.lazy_validate(schema.consumer_create, consumer) validation.lazy_validate(schema.consumer_create, consumer)
ref = self._assign_unique_id(self._normalize_dict(consumer)) ref = self._assign_unique_id(self._normalize_dict(consumer))
initiator = notifications._get_request_audit_info(request.context_dict) consumer_ref = self.oauth_api.create_consumer(ref,
consumer_ref = self.oauth_api.create_consumer(ref, initiator) request.audit_initiator)
return ConsumerCrudV3.wrap_member(request.context_dict, consumer_ref) return ConsumerCrudV3.wrap_member(request.context_dict, consumer_ref)
@controller.protected() @controller.protected()
@ -74,8 +74,9 @@ class ConsumerCrudV3(controller.V3Controller):
validation.lazy_validate(schema.consumer_update, consumer) validation.lazy_validate(schema.consumer_update, consumer)
self._require_matching_id(consumer_id, consumer) self._require_matching_id(consumer_id, consumer)
ref = self._normalize_dict(consumer) ref = self._normalize_dict(consumer)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.oauth_api.update_consumer(consumer_id,
ref = self.oauth_api.update_consumer(consumer_id, ref, initiator) ref,
request.audit_initiator)
return ConsumerCrudV3.wrap_member(request.context_dict, ref) return ConsumerCrudV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
@ -94,8 +95,7 @@ class ConsumerCrudV3(controller.V3Controller):
payload = {'user_id': user_token_ref.user_id, payload = {'user_id': user_token_ref.user_id,
'consumer_id': consumer_id} 'consumer_id': consumer_id}
_emit_user_oauth_consumer_token_invalidate(payload) _emit_user_oauth_consumer_token_invalidate(payload)
initiator = notifications._get_request_audit_info(request.context_dict) self.oauth_api.delete_consumer(consumer_id, request.audit_initiator)
self.oauth_api.delete_consumer(consumer_id, initiator)
@dependency.requires('oauth_api') @dependency.requires('oauth_api')
@ -140,9 +140,9 @@ class AccessTokenCrudV3(controller.V3Controller):
consumer_id = access_token['consumer_id'] consumer_id = access_token['consumer_id']
payload = {'user_id': user_id, 'consumer_id': consumer_id} payload = {'user_id': user_id, 'consumer_id': consumer_id}
_emit_user_oauth_consumer_token_invalidate(payload) _emit_user_oauth_consumer_token_invalidate(payload)
initiator = notifications._get_request_audit_info(request.context_dict) return self.oauth_api.delete_access_token(user_id,
return self.oauth_api.delete_access_token( access_token_id,
user_id, access_token_id, initiator) request.audit_initiator)
@staticmethod @staticmethod
def _get_user_id(entity): def _get_user_id(entity):
@ -248,11 +248,11 @@ class OAuthControllerV3(controller.V3Controller):
# show the details of the failure. # show the details of the failure.
oauth1.validate_oauth_params(b) oauth1.validate_oauth_params(b)
request_token_duration = CONF.oauth1.request_token_duration request_token_duration = CONF.oauth1.request_token_duration
initiator = notifications._get_request_audit_info(request.context_dict) token_ref = self.oauth_api.create_request_token(
token_ref = self.oauth_api.create_request_token(consumer_id, consumer_id,
requested_project_id, requested_project_id,
request_token_duration, request_token_duration,
initiator) request.audit_initiator)
result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s'
% {'key': token_ref['id'], % {'key': token_ref['id'],
@ -340,10 +340,9 @@ class OAuthControllerV3(controller.V3Controller):
raise exception.Unauthorized(message=msg) raise exception.Unauthorized(message=msg)
access_token_duration = CONF.oauth1.access_token_duration access_token_duration = CONF.oauth1.access_token_duration
initiator = notifications._get_request_audit_info(request.context_dict)
token_ref = self.oauth_api.create_access_token(request_token_id, token_ref = self.oauth_api.create_access_token(request_token_id,
access_token_duration, access_token_duration,
initiator) request.audit_initiator)
result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s'
% {'key': token_ref['id'], % {'key': token_ref['id'],

View File

@ -15,7 +15,6 @@
from keystone.common import controller from keystone.common import controller
from keystone.common import dependency from keystone.common import dependency
from keystone.common import validation from keystone.common import validation
from keystone import notifications
from keystone.policy import schema from keystone.policy import schema
@ -28,8 +27,9 @@ class PolicyV3(controller.V3Controller):
def create_policy(self, request, policy): def create_policy(self, request, policy):
validation.lazy_validate(schema.policy_create, policy) validation.lazy_validate(schema.policy_create, policy)
ref = self._assign_unique_id(self._normalize_dict(policy)) ref = self._assign_unique_id(self._normalize_dict(policy))
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.policy_api.create_policy(ref['id'],
ref = self.policy_api.create_policy(ref['id'], ref, initiator) ref,
request.audit_initiator)
return PolicyV3.wrap_member(request.context_dict, ref) return PolicyV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('type') @controller.filterprotected('type')
@ -47,11 +47,12 @@ class PolicyV3(controller.V3Controller):
@controller.protected() @controller.protected()
def update_policy(self, request, policy_id, policy): def update_policy(self, request, policy_id, policy):
validation.lazy_validate(schema.policy_update, policy) validation.lazy_validate(schema.policy_update, policy)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.policy_api.update_policy(policy_id,
ref = self.policy_api.update_policy(policy_id, policy, initiator) policy,
request.audit_initiator)
return PolicyV3.wrap_member(request.context_dict, ref) return PolicyV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_policy(self, request, policy_id): def delete_policy(self, request, policy_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.policy_api.delete_policy(policy_id,
return self.policy_api.delete_policy(policy_id, initiator) request.audit_initiator)

View File

@ -26,7 +26,6 @@ from keystone.common import wsgi
import keystone.conf import keystone.conf
from keystone import exception from keystone import exception
from keystone.i18n import _ from keystone.i18n import _
from keystone import notifications
from keystone.resource import schema from keystone.resource import schema
@ -94,11 +93,10 @@ class Tenant(controller.V2Controller):
self.resource_api.ensure_default_domain_exists() self.resource_api.ensure_default_domain_exists()
tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex) tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
initiator = notifications._get_request_audit_info(request.context_dict)
tenant = self.resource_api.create_project( tenant = self.resource_api.create_project(
tenant_ref['id'], tenant_ref['id'],
self._normalize_domain_id(request, tenant_ref), self._normalize_domain_id(request, tenant_ref),
initiator) request.audit_initiator)
return {'tenant': self.v3_to_v2_project(tenant)} return {'tenant': self.v3_to_v2_project(tenant)}
@controller.v2_deprecated @controller.v2_deprecated
@ -107,17 +105,15 @@ class Tenant(controller.V2Controller):
self.assert_admin(request) self.assert_admin(request)
self._assert_not_is_domain_project(tenant_id) self._assert_not_is_domain_project(tenant_id)
initiator = notifications._get_request_audit_info(request.context_dict)
tenant_ref = self.resource_api.update_project( tenant_ref = self.resource_api.update_project(
tenant_id, tenant, initiator) tenant_id, tenant, request.audit_initiator)
return {'tenant': self.v3_to_v2_project(tenant_ref)} return {'tenant': self.v3_to_v2_project(tenant_ref)}
@controller.v2_deprecated @controller.v2_deprecated
def delete_project(self, request, tenant_id): def delete_project(self, request, tenant_id):
self.assert_admin(request) self.assert_admin(request)
self._assert_not_is_domain_project(tenant_id) self._assert_not_is_domain_project(tenant_id)
initiator = notifications._get_request_audit_info(request.context_dict) self.resource_api.delete_project(tenant_id, request.audit_initiator)
self.resource_api.delete_project(tenant_id, initiator)
@dependency.requires('resource_api') @dependency.requires('resource_api')
@ -133,8 +129,9 @@ class DomainV3(controller.V3Controller):
def create_domain(self, request, domain): def create_domain(self, request, domain):
validation.lazy_validate(schema.domain_create, domain) validation.lazy_validate(schema.domain_create, domain)
ref = self._assign_unique_id(self._normalize_dict(domain)) ref = self._assign_unique_id(self._normalize_dict(domain))
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.resource_api.create_domain(ref['id'],
ref = self.resource_api.create_domain(ref['id'], ref, initiator) ref,
request.audit_initiator)
return DomainV3.wrap_member(request.context_dict, ref) return DomainV3.wrap_member(request.context_dict, ref)
@controller.filterprotected('enabled', 'name') @controller.filterprotected('enabled', 'name')
@ -153,14 +150,15 @@ class DomainV3(controller.V3Controller):
def update_domain(self, request, domain_id, domain): def update_domain(self, request, domain_id, domain):
validation.lazy_validate(schema.domain_update, domain) validation.lazy_validate(schema.domain_update, domain)
self._require_matching_id(domain_id, domain) self._require_matching_id(domain_id, domain)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.resource_api.update_domain(domain_id,
ref = self.resource_api.update_domain(domain_id, domain, initiator) domain,
request.audit_initiator)
return DomainV3.wrap_member(request.context_dict, ref) return DomainV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_domain(self, request, domain_id): def delete_domain(self, request, domain_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.resource_api.delete_domain(domain_id,
return self.resource_api.delete_domain(domain_id, initiator) request.audit_initiator)
@dependency.requires('domain_config_api') @dependency.requires('domain_config_api')
@ -241,10 +239,11 @@ class ProjectV3(controller.V3Controller):
if not ref.get('parent_id'): if not ref.get('parent_id'):
ref['parent_id'] = ref.get('domain_id') ref['parent_id'] = ref.get('domain_id')
initiator = notifications._get_request_audit_info(request.context_dict)
try: try:
ref = self.resource_api.create_project(ref['id'], ref, ref = self.resource_api.create_project(
initiator=initiator) ref['id'],
ref,
initiator=request.audit_initiator)
except (exception.DomainNotFound, exception.ProjectNotFound) as e: except (exception.DomainNotFound, exception.ProjectNotFound) as e:
raise exception.ValidationError(e) raise exception.ValidationError(e)
return ProjectV3.wrap_member(request.context_dict, ref) return ProjectV3.wrap_member(request.context_dict, ref)
@ -316,13 +315,14 @@ class ProjectV3(controller.V3Controller):
self._require_matching_id(project_id, project) self._require_matching_id(project_id, project)
self._require_matching_domain_id( self._require_matching_domain_id(
project_id, project, self.resource_api.get_project) project_id, project, self.resource_api.get_project)
initiator = notifications._get_request_audit_info(request.context_dict) ref = self.resource_api.update_project(
ref = self.resource_api.update_project(project_id, project, project_id,
initiator=initiator) project,
initiator=request.audit_initiator)
return ProjectV3.wrap_member(request.context_dict, ref) return ProjectV3.wrap_member(request.context_dict, ref)
@controller.protected() @controller.protected()
def delete_project(self, request, project_id): def delete_project(self, request, project_id):
initiator = notifications._get_request_audit_info(request.context_dict) return self.resource_api.delete_project(
return self.resource_api.delete_project(project_id, project_id,
initiator=initiator) initiator=request.audit_initiator)

View File

@ -1631,7 +1631,7 @@ class FederatedTokenTests(test_v3.RestfulTestCase, FederatedSetupMixin):
super(FederatedTokenTests, self).setUp() super(FederatedTokenTests, self).setUp()
self._notifications = [] self._notifications = []
def fake_saml_notify(action, context, user_id, group_ids, def fake_saml_notify(action, request, user_id, group_ids,
identity_provider, protocol, token_id, outcome): identity_provider, protocol, token_id, outcome):
note = { note = {
'action': action, 'action': action,

View File

@ -24,7 +24,6 @@ from keystone.common import utils
from keystone.common import validation from keystone.common import validation
from keystone import exception from keystone import exception
from keystone.i18n import _ from keystone.i18n import _
from keystone import notifications
from keystone.trust import schema from keystone.trust import schema
@ -137,12 +136,10 @@ class TrustV3(controller.V3Controller):
trust['expires_at'] = self._parse_expiration_date( trust['expires_at'] = self._parse_expiration_date(
trust.get('expires_at')) trust.get('expires_at'))
trust_id = uuid.uuid4().hex trust_id = uuid.uuid4().hex
initiator = notifications._get_request_audit_info(request.context_dict)
new_trust = self.trust_api.create_trust(trust_id, trust, new_trust = self.trust_api.create_trust(trust_id, trust,
normalized_roles, normalized_roles,
redelegated_trust, redelegated_trust,
initiator) request.audit_initiator)
self._fill_in_roles(request.context_dict, new_trust) self._fill_in_roles(request.context_dict, new_trust)
return TrustV3.wrap_member(request.context_dict, new_trust) return TrustV3.wrap_member(request.context_dict, new_trust)
@ -227,8 +224,7 @@ class TrustV3(controller.V3Controller):
not request.context.is_admin): not request.context.is_admin):
raise exception.Forbidden() raise exception.Forbidden()
initiator = notifications._get_request_audit_info(request.context_dict) self.trust_api.delete_trust(trust_id, request.audit_initiator)
self.trust_api.delete_trust(trust_id, initiator)
@controller.protected() @controller.protected()
def list_roles_for_trust(self, request, trust_id): def list_roles_for_trust(self, request, trust_id):