예제 #1
0
        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
예제 #2
0
    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
예제 #3
0
def build_audit_initiator():
    """A pyCADF initiator describing the current authenticated context."""
    pycadf_host = host.Host(address=flask.request.remote_addr,
                            agent=str(flask.request.user_agent))
    initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER,
                                  host=pycadf_host)
    oslo_context = flask.request.environ.get(context.REQUEST_CONTEXT_ENV)
    if oslo_context.user_id:
        initiator.id = utils.resource_uuid(oslo_context.user_id)
        initiator.user_id = oslo_context.user_id

    if oslo_context.project_id:
        initiator.project_id = oslo_context.project_id

    if oslo_context.domain_id:
        initiator.domain_id = oslo_context.domain_id

    return initiator
예제 #4
0
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.

    """

    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
                })
예제 #5
0
    def test_resource(self):
        res = resource.Resource(typeURI='storage',
                                name='res_name',
                                domain='res_domain',
                                ref='res_ref',
                                credential=credential.Credential(
                                    token=identifier.generate_uuid()),
                                host=host.Host(address='192.168.0.1'),
                                geolocation=geolocation.Geolocation(),
                                geolocationId=identifier.generate_uuid())

        res.add_attachment(attachment.Attachment(typeURI='attachURI',
                                                 content='content',
                                                 name='attachment_name'))
        res.add_address(endpoint.Endpoint(url='http://192.168.0.1'))

        self.assertEqual(res.is_valid(), True)
        dict_res = res.as_dict()
        for key in resource.RESOURCE_KEYNAMES:
            self.assertIn(key, dict_res)
예제 #6
0
        def fake_audit(action, initiator, outcome, target,
                       event_type, **kwargs):
            service_security = cadftaxonomy.SERVICE_SECURITY

            event = eventfactory.EventFactory().new_event(
                eventType=cadftype.EVENTTYPE_ACTIVITY,
                outcome=outcome,
                action=action,
                initiator=initiator,
                target=target,
                observer=cadfresource.Resource(typeURI=service_security))

            for key, value in kwargs.items():
                setattr(event, key, value)

            audit = {
                'payload': event.as_dict(),
                'event_type': event_type,
                'send_notification_called': True}
            self._audits.append(audit)
예제 #7
0
 def test_event_unique(self):
     ev = event.Event(eventType='activity',
                      initiator=resource.Resource(typeURI='storage'),
                      action='read',
                      target=resource.Resource(typeURI='storage'),
                      observer=resource.Resource(id='target'),
                      outcome='success')
     time.sleep(1)
     ev2 = event.Event(eventType='activity',
                       initiator=resource.Resource(typeURI='storage'),
                       action='read',
                       target=resource.Resource(typeURI='storage'),
                       observer=resource.Resource(id='target'),
                       outcome='success')
     self.assertNotEqual(ev.id, ev2.id)
     self.assertNotEqual(ev.eventTime, ev2.eventTime)
예제 #8
0
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)
        initiator = _add_username_to_initiator(initiator)

    if project_id:
        initiator.project_id = project_id
    if domain_id:
        initiator.domain_id = domain_id

    return initiator
예제 #9
0
        def fake_notify(action, initiator, outcome, target, event_type,
                        **kwargs):
            service_security = cadftaxonomy.SERVICE_SECURITY

            event = eventfactory.EventFactory().new_event(
                eventType=cadftype.EVENTTYPE_ACTIVITY,
                outcome=outcome,
                action=action,
                initiator=initiator,
                target=target,
                observer=cadfresource.Resource(typeURI=service_security))

            for key, value in kwargs.items():
                setattr(event, key, value)

            note = {
                'action': action,
                'initiator': initiator,
                'event': event,
                'send_notification_called': True
            }
            self._notifications.append(note)
예제 #10
0
 def test_event_resource_shortform_not_self(self):
     self.assertRaises(ValueError,
                       lambda: event.Event(
                           eventType='activity',
                           initiator=resource.Resource(typeURI='storage'),
                           action='read',
                           target=resource.Resource(id='target'),
                           observer=resource.Resource(id='target'),
                           outcome='success'))
     self.assertRaises(ValueError,
                       lambda: event.Event(
                           eventType='activity',
                           initiator=resource.Resource(id='initiator'),
                           action='read',
                           target=resource.Resource(typeURI='storage'),
                           observer=resource.Resource(id='target'),
                           outcome='success'))
예제 #11
0
def _create_cadf_payload(operation, resource_type, resource_id,
                         outcome, initiator, reason=None):
    """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
    :param reason: pycadf object containing the response code and
                   message description
    """
    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, reason=reason, **audit_kwargs)
예제 #12
0
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)
예제 #13
0
    def _process_response(self, request, response=None):
        # NOTE(gordc): handle case where error processing request
        if 'cadf_event' not in request.environ:
            self._create_event(request)
        event = request.environ['cadf_event']

        if response:
            if response.status_int >= 200 and response.status_int < 400:
                result = taxonomy.OUTCOME_SUCCESS
            else:
                result = taxonomy.OUTCOME_FAILURE
            event.reason = reason.Reason(reasonType='HTTP',
                                         reasonCode=str(response.status_int))
        else:
            result = taxonomy.UNKNOWN

        event.outcome = result
        event.add_reporterstep(
            reporterstep.Reporterstep(role=cadftype.REPORTER_ROLE_MODIFIER,
                                      reporter=resource.Resource(id='target'),
                                      reporterTime=timestamp.get_utc_now()))

        self._notifier.notify(request.context, 'audit.http.response',
                              event.as_dict())
예제 #14
0
        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

            # For backward compatability, send both old and new event_type.
            # Deprecate old format and remove it in the next release.
            event_types = [self.deprecated_event_type, self.event_type]
            versionutils.deprecated(
                as_of=versionutils.deprecated.KILO,
                remove_in=+1,
                what=('sending duplicate %s notification event type' %
                      self.deprecated_event_type),
                in_favor_of='%s notification event type' % self.event_type)
            try:
                result = f(wrapped_self, role_id, *args, **kwargs)
            except Exception:
                for event_type in event_types:
                    _send_audit_notification(self.action, initiator,
                                             taxonomy.OUTCOME_FAILURE, target,
                                             event_type, **audit_kwargs)
                raise
            else:
                for event_type in event_types:
                    _send_audit_notification(self.action, initiator,
                                             taxonomy.OUTCOME_SUCCESS, target,
                                             event_type, **audit_kwargs)
                return result
예제 #15
0
        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
예제 #16
0
def _send_audit_notification(action,
                             initiator,
                             outcome,
                             target,
                             event_type,
                             reason=None,
                             **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.
    :param reason: Reason for the notification which contains the response
        code and message description
    """
    if _check_notification_opt_out(event_type, outcome):
        return

    global _CATALOG_HELPER_OBJ
    if _CATALOG_HELPER_OBJ is None:
        _CATALOG_HELPER_OBJ = _CatalogHelperObj()
    service_list = _CATALOG_HELPER_OBJ.catalog_api.list_services()
    service_id = None

    for i in service_list:
        if i['type'] == SERVICE:
            service_id = i['id']
            break

    event = eventfactory.EventFactory().new_event(
        eventType=cadftype.EVENTTYPE_ACTIVITY,
        outcome=outcome,
        action=action,
        initiator=initiator,
        target=target,
        reason=reason,
        observer=resource.Resource(typeURI=taxonomy.SERVICE_SECURITY))

    if service_id is not None:
        event.observer.id = service_id

    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(
                'Failed to send %(action)s %(event_type)s notification', {
                    'action': action,
                    'event_type': event_type
                })
    def emit_event(self, env, bytes_received, bytes_sent, outcome='success'):
        path = urlparse.quote(env['PATH_INFO'])
        method = env['REQUEST_METHOD']
        headers = {}
        for header in env:
            if header.startswith('HTTP_') and env[header]:
                key = header[5:]
                if isinstance(env[header], six.text_type):
                    headers[key] = six.text_type(env[header])
                else:
                    headers[key] = str(env[header])

        try:
            container = obj = None
            version, account, remainder = path.replace('/', '',
                                                       1).split('/', 2)
            if not version or not account:
                raise ValueError('Invalid path: %s' % path)
            if remainder:
                if '/' in remainder:
                    container, obj = remainder.split('/', 1)
                else:
                    container = remainder
        except ValueError:
            return

        now = timeutils.utcnow().isoformat()

        resource_metadata = {
            "path": path,
            "version": version,
            "container": container,
            "object": obj,
        }

        for header in self.metadata_headers:
            if header.upper() in headers:
                resource_metadata['http_header_%s' % header] = headers.get(
                    header.upper())

        # build object store details
        target = cadf_resource.Resource(typeURI='service/storage/object',
                                        id=account.partition(
                                            self.reseller_prefix)[2])
        target.metadata = resource_metadata
        target.action = method.lower()

        # build user details
        initiator = cadf_resource.Resource(
            typeURI='service/security/account/user',
            id=env.get('HTTP_X_USER_ID'))
        initiator.project_id = env.get('HTTP_X_TENANT_ID')

        # build notification body
        event = cadf_event.Event(eventTime=now,
                                 outcome=outcome,
                                 initiator=initiator,
                                 target=target,
                                 observer=cadf_resource.Resource(id='target'))

        # measurements
        if bytes_received:
            event.add_measurement(
                cadf_measurement.Measurement(
                    result=bytes_received,
                    metric=cadf_metric.Metric(
                        name='storage.objects.incoming.bytes', unit='B')))
        if bytes_sent:
            event.add_measurement(
                cadf_measurement.Measurement(
                    result=bytes_sent,
                    metric=cadf_metric.Metric(
                        name='storage.objects.outgoing.bytes', unit='B')))

        self._notifier.info(context.get_admin_context().to_dict(),
                            'objectstore.http.request', event.as_dict())
예제 #18
0
    def test_event(self):
        ev = event.Event(eventType='activity',
                         id=identifier.generate_uuid(),
                         eventTime=timestamp.get_utc_now(),
                         initiator=resource.Resource(typeURI='storage'),
                         initiatorId=identifier.generate_uuid(),
                         action='read',
                         target=resource.Resource(typeURI='storage'),
                         targetId=identifier.generate_uuid(),
                         observer=resource.Resource(id='target'),
                         observerId=identifier.generate_uuid(),
                         outcome='success',
                         reason=reason.Reason(reasonType='HTTP',
                                              reasonCode='200'),
                         severity='high')
        ev.add_measurement(
            measurement.Measurement(result='100',
                                    metricId=identifier.generate_uuid())),
        ev.add_tag(tag.generate_name_value_tag('name', 'val'))
        ev.add_attachment(attachment.Attachment(typeURI='attachURI',
                                                content='content',
                                                name='attachment_name'))
        ev.observer = resource.Resource(typeURI='service/security')
        ev.add_reporterstep(reporterstep.Reporterstep(
            role='observer',
            reporter=resource.Resource(typeURI='service/security')))
        ev.add_reporterstep(reporterstep.Reporterstep(
            reporterId=identifier.generate_uuid()))
        self.assertEqual(ev.is_valid(), False)

        dict_ev = ev.as_dict()
        for key in event.EVENT_KEYNAMES:
            self.assertIn(key, dict_ev)

        ev = event.Event(eventType='activity',
                         id=identifier.generate_uuid(),
                         eventTime=timestamp.get_utc_now(),
                         initiator=resource.Resource(typeURI='storage'),
                         action='read',
                         target=resource.Resource(typeURI='storage'),
                         observer=resource.Resource(id='target'),
                         outcome='success')
        self.assertEqual(ev.is_valid(), True)

        ev = event.Event(eventType='activity',
                         id=identifier.generate_uuid(),
                         eventTime=timestamp.get_utc_now(),
                         initiatorId=identifier.generate_uuid(),
                         action='read',
                         targetId=identifier.generate_uuid(),
                         observerId=identifier.generate_uuid(),
                         outcome='success')
        self.assertEqual(ev.is_valid(), True)

        ev = event.Event(eventType='activity',
                         id=identifier.generate_uuid(),
                         eventTime=timestamp.get_utc_now(),
                         initiator=resource.Resource(typeURI='storage'),
                         action='read',
                         targetId=identifier.generate_uuid(),
                         observer=resource.Resource(id='target'),
                         outcome='success')
        self.assertEqual(ev.is_valid(), True)
예제 #19
0
    def emit_event(self, env, bytes_received, bytes_sent, outcome='success'):
        if ((env.get('HTTP_X_SERVICE_PROJECT_ID') or
                env.get('HTTP_X_PROJECT_ID') or
                env.get('HTTP_X_TENANT_ID')) in self.ignore_projects or
                env.get('swift.source') is not None):
            return

        path = urlparse.quote(env['PATH_INFO'])
        method = env['REQUEST_METHOD']
        headers = {}
        for header in env:
            if header.startswith('HTTP_') and env[header]:
                key = header[5:]
                if isinstance(env[header], six.text_type):
                    headers[key] = six.text_type(env[header])
                else:
                    headers[key] = str(env[header])

        try:
            container = obj = None
            path = path.replace('/', '', 1)
            version, account, remainder = path.split('/', 2)
        except ValueError:
            try:
                version, account = path.split('/', 1)
                remainder = None
            except ValueError:
                return
        try:
            if not version or not account:
                raise ValueError('Invalid path: %s' % path)
            if remainder:
                if '/' in remainder:
                    container, obj = remainder.split('/', 1)
                else:
                    container = remainder
        except ValueError:
            return

        now = datetime.datetime.utcnow().isoformat()

        resource_metadata = {
            "path": path,
            "version": version,
            "container": container,
            "object": obj,
        }

        for header in self.metadata_headers:
            if header.upper() in headers:
                resource_metadata['http_header_%s' % header] = headers.get(
                    header.upper())

        # build object store details
        if self.reseller_prefix:
            target = cadf_resource.Resource(
                typeURI='service/storage/object',
                id=account.partition(self.reseller_prefix)[2] or path)
        else:
            target = cadf_resource.Resource(
                typeURI='service/storage/object',
                id=account)
        target.metadata = resource_metadata
        target.action = method.lower()

        # build user details
        initiator = cadf_resource.Resource(
            typeURI='service/security/account/user',
            id=env.get('HTTP_X_USER_ID'))
        initiator.project_id = (env.get('HTTP_X_PROJECT_ID') or
                                env.get('HTTP_X_TENANT_ID'))

        # build notification body
        event = cadf_event.Event(eventTime=now, outcome=outcome,
                                 action=api.convert_req_action(method),
                                 initiator=initiator, target=target,
                                 observer=cadf_resource.Resource(id='target'))

        # measurements
        if bytes_received:
            event.add_measurement(cadf_measurement.Measurement(
                result=bytes_received,
                metric=cadf_metric.Metric(
                    name='storage.objects.incoming.bytes', unit='B')))
        if bytes_sent:
            event.add_measurement(cadf_measurement.Measurement(
                result=bytes_sent,
                metric=cadf_metric.Metric(
                    name='storage.objects.outgoing.bytes', unit='B')))

        # api call
        request_metric_name = self.get_request_metric_name(method.lower())
        if request_metric_name:
            event.add_measurement(cadf_measurement.Measurement(
                result=1,
                metric=cadf_metric.Metric(
                    name=request_metric_name, unit='request')))

        if self.nonblocking_notify:
            try:
                Swift.event_queue.put(event, False)
                if not Swift.event_sender.is_alive():
                    Swift.threadLock.acquire()
                    self.start_sender_thread()
                    Swift.threadLock.release()

            except queue.Full:
                LOG.warning('Send queue FULL: Event %s not added', event.id)
        else:
            Swift.send_notification(self._notifier, event)
예제 #20
0
def _policy_resource(ra_name):
    return resource.Resource(id='anchor://certificates/policy',
                             typeURI=cadftaxonomy.SECURITY_POLICY,
                             domain=ra_name)
예제 #21
0
def _auth_resource(ra_name):
    return resource.Resource(id='anchor://authentication',
                             typeURI=cadftaxonomy.SERVICE_SECURITY,
                             domain=ra_name)
예제 #22
0
    def create_event(self, req, correlation_id):
        action = self._get_action(req)
        initiator_host = host.Host(address=req.client_addr,
                                   agent=req.user_agent)
        catalog = ast.literal_eval(req.environ['HTTP_X_SERVICE_CATALOG'])
        service_info = self.Service(type=taxonomy.UNKNOWN,
                                    name=taxonomy.UNKNOWN,
                                    id=taxonomy.UNKNOWN,
                                    admin_endp=None,
                                    private_endp=None,
                                    public_endp=None)
        default_endpoint = None
        for endp in catalog:
            admin_urlparse = urlparse.urlparse(
                endp['endpoints'][0]['adminURL'])
            public_urlparse = urlparse.urlparse(
                endp['endpoints'][0]['publicURL'])
            req_url = urlparse.urlparse(req.host_url)
            if (req_url.netloc == admin_urlparse.netloc
                    or req_url.netloc == public_urlparse.netloc):
                service_info = self._get_service_info(endp)
                break
            elif (self._MAP.default_target_endpoint_type
                  and endp['type'] == self._MAP.default_target_endpoint_type):
                default_endpoint = endp
        else:
            if default_endpoint:
                service_info = self._get_service_info(default_endpoint)

        initiator = ClientResource(
            typeURI=taxonomy.ACCOUNT_USER,
            id=identifier.norm_ns(str(req.environ['HTTP_X_USER_ID'])),
            name=req.environ['HTTP_X_USER_NAME'],
            host=initiator_host,
            credential=KeystoneCredential(
                token=req.environ['HTTP_X_AUTH_TOKEN'],
                identity_status=req.environ['HTTP_X_IDENTITY_STATUS']),
            project_id=identifier.norm_ns(req.environ['HTTP_X_PROJECT_ID']))
        target_typeURI = (self._build_typeURI(req, service_info.type)
                          if service_info.type != taxonomy.UNKNOWN else
                          service_info.type)
        target = resource.Resource(typeURI=target_typeURI,
                                   id=service_info.id,
                                   name=service_info.name)
        if service_info.admin_endp:
            target.add_address(service_info.admin_endp)
        if service_info.private_endp:
            target.add_address(service_info.private_endp)
        if service_info.public_endp:
            target.add_address(service_info.public_endp)
        event = factory.EventFactory().new_event(
            eventType=cadftype.EVENTTYPE_ACTIVITY,
            outcome=taxonomy.OUTCOME_PENDING,
            action=action,
            initiator=initiator,
            target=target,
            observer=resource.Resource(id='target'))
        event.requestPath = req.path_qs
        event.add_tag(
            tag.generate_name_value_tag('correlation_id', correlation_id))
        return event