Example #1
0
    def check_alarm_actions(alarm):
        max_actions = pecan.request.cfg.api.alarm_max_actions
        for state in state_kind:
            actions_name = state.replace(" ", "_") + "_actions"
            actions = getattr(alarm, actions_name)
            if not actions:
                continue

            action_set = set(actions)
            if len(actions) != len(action_set):
                LOG.info(_LI("duplicate actions are found: %s, " "remove duplicate ones"), actions)
                actions = list(action_set)
                setattr(alarm, actions_name, actions)

            if 0 < max_actions < len(actions):
                error = _("%(name)s count exceeds maximum value " "%(maximum)d") % {
                    "name": actions_name,
                    "maximum": max_actions,
                }
                raise base.ClientSideError(error)

            limited = rbac.get_limited_to_project(pecan.request.headers, pecan.request.enforcer)

            for action in actions:
                try:
                    url = netutils.urlsplit(action)
                except Exception:
                    error = _("Unable to parse action %s") % action
                    raise base.ClientSideError(error)
                if url.scheme not in ACTIONS_SCHEMA:
                    error = _("Unsupported action %s") % action
                    raise base.ClientSideError(error)
                if limited and url.scheme in ("log", "test"):
                    error = _("You are not authorized to create " "action: %s") % action
                    raise base.ClientSideError(error, status_code=401)
Example #2
0
    def history(self, q=None, sort=None, limit=None, marker=None):
        """Assembles the alarm history requested.

        :param q: Filter rules for the changes to be described.
        :param sort: A list of pairs of sort key and sort dir.
        :param limit: The maximum number of items to be return.
        :param marker: The pagination query marker.
        """

        # Ensure alarm exists
        self._enforce_rbac('alarm_history')

        q = q or []
        # allow history to be returned for deleted alarms, but scope changes
        # returned to those carried out on behalf of the auth'd tenant, to
        # avoid inappropriate cross-tenant visibility of alarm history
        auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                                   pecan.request.enforcer)
        conn = pecan.request.storage
        kwargs = v2_utils.query_to_kwargs(
            q, conn.get_alarm_changes, ['on_behalf_of', 'alarm_id'])
        if sort or limit or marker:
            kwargs['pagination'] = v2_utils.get_pagination_options(
                sort, limit, marker, models.AlarmChange)
        return [AlarmChange.from_db_model(ac)
                for ac in conn.get_alarm_changes(self._id, auth_project,
                                                 **kwargs)]
Example #3
0
    def history(self, q=None, sort=None, limit=None, marker=None):
        """Assembles the alarm history requested.

        :param q: Filter rules for the changes to be described.
        :param sort: A list of pairs of sort key and sort dir.
        :param limit: The maximum number of items to be return.
        :param marker: The pagination query marker.
        """

        # Ensure alarm exists
        self._enforce_rbac('alarm_history')

        q = q or []
        # allow history to be returned for deleted alarms, but scope changes
        # returned to those carried out on behalf of the auth'd tenant, to
        # avoid inappropriate cross-tenant visibility of alarm history
        auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                                   pecan.request.enforcer)
        conn = pecan.request.storage
        kwargs = v2_utils.query_to_kwargs(q, conn.get_alarm_changes,
                                          ['on_behalf_of', 'alarm_id'])
        if sort or limit or marker:
            kwargs['pagination'] = v2_utils.get_pagination_options(
                sort, limit, marker, models.AlarmChange)
        return [
            AlarmChange.from_db_model(ac)
            for ac in conn.get_alarm_changes(self._id, auth_project, **kwargs)
        ]
Example #4
0
 def _alarm(self):
     self.conn = pecan.request.alarm_storage_conn
     auth_project = rbac.get_limited_to_project(pecan.request.headers)
     alarms = list(self.conn.get_alarms(alarm_id=self._id,
                                        project=auth_project))
     if not alarms:
         raise base.AlarmNotFound(alarm=self._id, auth_project=auth_project)
     return alarms[0]
Example #5
0
 def _alarm(self):
     self.conn = pecan.request.alarm_storage_conn
     auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                                pecan.request.enforcer)
     alarms = list(
         self.conn.get_alarms(alarm_id=self._id, project=auth_project))
     if not alarms:
         raise base.AlarmNotFound(alarm=self._id, auth_project=auth_project)
     return alarms[0]
Example #6
0
def _verify_query_segregation(query, auth_project=None):
    """Ensure non-admin queries are not constrained to another project."""
    auth_project = (auth_project or rbac.get_limited_to_project(
        pecan.request.headers, pecan.request.enforcer))

    if not auth_project:
        return

    for q in query:
        if q.field in ('project', 'project_id') and auth_project != q.value:
            raise base.ProjectNotAuthorized(q.value)
Example #7
0
 def _enforce_rbac(self, rbac_directive):
     # TODO(sileht): We should be able to relax this since we
     # pass the alarm object to the enforcer.
     auth_project = rbac.get_limited_to_project(pecan.request.headers, pecan.request.enforcer)
     alarms = list(pecan.request.storage.get_alarms(alarm_id=self._id, project=auth_project))
     if not alarms:
         raise base.AlarmNotFound(alarm=self._id, auth_project=auth_project)
     alarm = alarms[0]
     target = {"user_id": alarm.user_id, "project_id": alarm.project_id}
     rbac.enforce(rbac_directive, pecan.request.headers, pecan.request.enforcer, target)
     return alarm
Example #8
0
File: utils.py Project: chungg/aodh
def _verify_query_segregation(query, auth_project=None):
    """Ensure non-admin queries are not constrained to another project."""
    auth_project = (auth_project or
                    rbac.get_limited_to_project(pecan.request.headers))

    if not auth_project:
        return

    for q in query:
        if q.field in ('project', 'project_id') and auth_project != q.value:
            raise base.ProjectNotAuthorized(q.value)
Example #9
0
File: query.py Project: chungg/aodh
    def _force_visibility(self, visibility_field):
        """Force visibility field.

        If the tenant is not admin insert an extra
        "and <visibility_field>=<tenant's project_id>" clause to the query.
        """
        authorized_project = rbac.get_limited_to_project(pecan.request.headers)
        is_admin = authorized_project is None
        if not is_admin:
            self._restrict_to_project(authorized_project, visibility_field)
            self._check_cross_project_references(authorized_project,
                                                 visibility_field)
Example #10
0
    def _force_visibility(self, visibility_field):
        """Force visibility field.

        If the tenant is not admin insert an extra
        "and <visibility_field>=<tenant's project_id>" clause to the query.
        """
        authorized_project = rbac.get_limited_to_project(
            pecan.request.headers, pecan.request.enforcer)
        is_admin = authorized_project is None
        if not is_admin:
            self._restrict_to_project(authorized_project, visibility_field)
            self._check_cross_project_references(authorized_project,
                                                 visibility_field)
Example #11
0
 def _enforce_rbac(self, rbac_directive):
     # TODO(sileht): We should be able to relax this since we
     # pass the alarm object to the enforcer.
     auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                                pecan.request.enforcer)
     alarms = list(
         pecan.request.storage.get_alarms(alarm_id=self._id,
                                          project=auth_project))
     if not alarms:
         raise base.AlarmNotFound(alarm=self._id, auth_project=auth_project)
     alarm = alarms[0]
     target = {'user_id': alarm.user_id, 'project_id': alarm.project_id}
     rbac.enforce(rbac_directive, pecan.request.headers,
                  pecan.request.enforcer, target)
     return alarm
Example #12
0
def get_auth_project(on_behalf_of=None):
    # when an alarm is created by an admin on behalf of another tenant
    # we must ensure for:
    # - threshold alarm, that an implicit query constraint on project_id is
    #   added so that admin-level visibility on statistics is not leaked
    # Hence, for null auth_project (indicating admin-ness) we check if
    # the creating tenant differs from the tenant on whose behalf the
    # alarm is being created
    auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                               pecan.request.enforcer)
    created_by = pecan.request.headers.get('X-Project-Id')
    is_admin = auth_project is None

    if is_admin and on_behalf_of != created_by:
        auth_project = on_behalf_of
    return auth_project
Example #13
0
File: utils.py Project: chungg/aodh
def get_auth_project(on_behalf_of=None):
    # when an alarm is created by an admin on behalf of another tenant
    # we must ensure for:
    # - threshold alarm, that an implicit query constraint on project_id is
    #   added so that admin-level visibility on statistics is not leaked
    # - combination alarm, that alarm ids verification is scoped to
    #   alarms owned by the alarm project.
    # hence for null auth_project (indicating admin-ness) we check if
    # the creating tenant differs from the tenant on whose behalf the
    # alarm is being created
    auth_project = rbac.get_limited_to_project(pecan.request.headers)
    created_by = pecan.request.headers.get('X-Project-Id')
    is_admin = auth_project is None

    if is_admin and on_behalf_of != created_by:
        auth_project = on_behalf_of
    return auth_project
Example #14
0
    def history(self, q=None):
        """Assembles the alarm history requested.

        :param q: Filter rules for the changes to be described.
        """

        rbac.enforce('alarm_history', pecan.request)

        q = q or []
        # allow history to be returned for deleted alarms, but scope changes
        # returned to those carried out on behalf of the auth'd tenant, to
        # avoid inappropriate cross-tenant visibility of alarm history
        auth_project = rbac.get_limited_to_project(pecan.request.headers)
        conn = pecan.request.alarm_storage_conn
        kwargs = v2_utils.query_to_kwargs(
            q, conn.get_alarm_changes, ['on_behalf_of', 'alarm_id'])
        return [AlarmChange.from_db_model(ac)
                for ac in conn.get_alarm_changes(self._id, auth_project,
                                                 **kwargs)]
Example #15
0
    def check_alarm_actions(alarm):
        max_actions = pecan.request.cfg.api.alarm_max_actions
        for state in state_kind:
            actions_name = state.replace(" ", "_") + '_actions'
            actions = getattr(alarm, actions_name)
            if not actions:
                continue

            action_set = set(actions)
            if len(actions) != len(action_set):
                LOG.info(
                    'duplicate actions are found: %s, '
                    'remove duplicate ones', actions)
                actions = list(action_set)
                setattr(alarm, actions_name, actions)

            if 0 < max_actions < len(actions):
                error = _('%(name)s count exceeds maximum value '
                          '%(maximum)d') % {
                              "name": actions_name,
                              "maximum": max_actions
                          }
                raise base.ClientSideError(error)

            limited = rbac.get_limited_to_project(pecan.request.headers,
                                                  pecan.request.enforcer)

            for action in actions:
                try:
                    url = netutils.urlsplit(action)
                except Exception:
                    error = _("Unable to parse action %s") % action
                    raise base.ClientSideError(error)
                if url.scheme not in ACTIONS_SCHEMA:
                    error = _("Unsupported action %s") % action
                    raise base.ClientSideError(error)
                if limited and url.scheme in ('log', 'test'):
                    error = _('You are not authorized to create '
                              'action: %s') % action
                    raise base.ClientSideError(error, status_code=401)
Example #16
0
    def history(self, q=None):
        """Assembles the alarm history requested.

        :param q: Filter rules for the changes to be described.
        """

        rbac.enforce('alarm_history', pecan.request.headers,
                     pecan.request.enforcer)

        q = q or []
        # allow history to be returned for deleted alarms, but scope changes
        # returned to those carried out on behalf of the auth'd tenant, to
        # avoid inappropriate cross-tenant visibility of alarm history
        auth_project = rbac.get_limited_to_project(pecan.request.headers,
                                                   pecan.request.enforcer)
        conn = pecan.request.alarm_storage_conn
        kwargs = v2_utils.query_to_kwargs(q, conn.get_alarm_changes,
                                          ['on_behalf_of', 'alarm_id'])
        return [
            AlarmChange.from_db_model(ac)
            for ac in conn.get_alarm_changes(self._id, auth_project, **kwargs)
        ]
Example #17
0
    def check_alarm_actions(alarm):
        actions_schema = aodh_alarm.NOTIFIER_SCHEMAS
        max_actions = cfg.CONF.alarm.alarm_max_actions
        for state in state_kind:
            actions_name = state.replace(" ", "_") + '_actions'
            actions = getattr(alarm, actions_name)
            if not actions:
                continue

            action_set = set(actions)
            if len(actions) != len(action_set):
                LOG.info(_('duplicate actions are found: %s, '
                           'remove duplicate ones') % actions)
                actions = list(action_set)
                setattr(alarm, actions_name, actions)

            if 0 < max_actions < len(actions):
                error = _('%(name)s count exceeds maximum value '
                          '%(maximum)d') % {"name": actions_name,
                                            "maximum": max_actions}
                raise base.ClientSideError(error)

            limited = rbac.get_limited_to_project(pecan.request.headers)

            for action in actions:
                try:
                    url = netutils.urlsplit(action)
                except Exception:
                    error = _("Unable to parse action %s") % action
                    raise base.ClientSideError(error)
                if url.scheme not in actions_schema:
                    error = _("Unsupported action %s") % action
                    raise base.ClientSideError(error)
                if limited and url.scheme in ('log', 'test'):
                    error = _('You are not authorized to create '
                              'action: %s') % action
                    raise base.ClientSideError(error, status_code=401)