aboutsummaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/notifications.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/notifications.py')
-rw-r--r--keystone-moon/keystone/notifications.py741
1 files changed, 0 insertions, 741 deletions
diff --git a/keystone-moon/keystone/notifications.py b/keystone-moon/keystone/notifications.py
deleted file mode 100644
index 30d1713c..00000000
--- a/keystone-moon/keystone/notifications.py
+++ /dev/null
@@ -1,741 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Notifications module for OpenStack Identity Service resources"""
-
-import collections
-import functools
-import inspect
-import logging
-import socket
-
-from oslo_config import cfg
-from oslo_log import log
-import oslo_messaging
-from oslo_utils import reflection
-import pycadf
-from pycadf import cadftaxonomy as taxonomy
-from pycadf import cadftype
-from pycadf import credential
-from pycadf import eventfactory
-from pycadf import resource
-
-from keystone.i18n import _, _LE
-from keystone.common import utils
-
-
-notifier_opts = [
- cfg.StrOpt('default_publisher_id',
- help='Default publisher_id for outgoing notifications'),
- cfg.StrOpt('notification_format', default='basic',
- choices=['basic', 'cadf'],
- help='Define the notification format for Identity Service '
- 'events. A "basic" notification has information about '
- 'the resource being operated on. A "cadf" notification '
- 'has the same information, as well as information about '
- 'the initiator of the event.'),
- cfg.MultiStrOpt('notification_opt_out', default=[],
- help='Define the notification options to opt-out from. '
- 'The value expected is: '
- 'identity.<resource_type>.<operation>. This field '
- 'can be set multiple times in order to add more '
- 'notifications to opt-out from. For example:\n '
- 'notification_opt_out=identity.user.created\n '
- 'notification_opt_out=identity.authenticate.success'),
-]
-
-config_section = None
-list_opts = lambda: [(config_section, notifier_opts), ]
-
-LOG = log.getLogger(__name__)
-# NOTE(gyee): actions that can be notified. One must update this list whenever
-# a new action is supported.
-_ACTIONS = collections.namedtuple(
- 'NotificationActions',
- 'created, deleted, disabled, updated, internal')
-ACTIONS = _ACTIONS(created='created', deleted='deleted', disabled='disabled',
- updated='updated', internal='internal')
-"""The actions on resources."""
-
-CADF_TYPE_MAP = {
- 'group': taxonomy.SECURITY_GROUP,
- 'project': taxonomy.SECURITY_PROJECT,
- 'role': taxonomy.SECURITY_ROLE,
- 'user': taxonomy.SECURITY_ACCOUNT_USER,
- 'domain': taxonomy.SECURITY_DOMAIN,
- 'region': taxonomy.SECURITY_REGION,
- 'endpoint': taxonomy.SECURITY_ENDPOINT,
- 'service': taxonomy.SECURITY_SERVICE,
- 'policy': taxonomy.SECURITY_POLICY,
- 'OS-TRUST:trust': taxonomy.SECURITY_TRUST,
- 'OS-OAUTH1:access_token': taxonomy.SECURITY_CREDENTIAL,
- 'OS-OAUTH1:request_token': taxonomy.SECURITY_CREDENTIAL,
- 'OS-OAUTH1:consumer': taxonomy.SECURITY_ACCOUNT,
-}
-
-SAML_AUDIT_TYPE = 'http://docs.oasis-open.org/security/saml/v2.0'
-# resource types that can be notified
-_SUBSCRIBERS = {}
-_notifier = None
-SERVICE = 'identity'
-
-
-CONF = cfg.CONF
-CONF.register_opts(notifier_opts)
-
-# NOTE(morganfainberg): Special case notifications that are only used
-# internally for handling token persistence token deletions
-INVALIDATE_USER_TOKEN_PERSISTENCE = 'invalidate_user_tokens'
-INVALIDATE_USER_PROJECT_TOKEN_PERSISTENCE = 'invalidate_user_project_tokens'
-INVALIDATE_USER_OAUTH_CONSUMER_TOKENS = 'invalidate_user_consumer_tokens'
-
-
-class Audit(object):
- """Namespace for audit notification functions.
-
- This is a namespace object to contain all of the direct notification
- functions utilized for ``Manager`` methods.
- """
-
- @classmethod
- def _emit(cls, operation, resource_type, resource_id, initiator, public,
- actor_dict=None):
- """Directly send an event notification.
-
- :param operation: one of the values from ACTIONS
- :param resource_type: type of resource being affected
- :param resource_id: ID of the resource affected
- :param initiator: CADF representation of the user that created the
- request
- :param public: If True (default), the event will be sent to the
- notifier API. If False, the event will only be sent via
- notify_event_callbacks to in process listeners
- :param actor_dict: dictionary of actor information in the event of
- assignment notification
- """
- # NOTE(stevemar): the _send_notification function is
- # overloaded, it's used to register callbacks and to actually
- # send the notification externally. Thus, we should check
- # the desired notification format in the function instead
- # of before it.
- _send_notification(
- operation,
- resource_type,
- resource_id,
- actor_dict,
- public=public)
-
- if CONF.notification_format == 'cadf' and public:
- outcome = taxonomy.OUTCOME_SUCCESS
- _create_cadf_payload(operation, resource_type, resource_id,
- outcome, initiator)
-
- @classmethod
- def created(cls, resource_type, resource_id, initiator=None,
- public=True):
- cls._emit(ACTIONS.created, resource_type, resource_id, initiator,
- public)
-
- @classmethod
- def updated(cls, resource_type, resource_id, initiator=None,
- public=True):
- cls._emit(ACTIONS.updated, resource_type, resource_id, initiator,
- public)
-
- @classmethod
- def disabled(cls, resource_type, resource_id, initiator=None,
- public=True):
- cls._emit(ACTIONS.disabled, resource_type, resource_id, initiator,
- public)
-
- @classmethod
- def deleted(cls, resource_type, resource_id, initiator=None,
- public=True):
- cls._emit(ACTIONS.deleted, resource_type, resource_id, initiator,
- public)
-
- @classmethod
- def added_to(cls, target_type, target_id, actor_type, actor_id,
- initiator=None, public=True):
- actor_dict = {'id': actor_id,
- 'type': actor_type,
- 'actor_operation': 'added'}
- cls._emit(ACTIONS.updated, target_type, target_id, initiator, public,
- actor_dict=actor_dict)
-
- @classmethod
- def removed_from(cls, target_type, target_id, actor_type, actor_id,
- initiator=None, public=True):
- actor_dict = {'id': actor_id,
- 'type': actor_type,
- 'actor_operation': 'removed'}
- cls._emit(ACTIONS.updated, target_type, target_id, initiator, public,
- actor_dict=actor_dict)
-
- @classmethod
- def internal(cls, resource_type, resource_id):
- # NOTE(lbragstad): Internal notifications are never public and have
- # never used the initiator variable, but the _emit() method expects
- # them. Let's set them here but not expose them through the method
- # signature - that way someone can not do something like send an
- # internal notification publicly.
- initiator = None
- public = False
- cls._emit(ACTIONS.internal, resource_type, resource_id, initiator,
- public)
-
-
-def _get_callback_info(callback):
- """Return list containing callback's module and name.
-
- If the callback is a bound instance method also return the class name.
-
- :param callback: Function to call
- :type callback: function
- :returns: List containing parent module, (optional class,) function name
- :rtype: list
- """
- module_name = getattr(callback, '__module__', None)
- func_name = callback.__name__
- if inspect.ismethod(callback):
- class_name = reflection.get_class_name(callback.__self__,
- fully_qualified=False)
- return [module_name, class_name, func_name]
- else:
- return [module_name, func_name]
-
-
-def register_event_callback(event, resource_type, callbacks):
- """Register each callback with the event.
-
- :param event: Action being registered
- :type event: keystone.notifications.ACTIONS
- :param resource_type: Type of resource being operated on
- :type resource_type: str
- :param callbacks: Callback items to be registered with event
- :type callbacks: list
- :raises ValueError: If event is not a valid ACTION
- :raises TypeError: If callback is not callable
- """
- if event not in ACTIONS:
- raise ValueError(_('%(event)s is not a valid notification event, must '
- 'be one of: %(actions)s') %
- {'event': event, 'actions': ', '.join(ACTIONS)})
-
- if not hasattr(callbacks, '__iter__'):
- callbacks = [callbacks]
-
- for callback in callbacks:
- if not callable(callback):
- msg = _('Method not callable: %s') % callback
- LOG.error(msg)
- raise TypeError(msg)
- _SUBSCRIBERS.setdefault(event, {}).setdefault(resource_type, set())
- _SUBSCRIBERS[event][resource_type].add(callback)
-
- if LOG.logger.getEffectiveLevel() <= logging.DEBUG:
- # Do this only if its going to appear in the logs.
- msg = 'Callback: `%(callback)s` subscribed to event `%(event)s`.'
- callback_info = _get_callback_info(callback)
- callback_str = '.'.join(i for i in callback_info if i is not None)
- event_str = '.'.join(['identity', resource_type, event])
- LOG.debug(msg, {'callback': callback_str, 'event': event_str})
-
-
-def listener(cls):
- """A class decorator to declare a class to be a notification listener.
-
- A notification listener must specify the event(s) it is interested in by
- defining a ``event_callbacks`` attribute or property. ``event_callbacks``
- is a dictionary where the key is the type of event and the value is a
- dictionary containing a mapping of resource types to callback(s).
-
- :data:`.ACTIONS` contains constants for the currently
- supported events. There is currently no single place to find constants for
- the resource types.
-
- Example::
-
- @listener
- class Something(object):
-
- def __init__(self):
- self.event_callbacks = {
- notifications.ACTIONS.created: {
- 'user': self._user_created_callback,
- },
- notifications.ACTIONS.deleted: {
- 'project': [
- self._project_deleted_callback,
- self._do_cleanup,
- ]
- },
- }
-
- """
- def init_wrapper(init):
- @functools.wraps(init)
- def __new_init__(self, *args, **kwargs):
- init(self, *args, **kwargs)
- _register_event_callbacks(self)
- return __new_init__
-
- def _register_event_callbacks(self):
- for event, resource_types in self.event_callbacks.items():
- for resource_type, callbacks in resource_types.items():
- register_event_callback(event, resource_type, callbacks)
-
- cls.__init__ = init_wrapper(cls.__init__)
- return cls
-
-
-def notify_event_callbacks(service, resource_type, operation, payload):
- """Sends a notification to registered extensions."""
- if operation in _SUBSCRIBERS:
- if resource_type in _SUBSCRIBERS[operation]:
- for cb in _SUBSCRIBERS[operation][resource_type]:
- subst_dict = {'cb_name': cb.__name__,
- 'service': service,
- 'resource_type': resource_type,
- 'operation': operation,
- 'payload': payload}
- LOG.debug('Invoking callback %(cb_name)s for event '
- '%(service)s %(resource_type)s %(operation)s for '
- '%(payload)s', subst_dict)
- cb(service, resource_type, operation, payload)
-
-
-def _get_notifier():
- """Return a notifier object.
-
- If _notifier is None it means that a notifier object has not been set.
- If _notifier is False it means that a notifier has previously failed to
- construct.
- Otherwise it is a constructed Notifier object.
- """
- global _notifier
-
- if _notifier is None:
- host = CONF.default_publisher_id or socket.gethostname()
- try:
- transport = oslo_messaging.get_transport(CONF)
- _notifier = oslo_messaging.Notifier(transport,
- "identity.%s" % host)
- except Exception:
- LOG.exception(_LE("Failed to construct notifier"))
- _notifier = False
-
- return _notifier
-
-
-def clear_subscribers():
- """Empty subscribers dictionary.
-
- This effectively stops notifications since there will be no subscribers
- to publish to.
- """
- _SUBSCRIBERS.clear()
-
-
-def reset_notifier():
- """Reset the notifications internal state.
-
- This is used only for testing purposes.
-
- """
- global _notifier
- _notifier = None
-
-
-def _create_cadf_payload(operation, resource_type, resource_id,
- outcome, initiator):
- """Prepare data for CADF audit notifier.
-
- Transform the arguments into content to be consumed by the function that
- emits CADF events (_send_audit_notification). Specifically the
- ``resource_type`` (role, user, etc) must be transformed into a CADF
- keyword, such as: ``data/security/role``. The ``resource_id`` is added as a
- top level value for the ``resource_info`` key. Lastly, the ``operation`` is
- used to create the CADF ``action``, and the ``event_type`` name.
-
- As per the CADF specification, the ``action`` must start with create,
- update, delete, etc... i.e.: created.user or deleted.role
-
- However the ``event_type`` is an OpenStack-ism that is typically of the
- form project.resource.operation. i.e.: identity.project.updated
-
- :param operation: operation being performed (created, updated, or deleted)
- :param resource_type: type of resource being operated on (role, user, etc)
- :param resource_id: ID of resource being operated on
- :param outcome: outcomes of the operation (SUCCESS, FAILURE, etc)
- :param initiator: CADF representation of the user that created the request
- """
- if resource_type not in CADF_TYPE_MAP:
- target_uri = taxonomy.UNKNOWN
- else:
- target_uri = CADF_TYPE_MAP.get(resource_type)
- target = resource.Resource(typeURI=target_uri,
- id=resource_id)
-
- audit_kwargs = {'resource_info': resource_id}
- cadf_action = '%s.%s' % (operation, resource_type)
- event_type = '%s.%s.%s' % (SERVICE, resource_type, operation)
-
- _send_audit_notification(cadf_action, initiator, outcome,
- target, event_type, **audit_kwargs)
-
-
-def _send_notification(operation, resource_type, resource_id, actor_dict=None,
- public=True):
- """Send notification to inform observers about the affected resource.
-
- This method doesn't raise an exception when sending the notification fails.
-
- :param operation: operation being performed (created, updated, or deleted)
- :param resource_type: type of resource being operated on
- :param resource_id: ID of resource being operated on
- :param actor_dict: a dictionary containing the actor's ID and type
- :param public: if True (default), the event will be sent
- to the notifier API.
- if False, the event will only be sent via
- notify_event_callbacks to in process listeners.
- """
- payload = {'resource_info': resource_id}
-
- if actor_dict:
- payload['actor_id'] = actor_dict['id']
- payload['actor_type'] = actor_dict['type']
- payload['actor_operation'] = actor_dict['actor_operation']
-
- notify_event_callbacks(SERVICE, resource_type, operation, payload)
-
- # Only send this notification if the 'basic' format is used, otherwise
- # let the CADF functions handle sending the notification. But we check
- # here so as to not disrupt the notify_event_callbacks function.
- if public and CONF.notification_format == 'basic':
- notifier = _get_notifier()
- if notifier:
- context = {}
- event_type = '%(service)s.%(resource_type)s.%(operation)s' % {
- 'service': SERVICE,
- 'resource_type': resource_type,
- 'operation': operation}
- if _check_notification_opt_out(event_type, outcome=None):
- return
- try:
- notifier.info(context, event_type, payload)
- except Exception:
- LOG.exception(_LE(
- 'Failed to send %(res_id)s %(event_type)s notification'),
- {'res_id': resource_id, 'event_type': event_type})
-
-
-def _get_request_audit_info(context, user_id=None):
- """Collect audit information about the request used for CADF.
-
- :param context: Request context
- :param user_id: Optional user ID, alternatively collected from context
- :returns: Auditing data about the request
- :rtype: :class:`pycadf.Resource`
- """
- remote_addr = None
- http_user_agent = None
- project_id = None
- domain_id = None
-
- if context and 'environment' in context and context['environment']:
- environment = context['environment']
- remote_addr = environment.get('REMOTE_ADDR')
- http_user_agent = environment.get('HTTP_USER_AGENT')
- if not user_id:
- user_id = environment.get('KEYSTONE_AUTH_CONTEXT',
- {}).get('user_id')
- project_id = environment.get('KEYSTONE_AUTH_CONTEXT',
- {}).get('project_id')
- domain_id = environment.get('KEYSTONE_AUTH_CONTEXT',
- {}).get('domain_id')
-
- host = pycadf.host.Host(address=remote_addr, agent=http_user_agent)
- initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER, host=host)
-
- if user_id:
- initiator.user_id = user_id
- initiator.id = utils.resource_uuid(user_id)
-
- if project_id:
- initiator.project_id = project_id
- if domain_id:
- initiator.domain_id = domain_id
-
- return initiator
-
-
-class CadfNotificationWrapper(object):
- """Send CADF event notifications for various methods.
-
- This function is only used for Authentication events. Its ``action`` and
- ``event_type`` are dictated below.
-
- - action: ``authenticate``
- - event_type: ``identity.authenticate``
-
- Sends CADF notifications for events such as whether an authentication was
- successful or not.
-
- :param operation: The authentication related action being performed
-
- """
-
- def __init__(self, operation):
- self.action = operation
- self.event_type = '%s.%s' % (SERVICE, operation)
-
- def __call__(self, f):
- @functools.wraps(f)
- def wrapper(wrapped_self, context, user_id, *args, **kwargs):
- """Always send a notification."""
- initiator = _get_request_audit_info(context, user_id)
- target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
- try:
- result = f(wrapped_self, context, user_id, *args, **kwargs)
- except Exception:
- # For authentication failure send a cadf event as well
- _send_audit_notification(self.action, initiator,
- taxonomy.OUTCOME_FAILURE,
- target, self.event_type)
- raise
- else:
- _send_audit_notification(self.action, initiator,
- taxonomy.OUTCOME_SUCCESS,
- target, self.event_type)
- return result
-
- return wrapper
-
-
-class CadfRoleAssignmentNotificationWrapper(object):
- """Send CADF notifications for ``role_assignment`` methods.
-
- This function is only used for role assignment events. Its ``action`` and
- ``event_type`` are dictated below.
-
- - action: ``created.role_assignment`` or ``deleted.role_assignment``
- - event_type: ``identity.role_assignment.created`` or
- ``identity.role_assignment.deleted``
-
- Sends a CADF notification if the wrapped method does not raise an
- :class:`Exception` (such as :class:`keystone.exception.NotFound`).
-
- :param operation: one of the values from ACTIONS (created or deleted)
- """
-
- ROLE_ASSIGNMENT = 'role_assignment'
-
- def __init__(self, operation):
- self.action = '%s.%s' % (operation, self.ROLE_ASSIGNMENT)
- self.event_type = '%s.%s.%s' % (SERVICE, self.ROLE_ASSIGNMENT,
- operation)
-
- def __call__(self, f):
- @functools.wraps(f)
- def wrapper(wrapped_self, role_id, *args, **kwargs):
- """Send a notification if the wrapped callable is successful.
-
- NOTE(stevemar): The reason we go through checking kwargs
- and args for possible target and actor values is because the
- create_grant() (and delete_grant()) method are called
- differently in various tests.
- Using named arguments, i.e.::
-
- create_grant(user_id=user['id'], domain_id=domain['id'],
- role_id=role['id'])
-
- Or, using positional arguments, i.e.::
-
- create_grant(role_id['id'], user['id'], None,
- domain_id=domain['id'], None)
-
- Or, both, i.e.::
-
- create_grant(role_id['id'], user_id=user['id'],
- domain_id=domain['id'])
-
- Checking the values for kwargs is easy enough, since it comes
- in as a dictionary
-
- The actual method signature is
-
- ::
-
- create_grant(role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None,
- inherited_to_projects=False)
-
- So, if the values of actor or target are still None after
- checking kwargs, we can check the positional arguments,
- based on the method signature.
- """
- call_args = inspect.getcallargs(
- f, wrapped_self, role_id, *args, **kwargs)
- inherited = call_args['inherited_to_projects']
- context = call_args['context']
-
- initiator = _get_request_audit_info(context)
- target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
-
- audit_kwargs = {}
- if call_args['project_id']:
- audit_kwargs['project'] = call_args['project_id']
- elif call_args['domain_id']:
- audit_kwargs['domain'] = call_args['domain_id']
-
- if call_args['user_id']:
- audit_kwargs['user'] = call_args['user_id']
- elif call_args['group_id']:
- audit_kwargs['group'] = call_args['group_id']
-
- audit_kwargs['inherited_to_projects'] = inherited
- audit_kwargs['role'] = role_id
-
- try:
- result = f(wrapped_self, role_id, *args, **kwargs)
- except Exception:
- _send_audit_notification(self.action, initiator,
- taxonomy.OUTCOME_FAILURE,
- target, self.event_type,
- **audit_kwargs)
- raise
- else:
- _send_audit_notification(self.action, initiator,
- taxonomy.OUTCOME_SUCCESS,
- target, self.event_type,
- **audit_kwargs)
- return result
-
- return wrapper
-
-
-def send_saml_audit_notification(action, context, user_id, group_ids,
- identity_provider, protocol, token_id,
- outcome):
- """Send notification to inform observers about SAML events.
-
- :param action: Action being audited
- :type action: str
- :param context: Current request context to collect request info from
- :type context: dict
- :param user_id: User ID from Keystone token
- :type user_id: str
- :param group_ids: List of Group IDs from Keystone token
- :type group_ids: list
- :param identity_provider: ID of the IdP from the Keystone token
- :type identity_provider: str or None
- :param protocol: Protocol ID for IdP from the Keystone token
- :type protocol: str
- :param token_id: audit_id from Keystone token
- :type token_id: str or None
- :param outcome: One of :class:`pycadf.cadftaxonomy`
- :type outcome: str
- """
- initiator = _get_request_audit_info(context)
- target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER)
- audit_type = SAML_AUDIT_TYPE
- user_id = user_id or taxonomy.UNKNOWN
- token_id = token_id or taxonomy.UNKNOWN
- group_ids = group_ids or []
- cred = credential.FederatedCredential(token=token_id, type=audit_type,
- identity_provider=identity_provider,
- user=user_id, groups=group_ids)
- initiator.credential = cred
- event_type = '%s.%s' % (SERVICE, action)
- _send_audit_notification(action, initiator, outcome, target, event_type)
-
-
-def _send_audit_notification(action, initiator, outcome, target,
- event_type, **kwargs):
- """Send CADF notification to inform observers about the affected resource.
-
- This method logs an exception when sending the notification fails.
-
- :param action: CADF action being audited (e.g., 'authenticate')
- :param initiator: CADF resource representing the initiator
- :param outcome: The CADF outcome (taxonomy.OUTCOME_PENDING,
- taxonomy.OUTCOME_SUCCESS, taxonomy.OUTCOME_FAILURE)
- :param target: CADF resource representing the target
- :param event_type: An OpenStack-ism, typically this is the meter name that
- Ceilometer uses to poll events.
- :param kwargs: Any additional arguments passed in will be added as
- key-value pairs to the CADF event.
-
- """
- if _check_notification_opt_out(event_type, outcome):
- return
-
- event = eventfactory.EventFactory().new_event(
- eventType=cadftype.EVENTTYPE_ACTIVITY,
- outcome=outcome,
- action=action,
- initiator=initiator,
- target=target,
- observer=resource.Resource(typeURI=taxonomy.SERVICE_SECURITY))
-
- for key, value in kwargs.items():
- setattr(event, key, value)
-
- context = {}
- payload = event.as_dict()
- notifier = _get_notifier()
-
- if notifier:
- try:
- notifier.info(context, event_type, payload)
- except Exception:
- # diaper defense: any exception that occurs while emitting the
- # notification should not interfere with the API request
- LOG.exception(_LE(
- 'Failed to send %(action)s %(event_type)s notification'),
- {'action': action, 'event_type': event_type})
-
-
-def _check_notification_opt_out(event_type, outcome):
- """Check if a particular event_type has been opted-out of.
-
- This method checks to see if an event should be sent to the messaging
- service. Any event specified in the opt-out list will not be transmitted.
-
- :param event_type: This is the meter name that Ceilometer uses to poll
- events. For example: identity.user.created, or
- identity.authenticate.success, or identity.role_assignment.created
- :param outcome: The CADF outcome (taxonomy.OUTCOME_PENDING,
- taxonomy.OUTCOME_SUCCESS, taxonomy.OUTCOME_FAILURE)
-
- """
- # NOTE(stevemar): Special handling for authenticate, we look at the outcome
- # as well when evaluating. For authN events, event_type is just
- # idenitity.authenticate, which isn't fine enough to provide any opt-out
- # value, so we attach the outcome to re-create the meter name used in
- # ceilometer.
- if 'authenticate' in event_type:
- event_type = event_type + "." + outcome
-
- if event_type in CONF.notification_opt_out:
- return True
-
- return False
-
-
-emit_event = CadfNotificationWrapper
-
-
-role_assignment = CadfRoleAssignmentNotificationWrapper