Get initiator from manager and send to controller
Using the WSGI context that is available at the manager layer, we can get the Initiator content we need and forward it to the manager classes. Co-Authored-By: Morgan Fainberg <morgan.fainberg@gmail.com> partially implements bp: cadf-everywhere Change-Id: I6b7885d29cd733c5040bea6003dd93607cb5821e
This commit is contained in:
parent
bc7fcca3af
commit
ffcc81b7a6
|
@ -30,6 +30,7 @@ from keystone.common import validation
|
|||
from keystone import exception
|
||||
from keystone.i18n import _, _LW
|
||||
from keystone.models import token_model
|
||||
from keystone import notifications
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -282,7 +283,8 @@ class RoleV3(controller.V3Controller):
|
|||
@validation.validated(schema.role_create, 'role')
|
||||
def create_role(self, context, role):
|
||||
ref = self._assign_unique_id(self._normalize_dict(role))
|
||||
ref = self.role_api.create_role(ref['id'], ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.role_api.create_role(ref['id'], ref, initiator)
|
||||
return RoleV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('name')
|
||||
|
@ -301,13 +303,14 @@ class RoleV3(controller.V3Controller):
|
|||
@validation.validated(schema.role_update, 'role')
|
||||
def update_role(self, context, role_id, role):
|
||||
self._require_matching_id(role_id, role)
|
||||
|
||||
ref = self.role_api.update_role(role_id, role)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.role_api.update_role(role_id, role, initiator)
|
||||
return RoleV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_role(self, context, role_id):
|
||||
self.role_api.delete_role(role_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.role_api.delete_role(role_id, initiator)
|
||||
|
||||
|
||||
@dependency.requires('assignment_api', 'identity_api', 'resource_api',
|
||||
|
|
|
@ -916,9 +916,9 @@ class RoleManager(manager.Manager):
|
|||
def get_role(self, role_id):
|
||||
return self.driver.get_role(role_id)
|
||||
|
||||
@notifications.created(_ROLE)
|
||||
def create_role(self, role_id, role):
|
||||
def create_role(self, role_id, role, initiator=None):
|
||||
ret = self.driver.create_role(role_id, role)
|
||||
notifications.Audit.created(self._ROLE, role_id, initiator)
|
||||
if SHOULD_CACHE(ret):
|
||||
self.get_role.set(ret, self, role_id)
|
||||
return ret
|
||||
|
@ -927,17 +927,28 @@ class RoleManager(manager.Manager):
|
|||
def list_roles(self, hints=None):
|
||||
return self.driver.list_roles(hints or driver_hints.Hints())
|
||||
|
||||
@notifications.updated(_ROLE)
|
||||
def update_role(self, role_id, role):
|
||||
def update_role(self, role_id, role, initiator=None):
|
||||
ret = self.driver.update_role(role_id, role)
|
||||
notifications.Audit.updated(self._ROLE, role_id, initiator)
|
||||
self.get_role.invalidate(self, role_id)
|
||||
return ret
|
||||
|
||||
@notifications.deleted(_ROLE)
|
||||
def delete_role(self, role_id):
|
||||
self.assignment_api.delete_tokens_for_role_assignments(role_id)
|
||||
def delete_role(self, role_id, initiator=None):
|
||||
try:
|
||||
self.assignment_api.delete_tokens_for_role_assignments(role_id)
|
||||
except exception.NotImplemented:
|
||||
# FIXME(morganfainberg): Not all backends (ldap) implement
|
||||
# `list_role_assignments_for_role` which would have previously
|
||||
# caused a NotImplmented error to be raised when called through
|
||||
# the controller. Now error or proper action will always come from
|
||||
# the `delete_role` method logic. Work needs to be done to make
|
||||
# the behavior between drivers consistent (capable of revoking
|
||||
# tokens for the same circumstances). This is related to the bug
|
||||
# https://bugs.launchpad.net/keystone/+bug/1221805
|
||||
pass
|
||||
self.assignment_api.delete_role_assignments(role_id)
|
||||
self.driver.delete_role(role_id)
|
||||
notifications.Audit.deleted(self._ROLE, role_id, initiator)
|
||||
self.get_role.invalidate(self, role_id)
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from keystone.common import validation
|
|||
from keystone.common import wsgi
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone import notifications
|
||||
|
||||
|
||||
INTERFACES = ['public', 'internal', 'admin']
|
||||
|
@ -99,12 +100,14 @@ class Endpoint(controller.V2Controller):
|
|||
# service_id is necessary
|
||||
self._require_attribute(endpoint, 'service_id')
|
||||
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
|
||||
if endpoint.get('region') is not None:
|
||||
try:
|
||||
self.catalog_api.get_region(endpoint['region'])
|
||||
except exception.RegionNotFound:
|
||||
region = dict(id=endpoint['region'])
|
||||
self.catalog_api.create_region(region)
|
||||
self.catalog_api.create_region(region, initiator)
|
||||
|
||||
legacy_endpoint_ref = endpoint.copy()
|
||||
|
||||
|
@ -128,8 +131,8 @@ class Endpoint(controller.V2Controller):
|
|||
endpoint_ref['interface'] = interface
|
||||
endpoint_ref['url'] = url
|
||||
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'], endpoint_ref,
|
||||
initiator)
|
||||
|
||||
legacy_endpoint_ref['id'] = legacy_endpoint_id
|
||||
return {'endpoint': legacy_endpoint_ref}
|
||||
|
@ -177,7 +180,8 @@ class RegionV3(controller.V3Controller):
|
|||
if not ref.get('id'):
|
||||
ref = self._assign_unique_id(ref)
|
||||
|
||||
ref = self.catalog_api.create_region(ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.create_region(ref, initiator)
|
||||
return wsgi.render_response(
|
||||
RegionV3.wrap_member(context, ref),
|
||||
status=(201, 'Created'))
|
||||
|
@ -197,13 +201,14 @@ class RegionV3(controller.V3Controller):
|
|||
@validation.validated(schema.region_update, 'region')
|
||||
def update_region(self, context, region_id, region):
|
||||
self._require_matching_id(region_id, region)
|
||||
|
||||
ref = self.catalog_api.update_region(region_id, region)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.update_region(region_id, region, initiator)
|
||||
return RegionV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_region(self, context, region_id):
|
||||
return self.catalog_api.delete_region(region_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.catalog_api.delete_region(region_id, initiator)
|
||||
|
||||
|
||||
@dependency.requires('catalog_api')
|
||||
|
@ -219,8 +224,8 @@ class ServiceV3(controller.V3Controller):
|
|||
@validation.validated(schema.service_create, 'service')
|
||||
def create_service(self, context, service):
|
||||
ref = self._assign_unique_id(self._normalize_dict(service))
|
||||
|
||||
ref = self.catalog_api.create_service(ref['id'], ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.create_service(ref['id'], ref, initiator)
|
||||
return ServiceV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('type', 'name')
|
||||
|
@ -238,13 +243,14 @@ class ServiceV3(controller.V3Controller):
|
|||
@validation.validated(schema.service_update, 'service')
|
||||
def update_service(self, context, service_id, service):
|
||||
self._require_matching_id(service_id, service)
|
||||
|
||||
ref = self.catalog_api.update_service(service_id, service)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.update_service(service_id, service, initiator)
|
||||
return ServiceV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_service(self, context, service_id):
|
||||
return self.catalog_api.delete_service(service_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.catalog_api.delete_service(service_id, initiator)
|
||||
|
||||
|
||||
@dependency.requires('catalog_api')
|
||||
|
@ -268,7 +274,7 @@ class EndpointV3(controller.V3Controller):
|
|||
ref = cls.filter_endpoint(ref)
|
||||
return super(EndpointV3, cls).wrap_member(context, ref)
|
||||
|
||||
def _validate_endpoint_region(self, endpoint):
|
||||
def _validate_endpoint_region(self, endpoint, context=None):
|
||||
"""Ensure the region for the endpoint exists.
|
||||
|
||||
If 'region_id' is used to specify the region, then we will let the
|
||||
|
@ -287,7 +293,8 @@ class EndpointV3(controller.V3Controller):
|
|||
self.catalog_api.get_region(endpoint['region_id'])
|
||||
except exception.RegionNotFound:
|
||||
region = dict(id=endpoint['region_id'])
|
||||
self.catalog_api.create_region(region)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.catalog_api.create_region(region, initiator)
|
||||
|
||||
return endpoint
|
||||
|
||||
|
@ -296,9 +303,9 @@ class EndpointV3(controller.V3Controller):
|
|||
def create_endpoint(self, context, endpoint):
|
||||
ref = self._assign_unique_id(self._normalize_dict(endpoint))
|
||||
self.catalog_api.get_service(ref['service_id'])
|
||||
ref = self._validate_endpoint_region(ref)
|
||||
|
||||
ref = self.catalog_api.create_endpoint(ref['id'], ref)
|
||||
ref = self._validate_endpoint_region(ref, context)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.create_endpoint(ref['id'], ref, initiator)
|
||||
return EndpointV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('interface', 'service_id')
|
||||
|
@ -319,11 +326,14 @@ class EndpointV3(controller.V3Controller):
|
|||
|
||||
if 'service_id' in endpoint:
|
||||
self.catalog_api.get_service(endpoint['service_id'])
|
||||
endpoint = self._validate_endpoint_region(endpoint.copy())
|
||||
endpoint = self._validate_endpoint_region(endpoint.copy(), context)
|
||||
|
||||
ref = self.catalog_api.update_endpoint(endpoint_id, endpoint)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.catalog_api.update_endpoint(endpoint_id, endpoint,
|
||||
initiator)
|
||||
return EndpointV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_endpoint(self, context, endpoint_id):
|
||||
return self.catalog_api.delete_endpoint(endpoint_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.catalog_api.delete_endpoint(endpoint_id, initiator)
|
||||
|
|
|
@ -95,8 +95,7 @@ class Manager(manager.Manager):
|
|||
def __init__(self):
|
||||
super(Manager, self).__init__(CONF.catalog.driver)
|
||||
|
||||
@notifications.created(_REGION, result_id_arg_attr='id')
|
||||
def create_region(self, region_ref):
|
||||
def create_region(self, region_ref, initiator=None):
|
||||
# Check duplicate ID
|
||||
try:
|
||||
self.get_region(region_ref['id'])
|
||||
|
@ -111,11 +110,14 @@ class Manager(manager.Manager):
|
|||
# set it to an empty string.
|
||||
region_ref.setdefault('description', '')
|
||||
try:
|
||||
return self.driver.create_region(region_ref)
|
||||
ret = self.driver.create_region(region_ref)
|
||||
except exception.NotFound:
|
||||
parent_region_id = region_ref.get('parent_region_id')
|
||||
raise exception.RegionNotFound(region_id=parent_region_id)
|
||||
|
||||
notifications.Audit.created(self._REGION, ret['id'], initiator)
|
||||
return ret
|
||||
|
||||
@cache.on_arguments(should_cache_fn=SHOULD_CACHE,
|
||||
expiration_time=EXPIRATION_TIME)
|
||||
def get_region(self, region_id):
|
||||
|
@ -124,16 +126,16 @@ class Manager(manager.Manager):
|
|||
except exception.NotFound:
|
||||
raise exception.RegionNotFound(region_id=region_id)
|
||||
|
||||
@notifications.updated(_REGION)
|
||||
def update_region(self, region_id, region_ref):
|
||||
def update_region(self, region_id, region_ref, initiator=None):
|
||||
ref = self.driver.update_region(region_id, region_ref)
|
||||
notifications.Audit.updated(self._REGION, region_id, initiator)
|
||||
self.get_region.invalidate(self, region_id)
|
||||
return ref
|
||||
|
||||
@notifications.deleted(_REGION)
|
||||
def delete_region(self, region_id):
|
||||
def delete_region(self, region_id, initiator=None):
|
||||
try:
|
||||
ret = self.driver.delete_region(region_id)
|
||||
notifications.Audit.deleted(self._REGION, region_id, initiator)
|
||||
self.get_region.invalidate(self, region_id)
|
||||
return ret
|
||||
except exception.NotFound:
|
||||
|
@ -143,10 +145,11 @@ class Manager(manager.Manager):
|
|||
def list_regions(self, hints=None):
|
||||
return self.driver.list_regions(hints or driver_hints.Hints())
|
||||
|
||||
@notifications.created(_SERVICE)
|
||||
def create_service(self, service_id, service_ref):
|
||||
def create_service(self, service_id, service_ref, initiator=None):
|
||||
service_ref.setdefault('enabled', True)
|
||||
return self.driver.create_service(service_id, service_ref)
|
||||
ref = self.driver.create_service(service_id, service_ref)
|
||||
notifications.Audit.created(self._SERVICE, service_id, initiator)
|
||||
return ref
|
||||
|
||||
@cache.on_arguments(should_cache_fn=SHOULD_CACHE,
|
||||
expiration_time=EXPIRATION_TIME)
|
||||
|
@ -156,17 +159,17 @@ class Manager(manager.Manager):
|
|||
except exception.NotFound:
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
|
||||
@notifications.updated(_SERVICE)
|
||||
def update_service(self, service_id, service_ref):
|
||||
def update_service(self, service_id, service_ref, initiator=None):
|
||||
ref = self.driver.update_service(service_id, service_ref)
|
||||
notifications.Audit.updated(self._SERVICE, service_id, initiator)
|
||||
self.get_service.invalidate(self, service_id)
|
||||
return ref
|
||||
|
||||
@notifications.deleted(_SERVICE)
|
||||
def delete_service(self, service_id):
|
||||
def delete_service(self, service_id, initiator=None):
|
||||
try:
|
||||
endpoints = self.list_endpoints()
|
||||
ret = self.driver.delete_service(service_id)
|
||||
notifications.Audit.deleted(self._SERVICE, service_id, initiator)
|
||||
self.get_service.invalidate(self, service_id)
|
||||
for endpoint in endpoints:
|
||||
if endpoint['service_id'] == service_id:
|
||||
|
@ -179,10 +182,9 @@ class Manager(manager.Manager):
|
|||
def list_services(self, hints=None):
|
||||
return self.driver.list_services(hints or driver_hints.Hints())
|
||||
|
||||
@notifications.created(_ENDPOINT)
|
||||
def create_endpoint(self, endpoint_id, endpoint_ref):
|
||||
def create_endpoint(self, endpoint_id, endpoint_ref, initiator=None):
|
||||
try:
|
||||
return self.driver.create_endpoint(endpoint_id, endpoint_ref)
|
||||
ref = self.driver.create_endpoint(endpoint_id, endpoint_ref)
|
||||
except exception.RegionNotFound:
|
||||
raise exception.ValidationError(attribute='endpoint region_id',
|
||||
target='region table')
|
||||
|
@ -190,16 +192,19 @@ class Manager(manager.Manager):
|
|||
service_id = endpoint_ref.get('service_id')
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
|
||||
@notifications.updated(_ENDPOINT)
|
||||
def update_endpoint(self, endpoint_id, endpoint_ref):
|
||||
notifications.Audit.created(self._ENDPOINT, endpoint_id, initiator)
|
||||
return ref
|
||||
|
||||
def update_endpoint(self, endpoint_id, endpoint_ref, initiator=None):
|
||||
ref = self.driver.update_endpoint(endpoint_id, endpoint_ref)
|
||||
notifications.Audit.updated(self._ENDPOINT, endpoint_id, initiator)
|
||||
self.get_endpoint.invalidate(self, endpoint_id)
|
||||
return ref
|
||||
|
||||
@notifications.deleted(_ENDPOINT)
|
||||
def delete_endpoint(self, endpoint_id):
|
||||
def delete_endpoint(self, endpoint_id, initiator=None):
|
||||
try:
|
||||
ret = self.driver.delete_endpoint(endpoint_id)
|
||||
notifications.Audit.deleted(self._ENDPOINT, endpoint_id, initiator)
|
||||
self.get_endpoint.invalidate(self, endpoint_id)
|
||||
return ret
|
||||
except exception.NotFound:
|
||||
|
|
|
@ -21,6 +21,7 @@ from keystone.common import controller
|
|||
from keystone.common import dependency
|
||||
from keystone import exception
|
||||
from keystone.i18n import _, _LW
|
||||
from keystone import notifications
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -210,7 +211,8 @@ class UserV3(controller.V3Controller):
|
|||
# The manager layer will generate the unique ID for users
|
||||
ref = self._normalize_dict(user)
|
||||
ref = self._normalize_domain_id(context, ref)
|
||||
ref = self.identity_api.create_user(ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.identity_api.create_user(ref, initiator)
|
||||
return UserV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('domain_id', 'enabled', 'name')
|
||||
|
@ -236,7 +238,8 @@ class UserV3(controller.V3Controller):
|
|||
self._require_matching_id(user_id, user)
|
||||
self._require_matching_domain_id(
|
||||
user_id, user, self.identity_api.get_user)
|
||||
ref = self.identity_api.update_user(user_id, user)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.identity_api.update_user(user_id, user, initiator)
|
||||
return UserV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
|
@ -257,7 +260,8 @@ class UserV3(controller.V3Controller):
|
|||
|
||||
@controller.protected()
|
||||
def delete_user(self, context, user_id):
|
||||
return self.identity_api.delete_user(user_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.identity_api.delete_user(user_id, initiator)
|
||||
|
||||
@controller.protected()
|
||||
def change_password(self, context, user_id, user):
|
||||
|
@ -293,7 +297,8 @@ class GroupV3(controller.V3Controller):
|
|||
# The manager layer will generate the unique ID for groups
|
||||
ref = self._normalize_dict(group)
|
||||
ref = self._normalize_domain_id(context, ref)
|
||||
ref = self.identity_api.create_group(ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.identity_api.create_group(ref, initiator)
|
||||
return GroupV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('domain_id', 'name')
|
||||
|
@ -320,9 +325,11 @@ class GroupV3(controller.V3Controller):
|
|||
self._require_matching_id(group_id, group)
|
||||
self._require_matching_domain_id(
|
||||
group_id, group, self.identity_api.get_group)
|
||||
ref = self.identity_api.update_group(group_id, group)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.identity_api.update_group(group_id, group, initiator)
|
||||
return GroupV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_group(self, context, group_id):
|
||||
self.identity_api.delete_group(group_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
self.identity_api.delete_group(group_id, initiator)
|
||||
|
|
|
@ -582,10 +582,9 @@ class Manager(manager.Manager):
|
|||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.USER)
|
||||
|
||||
@notifications.created(_USER, result_id_arg_attr='id')
|
||||
@domains_configured
|
||||
@exception_translated('user')
|
||||
def create_user(self, user_ref):
|
||||
def create_user(self, user_ref, initiator=None):
|
||||
user = user_ref.copy()
|
||||
user['name'] = clean.user_name(user['name'])
|
||||
user.setdefault('enabled', True)
|
||||
|
@ -602,6 +601,7 @@ class Manager(manager.Manager):
|
|||
# that particular driver type.
|
||||
user['id'] = uuid.uuid4().hex
|
||||
ref = driver.create_user(user['id'], user)
|
||||
notifications.Audit.created(self._USER, user['id'], initiator)
|
||||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.USER)
|
||||
|
||||
|
@ -655,10 +655,9 @@ class Manager(manager.Manager):
|
|||
return self._set_domain_id_and_mapping(
|
||||
ref_list, domain_scope, driver, mapping.EntityType.USER)
|
||||
|
||||
@notifications.updated(_USER)
|
||||
@domains_configured
|
||||
@exception_translated('user')
|
||||
def update_user(self, user_id, user_ref):
|
||||
def update_user(self, user_id, user_ref, initiator=None):
|
||||
old_user_ref = self.get_user(user_id)
|
||||
user = user_ref.copy()
|
||||
if 'name' in user:
|
||||
|
@ -684,6 +683,8 @@ class Manager(manager.Manager):
|
|||
|
||||
ref = driver.update_user(entity_id, user)
|
||||
|
||||
notifications.Audit.updated(self._USER, user_id, initiator)
|
||||
|
||||
enabled_change = ((user.get('enabled') is False) and
|
||||
user['enabled'] != old_user_ref.get('enabled'))
|
||||
if enabled_change or user.get('password') is not None:
|
||||
|
@ -692,10 +693,9 @@ class Manager(manager.Manager):
|
|||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.USER)
|
||||
|
||||
@notifications.deleted(_USER)
|
||||
@domains_configured
|
||||
@exception_translated('user')
|
||||
def delete_user(self, user_id):
|
||||
def delete_user(self, user_id, initiator=None):
|
||||
domain_id, driver, entity_id = (
|
||||
self._get_domain_driver_and_entity_id(user_id))
|
||||
# Get user details to invalidate the cache.
|
||||
|
@ -707,11 +707,11 @@ class Manager(manager.Manager):
|
|||
user_old['domain_id'])
|
||||
self.credential_api.delete_credentials_for_user(user_id)
|
||||
self.id_mapping_api.delete_id_mapping(user_id)
|
||||
notifications.Audit.deleted(self._USER, user_id, initiator)
|
||||
|
||||
@notifications.created(_GROUP, result_id_arg_attr='id')
|
||||
@domains_configured
|
||||
@exception_translated('group')
|
||||
def create_group(self, group_ref):
|
||||
def create_group(self, group_ref, initiator=None):
|
||||
group = group_ref.copy()
|
||||
group.setdefault('description', '')
|
||||
domain_id = group['domain_id']
|
||||
|
@ -726,6 +726,9 @@ class Manager(manager.Manager):
|
|||
# that particular driver type.
|
||||
group['id'] = uuid.uuid4().hex
|
||||
ref = driver.create_group(group['id'], group)
|
||||
|
||||
notifications.Audit.created(self._GROUP, group['id'], initiator)
|
||||
|
||||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.GROUP)
|
||||
|
||||
|
@ -748,10 +751,9 @@ class Manager(manager.Manager):
|
|||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.GROUP)
|
||||
|
||||
@notifications.updated(_GROUP)
|
||||
@domains_configured
|
||||
@exception_translated('group')
|
||||
def update_group(self, group_id, group):
|
||||
def update_group(self, group_id, group, initiator=None):
|
||||
if 'domain_id' in group:
|
||||
self.resource_api.get_domain(group['domain_id'])
|
||||
domain_id, driver, entity_id = (
|
||||
|
@ -759,13 +761,13 @@ class Manager(manager.Manager):
|
|||
group = self._clear_domain_id_if_domain_unaware(driver, group)
|
||||
ref = driver.update_group(entity_id, group)
|
||||
self.get_group.invalidate(self, group_id)
|
||||
notifications.Audit.updated(self._GROUP, group_id, initiator)
|
||||
return self._set_domain_id_and_mapping(
|
||||
ref, domain_id, driver, mapping.EntityType.GROUP)
|
||||
|
||||
@notifications.deleted(_GROUP)
|
||||
@domains_configured
|
||||
@exception_translated('group')
|
||||
def delete_group(self, group_id):
|
||||
def delete_group(self, group_id, initiator=None):
|
||||
domain_id, driver, entity_id = (
|
||||
self._get_domain_driver_and_entity_id(group_id))
|
||||
user_ids = (u['id'] for u in self.list_users_in_group(group_id))
|
||||
|
@ -773,6 +775,9 @@ class Manager(manager.Manager):
|
|||
self.get_group.invalidate(self, group_id)
|
||||
self.id_mapping_api.delete_id_mapping(group_id)
|
||||
self.assignment_api.delete_group(group_id)
|
||||
|
||||
notifications.Audit.deleted(self._GROUP, group_id, initiator)
|
||||
|
||||
for uid in user_ids:
|
||||
self.emit_invalidate_user_token_persistence(uid)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
from keystone.common import controller
|
||||
from keystone.common import dependency
|
||||
from keystone.common import validation
|
||||
from keystone import notifications
|
||||
from keystone.policy import schema
|
||||
|
||||
|
||||
|
@ -27,8 +28,8 @@ class PolicyV3(controller.V3Controller):
|
|||
@validation.validated(schema.policy_create, 'policy')
|
||||
def create_policy(self, context, policy):
|
||||
ref = self._assign_unique_id(self._normalize_dict(policy))
|
||||
|
||||
ref = self.policy_api.create_policy(ref['id'], ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.policy_api.create_policy(ref['id'], ref, initiator)
|
||||
return PolicyV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('type')
|
||||
|
@ -45,9 +46,11 @@ class PolicyV3(controller.V3Controller):
|
|||
@controller.protected()
|
||||
@validation.validated(schema.policy_update, 'policy')
|
||||
def update_policy(self, context, policy_id, policy):
|
||||
ref = self.policy_api.update_policy(policy_id, policy)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.policy_api.update_policy(policy_id, policy, initiator)
|
||||
return PolicyV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_policy(self, context, policy_id):
|
||||
return self.policy_api.delete_policy(policy_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.policy_api.delete_policy(policy_id, initiator)
|
||||
|
|
|
@ -41,9 +41,10 @@ class Manager(manager.Manager):
|
|||
def __init__(self):
|
||||
super(Manager, self).__init__(CONF.policy.driver)
|
||||
|
||||
@notifications.created(_POLICY)
|
||||
def create_policy(self, policy_id, policy):
|
||||
return self.driver.create_policy(policy_id, policy)
|
||||
def create_policy(self, policy_id, policy, initiator=None):
|
||||
ref = self.driver.create_policy(policy_id, policy)
|
||||
notifications.Audit.created(self._POLICY, policy_id, initiator)
|
||||
return ref
|
||||
|
||||
def get_policy(self, policy_id):
|
||||
try:
|
||||
|
@ -51,14 +52,15 @@ class Manager(manager.Manager):
|
|||
except exception.NotFound:
|
||||
raise exception.PolicyNotFound(policy_id=policy_id)
|
||||
|
||||
@notifications.updated(_POLICY)
|
||||
def update_policy(self, policy_id, policy):
|
||||
def update_policy(self, policy_id, policy, initiator=None):
|
||||
if 'id' in policy and policy_id != policy['id']:
|
||||
raise exception.ValidationError('Cannot change policy ID')
|
||||
try:
|
||||
return self.driver.update_policy(policy_id, policy)
|
||||
ref = self.driver.update_policy(policy_id, policy)
|
||||
except exception.NotFound:
|
||||
raise exception.PolicyNotFound(policy_id=policy_id)
|
||||
notifications.Audit.updated(self._POLICY, policy_id, initiator)
|
||||
return ref
|
||||
|
||||
@manager.response_truncated
|
||||
def list_policies(self, hints=None):
|
||||
|
@ -67,12 +69,13 @@ class Manager(manager.Manager):
|
|||
# caller.
|
||||
return self.driver.list_policies()
|
||||
|
||||
@notifications.deleted(_POLICY)
|
||||
def delete_policy(self, policy_id):
|
||||
def delete_policy(self, policy_id, initiator=None):
|
||||
try:
|
||||
return self.driver.delete_policy(policy_id)
|
||||
ret = self.driver.delete_policy(policy_id)
|
||||
except exception.NotFound:
|
||||
raise exception.PolicyNotFound(policy_id=policy_id)
|
||||
notifications.Audit.deleted(self._POLICY, policy_id, initiator)
|
||||
return ret
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
|
|
|
@ -25,6 +25,7 @@ from keystone.common import dependency
|
|||
from keystone.common import validation
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone import notifications
|
||||
from keystone.resource import schema
|
||||
|
||||
|
||||
|
@ -114,7 +115,8 @@ class DomainV3(controller.V3Controller):
|
|||
@validation.validated(schema.domain_create, 'domain')
|
||||
def create_domain(self, context, domain):
|
||||
ref = self._assign_unique_id(self._normalize_dict(domain))
|
||||
ref = self.resource_api.create_domain(ref['id'], ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.resource_api.create_domain(ref['id'], ref, initiator)
|
||||
return DomainV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('enabled', 'name')
|
||||
|
@ -132,12 +134,14 @@ class DomainV3(controller.V3Controller):
|
|||
@validation.validated(schema.domain_update, 'domain')
|
||||
def update_domain(self, context, domain_id, domain):
|
||||
self._require_matching_id(domain_id, domain)
|
||||
ref = self.resource_api.update_domain(domain_id, domain)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.resource_api.update_domain(domain_id, domain, initiator)
|
||||
return DomainV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_domain(self, context, domain_id):
|
||||
return self.resource_api.delete_domain(domain_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.resource_api.delete_domain(domain_id, initiator)
|
||||
|
||||
|
||||
@dependency.requires('resource_api')
|
||||
|
@ -154,7 +158,9 @@ class ProjectV3(controller.V3Controller):
|
|||
def create_project(self, context, project):
|
||||
ref = self._assign_unique_id(self._normalize_dict(project))
|
||||
ref = self._normalize_domain_id(context, ref)
|
||||
ref = self.resource_api.create_project(ref['id'], ref)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.resource_api.create_project(ref['id'], ref,
|
||||
initiator=initiator)
|
||||
return ProjectV3.wrap_member(context, ref)
|
||||
|
||||
@controller.filterprotected('domain_id', 'enabled', 'name',
|
||||
|
@ -220,9 +226,13 @@ class ProjectV3(controller.V3Controller):
|
|||
self._require_matching_id(project_id, project)
|
||||
self._require_matching_domain_id(
|
||||
project_id, project, self.resource_api.get_project)
|
||||
ref = self.resource_api.update_project(project_id, project)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
ref = self.resource_api.update_project(project_id, project,
|
||||
initiator=initiator)
|
||||
return ProjectV3.wrap_member(context, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_project(self, context, project_id):
|
||||
return self.resource_api.delete_project(project_id)
|
||||
initiator = notifications._get_request_audit_info(context)
|
||||
return self.resource_api.delete_project(project_id,
|
||||
initiator=initiator)
|
||||
|
|
|
@ -83,8 +83,7 @@ class Manager(manager.Manager):
|
|||
action=_('max hierarchy depth reached for '
|
||||
'%s branch.') % project_id)
|
||||
|
||||
@notifications.created(_PROJECT)
|
||||
def create_project(self, tenant_id, tenant):
|
||||
def create_project(self, tenant_id, tenant, initiator=None):
|
||||
tenant = tenant.copy()
|
||||
tenant.setdefault('enabled', True)
|
||||
tenant['enabled'] = clean.project_enabled(tenant['enabled'])
|
||||
|
@ -109,6 +108,7 @@ class Manager(manager.Manager):
|
|||
parents_list)
|
||||
|
||||
ret = self.driver.create_project(tenant_id, tenant)
|
||||
notifications.Audit.created(self._PROJECT, tenant_id, initiator)
|
||||
if SHOULD_CACHE(ret):
|
||||
self.get_project.set(ret, self, tenant_id)
|
||||
self.get_project_by_name.set(ret, self, ret['name'],
|
||||
|
@ -188,8 +188,7 @@ class Manager(manager.Manager):
|
|||
'its subtree contains enabled '
|
||||
'projects') % project_id)
|
||||
|
||||
@notifications.updated(_PROJECT)
|
||||
def update_project(self, tenant_id, tenant):
|
||||
def update_project(self, tenant_id, tenant, initiator=None):
|
||||
original_tenant = self.driver.get_project(tenant_id)
|
||||
tenant = tenant.copy()
|
||||
|
||||
|
@ -214,13 +213,13 @@ class Manager(manager.Manager):
|
|||
self._disable_project(tenant_id)
|
||||
|
||||
ret = self.driver.update_project(tenant_id, tenant)
|
||||
notifications.Audit.updated(self._PROJECT, tenant_id, initiator)
|
||||
self.get_project.invalidate(self, tenant_id)
|
||||
self.get_project_by_name.invalidate(self, original_tenant['name'],
|
||||
original_tenant['domain_id'])
|
||||
return ret
|
||||
|
||||
@notifications.deleted(_PROJECT)
|
||||
def delete_project(self, tenant_id):
|
||||
def delete_project(self, tenant_id, initiator=None):
|
||||
if not self.driver.is_leaf_project(tenant_id):
|
||||
raise exception.ForbiddenAction(
|
||||
action=_('cannot delete the project %s since it is not '
|
||||
|
@ -238,6 +237,7 @@ class Manager(manager.Manager):
|
|||
self.get_project_by_name.invalidate(self, project['name'],
|
||||
project['domain_id'])
|
||||
self.credential_api.delete_credentials_for_project(tenant_id)
|
||||
notifications.Audit.deleted(self._PROJECT, tenant_id, initiator)
|
||||
return ret
|
||||
|
||||
def _filter_projects_list(self, projects_list, user_id):
|
||||
|
@ -375,8 +375,7 @@ class Manager(manager.Manager):
|
|||
def get_domain_by_name(self, domain_name):
|
||||
return self.driver.get_domain_by_name(domain_name)
|
||||
|
||||
@notifications.created(_DOMAIN)
|
||||
def create_domain(self, domain_id, domain):
|
||||
def create_domain(self, domain_id, domain, initiator=None):
|
||||
if (not self.identity_api.multiple_domains_supported and
|
||||
domain_id != CONF.identity.default_domain_id):
|
||||
raise exception.Forbidden(_('Multiple domains are not supported'))
|
||||
|
@ -384,6 +383,9 @@ class Manager(manager.Manager):
|
|||
domain.setdefault('enabled', True)
|
||||
domain['enabled'] = clean.domain_enabled(domain['enabled'])
|
||||
ret = self.driver.create_domain(domain_id, domain)
|
||||
|
||||
notifications.Audit.created(self._DOMAIN, domain_id, initiator)
|
||||
|
||||
if SHOULD_CACHE(ret):
|
||||
self.get_domain.set(ret, self, domain_id)
|
||||
self.get_domain_by_name.set(ret, self, ret['name'])
|
||||
|
@ -406,24 +408,25 @@ class Manager(manager.Manager):
|
|||
"""
|
||||
pass
|
||||
|
||||
@notifications.updated(_DOMAIN)
|
||||
def update_domain(self, domain_id, domain):
|
||||
def update_domain(self, domain_id, domain, initiator=None):
|
||||
self.assert_domain_not_federated(domain_id, domain)
|
||||
original_domain = self.driver.get_domain(domain_id)
|
||||
if 'enabled' in domain:
|
||||
domain['enabled'] = clean.domain_enabled(domain['enabled'])
|
||||
ret = self.driver.update_domain(domain_id, domain)
|
||||
notifications.Audit.updated(self._DOMAIN, domain_id, initiator)
|
||||
# disable owned users & projects when the API user specifically set
|
||||
# enabled=False
|
||||
if (original_domain.get('enabled', True) and
|
||||
not domain.get('enabled', True)):
|
||||
self._disable_domain(domain_id)
|
||||
notifications.Audit.disabled(self._DOMAIN, domain_id, initiator,
|
||||
public=False)
|
||||
|
||||
self.get_domain.invalidate(self, domain_id)
|
||||
self.get_domain_by_name.invalidate(self, original_domain['name'])
|
||||
return ret
|
||||
|
||||
@notifications.deleted(_DOMAIN)
|
||||
def delete_domain(self, domain_id):
|
||||
def delete_domain(self, domain_id, initiator=None):
|
||||
# explicitly forbid deleting the default domain (this should be a
|
||||
# carefully orchestrated manual process involving configuration
|
||||
# changes, etc)
|
||||
|
@ -451,6 +454,7 @@ class Manager(manager.Manager):
|
|||
# to the backend to delete all assignments for this domain.
|
||||
# (see Bug #1277847)
|
||||
self.driver.delete_domain(domain_id)
|
||||
notifications.Audit.deleted(self._DOMAIN, domain_id, initiator)
|
||||
self.get_domain.invalidate(self, domain_id)
|
||||
self.get_domain_by_name.invalidate(self, domain['name'])
|
||||
|
||||
|
|
|
@ -619,6 +619,17 @@ class NotificationsForEntities(test_v3.RestfulTestCase):
|
|||
# No audit event should have occurred
|
||||
self.assertEqual(0, len(self._audits))
|
||||
|
||||
def test_initiator_data_is_set(self):
|
||||
ref = self.new_domain_ref()
|
||||
resp = self.post('/domains', body={'domain': ref})
|
||||
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'])
|
||||
|
||||
|
||||
class CADFNotificationsForEntities(NotificationsForEntities):
|
||||
|
||||
|
|
Loading…
Reference in New Issue