def _check_default_routing_instance(obj_dict, db_obj_dict=None):
        """Prevent to update/delete default routing instance.

        Forbidden an external call to delete a default routing instance and
        also prevent an external call to change the default flag.
        """
        if is_internal_request():
            return True, ''
        if 'routing_instance_is_default' not in obj_dict:
            return True, ''
        if not db_obj_dict and not obj_dict['routing_instance_is_default']:
            # create and delete allowed if not default RI
            return True, ''
        elif (db_obj_dict and obj_dict['routing_instance_is_default'] ==
                db_obj_dict.get('routing_instance_is_default', False)):
            # update allowed if same as before
            return True, ''

        if not db_obj_dict:
            db_obj_dict = obj_dict
        msg = CANNOT_MODIFY_MSG % {
            'resource_type':
                RoutingInstance.object_type.replace('_', ' ').title(),
            'fq_name': ':'.join(db_obj_dict['fq_name']),
            'uuid': db_obj_dict['uuid'],
        }
        return False, (409, msg)
    def _check_default_routing_instance(obj_dict, db_obj_dict=None):
        """Prevent to update/delete default routing instance.

        Forbidden an external call to delete a default routing instance and
        also prevent an external call to change the default flag.
        """
        if is_internal_request():
            return True, ''
        if 'routing_instance_is_default' not in obj_dict:
            return True, ''
        if not db_obj_dict and not obj_dict['routing_instance_is_default']:
            # create and delete allowed if not default RI
            return True, ''
        elif (db_obj_dict
              and obj_dict['routing_instance_is_default'] == db_obj_dict.get(
                  'routing_instance_is_default', False)):
            # update allowed if same as before
            return True, ''

        if not db_obj_dict:
            db_obj_dict = obj_dict
        msg = ("Routing instance %s(%s) cannot modify as it the default "
               "routing instance of the %s %s(%s)" %
               (':'.join(db_obj_dict['fq_name']), db_obj_dict['uuid'],
                db_obj_dict['parent_type'].replace('_', ' '), ':'.join(
                    db_obj_dict['fq_name'][:-1]), db_obj_dict['parent_uuid']))
        return False, (400, msg)
    def check_draft_mode_state(obj_dict):
        if is_internal_request():
            # system only property
            return True, ''

        if 'draft_mode_state' in obj_dict:
            msg = ("Security resource property 'draft_mode_state' is only "
                   "readable")
            return False, (400, msg)

        return True, ''
    def check_draft_mode_state(obj_dict):
        if is_internal_request():
            # system only property
            return True, ''

        if 'draft_mode_state' in obj_dict:
            msg = ("Security resource property 'draft_mode_state' is only "
                   "readable")
            return False, (400, msg)

        return True, ''
    def wrapper(cls, obj_dict, *args, **kwargs):
        if cls.object_type not in SECURITY_OBJECT_TYPES:
            return True, ''

        if is_internal_request():
            # Ignore all internal calls to not pending pending actions
            return True, ''

        ok, result = cls._get_dedicated_draft_policy_management(obj_dict)
        if not ok:
            return False, result
        # if nothing returned without error, that means security draft mode
        # is  NOT enabled
        if result == '':
            return True, ''
        draft_pm = result

        # if a commit or discard is on going in that scope, forbidden any
        # security resource modification in that scope
        scope_type = draft_pm.get('parent_type',
                                  GlobalSystemConfig.object_type)
        scope_uuid = draft_pm.get('parent_uuid', 'unknown UUID')
        scope_fq_name = draft_pm['fq_name'][:-1]
        if not scope_fq_name:
            scope_fq_name = [GlobalSystemConfig().name]
        scope_read_lock = cls.vnc_zk_client._zk_client.read_lock(
            '%s/%s/%s' % (
                cls.server.security_lock_prefix,
                scope_type,
                ':'.join(scope_fq_name),
            ),
        )
        if not scope_read_lock.acquire(blocking=False):
            contenders = scope_read_lock.contenders()
            for contender in contenders:
                _, action_in_progress = contender.split()
                if action_in_progress:
                    break
            else:
                action_in_progress = '<unknown action>'
            msg = ("Action '%s' on %s '%s' (%s) scope is under progress. "
                   "Cannot modify %s security resource." %
                   (action_in_progress, scope_type.replace('_', ' ').title(),
                    ':'.join(scope_fq_name), scope_uuid,
                    cls.object_type.replace('_', ' ').title()))
            return False, (400, msg)
        try:
            return func(cls, draft_pm, obj_dict, *args, **kwargs)
        finally:
            scope_read_lock.release()
    def wrapper(cls, obj_dict, *args, **kwargs):
        if cls.object_type not in SECURITY_OBJECT_TYPES:
            return True, ''

        if is_internal_request():
            # Ignore all internal calls to not pending pending actions
            return True, ''

        ok, result = cls._get_dedicated_draft_policy_management(obj_dict)
        if not ok:
            return False, result
        # if nothing returned without error, that means security draft mode
        # is  NOT enabled
        if result == '':
            return True, ''
        draft_pm = result

        # if a commit or discard is on going in that scope, forbidden any
        # security resource modification in that scope
        scope_type = draft_pm.get('parent_type',
                                  GlobalSystemConfig.object_type)
        scope_uuid = draft_pm.get('parent_uuid', 'unknown UUID')
        scope_fq_name = draft_pm['fq_name'][:-1]
        if not scope_fq_name:
            scope_fq_name = [GlobalSystemConfig().name]
        scope_read_lock = cls.vnc_zk_client._zk_client.read_lock(
            '%s/%s/%s' % (
                cls.server.security_lock_prefix,
                scope_type,
                ':'.join(scope_fq_name),
            ), )
        if not scope_read_lock.acquire(blocking=False):
            contenders = scope_read_lock.contenders()
            for contender in contenders:
                _, action_in_progress = contender.split()
                if action_in_progress:
                    break
            else:
                action_in_progress = '<unknown action>'
            msg = ("Action '%s' on %s '%s' (%s) scope is under progress. "
                   "Cannot modify %s security resource." %
                   (action_in_progress, scope_type.replace(
                       '_', ' ').title(), ':'.join(scope_fq_name), scope_uuid,
                    cls.object_type.replace('_', ' ').title()))
            return False, (400, msg)
        try:
            return func(cls, draft_pm, obj_dict, *args, **kwargs)
        finally:
            scope_read_lock.release()
    def pre_dbe_delete(cls, id, obj_dict, db_conn):
        ok, result = cls.check_openstack_firewall_group_quota(obj_dict, True)
        if not ok:
            return False, result, None

        ok, result = cls.dbe_read(db_conn, 'application_policy_set', id)
        if not ok:
            return ok, result, None
        aps = result

        if aps.get('all_applications', False) and not is_internal_request():
            msg = ("Application Policy Set defined on all applications cannot "
                   "be deleted")
            return (False, (400, msg), None)

        return True, '', None
Exemple #8
0
    def _frs_fix_endpoint_address_group(cls, obj_dict, db_obj_dict=None):
        ag_refs = []
        db_ag_refs = []
        if db_obj_dict:
            db_ag_refs = db_obj_dict.get('address_group_refs', [])

        if (not is_internal_request() and 'address_group_refs' in obj_dict
                and (db_obj_dict or obj_dict['address_group_refs'])):
            msg = ("Cannot directly define Address Group reference from a "
                   "Firewall Rule. Use 'address_group' endpoints property in "
                   "the Firewall Rule")
            return False, (400, msg)

        for ep_name in ['endpoint_1', 'endpoint_2']:
            if (ep_name not in obj_dict and db_obj_dict
                    and ep_name in db_obj_dict):
                ep = db_obj_dict.get(ep_name)
                if ep is None:
                    continue
                ag_fq_name_str = ep.get('address_group')
                if ag_fq_name_str:
                    ag_fq_name = ag_fq_name_str.split(':')
                    [
                        ag_refs.append(ref) for ref in db_ag_refs
                        if ref['to'] == ag_fq_name
                    ]
            else:
                ep = obj_dict.get(ep_name)
                if ep is None:
                    continue
                ag_fq_name_str = ep.get('address_group')
                if ag_fq_name_str:
                    ag_fq_name = ag_fq_name_str.split(':')
                    try:
                        ag_uuid = cls.db_conn.fq_name_to_uuid(
                            'address_group', ag_fq_name)
                    except NoIdError:
                        msg = ('No Address Group object found for %s' %
                               ag_fq_name_str)
                        return False, (404, msg)
                    ag_refs.append({'to': ag_fq_name, 'uuid': ag_uuid})

        if {r['uuid'] for r in ag_refs} != {r['uuid'] for r in db_ag_refs}:
            obj_dict['address_group_refs'] = ag_refs

        return True, ''
    def _frs_fix_endpoint_address_group(cls, obj_dict, db_obj_dict=None):
        ag_refs = []
        db_ag_refs = []
        if db_obj_dict:
            db_ag_refs = db_obj_dict.get('address_group_refs', [])

        if (not is_internal_request() and 'address_group_refs' in obj_dict and
                (db_obj_dict or obj_dict['address_group_refs'])):
            msg = ("Cannot directly define Address Group reference from a "
                   "Firewall Rule. Use 'address_group' endpoints property in "
                   "the Firewall Rule")
            return False, (400, msg)

        for ep_name in ['endpoint_1', 'endpoint_2']:
            if (ep_name not in obj_dict and db_obj_dict and
                    ep_name in db_obj_dict):
                ep = db_obj_dict.get(ep_name)
                if ep is None:
                    continue
                ag_fq_name_str = ep.get('address_group')
                if ag_fq_name_str:
                    ag_fq_name = ag_fq_name_str.split(':')
                    [ag_refs.append(ref) for ref in db_ag_refs
                     if ref['to'] == ag_fq_name]
            else:
                ep = obj_dict.get(ep_name)
                if ep is None:
                    continue
                ag_fq_name_str = ep.get('address_group')
                if ag_fq_name_str:
                    ag_fq_name = ag_fq_name_str.split(':')
                    try:
                        ag_uuid = cls.db_conn.fq_name_to_uuid('address_group',
                                                              ag_fq_name)
                    except NoIdError:
                        msg = ('No Address Group object found for %s' %
                               ag_fq_name_str)
                        return False, (404, msg)
                    ag_refs.append({'to': ag_fq_name, 'uuid': ag_uuid})

        if {r['uuid'] for r in ag_refs} != {r['uuid'] for r in db_ag_refs}:
            obj_dict['address_group_refs'] = ag_refs

        return True, ''
Exemple #10
0
    def _check_default_vn_valid(self, req_dict, is_create, non_vn_ref_update):
        if is_internal_request() or non_vn_ref_update:
            return True, ''
        vn_type_set = set()

        err_op = ''
        if is_create:
            err_op = 'created'
        else:
            err_op = 'updated'

        for ref in req_dict.get('virtual_network_refs', []):
            if 'attr' in ref and ref['attr'].get('virtual_network_type'):
                vn_type_set.add(ref['attr'].get('virtual_network_type'))

        vn_types = ['left', 'right']
        for vn_type in vn_types:
            if not self.is_default_vn_ref_valid(vn_type_set, vn_type,
                                                is_create):
                msg = ("default hbf-%s Virtual network  reference cannot be "
                       "%s" % (vn_type, err_op))
                return False, (400, msg)

        return True, ''
    def _frs_fix_endpoint_tag(cls, obj_dict, db_obj_dict=None):
        obj_parent_type = obj_dict.get('parent_type')
        obj_fq_name = obj_dict.get('fq_name')
        tag_refs = []
        db_tag_refs = []
        if db_obj_dict:
            obj_fq_name = db_obj_dict['fq_name']
            obj_parent_type = db_obj_dict['parent_type']
            db_tag_refs = db_obj_dict.get('tag_refs', [])

        if (not is_internal_request() and 'tag_refs' in obj_dict and
                (db_obj_dict or obj_dict['tag_refs'])):
            msg = ("Cannot directly define Tags reference from a Firewall "
                   "Rule. Use 'tags' endpoints property in the Firewall Rule")
            return False, (400, msg)

        def _get_tag_fq_name(tag_name):
            # unless global, inherit project id from caller
            if "=" not in tag_name:
                return False, (404, "Invalid tag name '%s'" % tag_name)
            if tag_name[0:7] == 'global:':
                tag_fq_name = [tag_name[7:]]
            # Owned by a policy management, could be a global resource or a
            # global/scoped draft resource
            elif obj_parent_type == PolicyManagement.resource_type:
                # global: [default-pm:sec-res] => [tag-res]
                # draft global: [draft-pm:sec-res] => [tag-res]
                # draft scope: [domain:project:draft-pm:sec-res] =>
                #              [domain:project:tag-res]
                tag_fq_name = obj_fq_name[:-2] + [tag_name]
            # Project scoped resource, tag has to be in same scoped
            elif obj_parent_type == Project.resource_type:
                # scope: [domain:project:sec-res] =>
                #        [domain:project:tag-res]
                tag_fq_name = obj_fq_name[:-1] + [tag_name]
            else:
                msg = ("Firewall rule %s (%s) parent type '%s' is not "
                       "supported as security resource scope" %
                       (obj_parent_type, ':'.join(obj_fq_name),
                        obj_dict['uuid']))
                return False, (400, msg)

            return True, tag_fq_name

        for ep_name in ['endpoint_1', 'endpoint_2']:
            if (ep_name not in obj_dict and db_obj_dict and
                    ep_name in db_obj_dict):
                ep = db_obj_dict.get(ep_name)
                if ep is None:
                    continue
                for tag_name in set(ep.get('tags', [])):
                    ok, result = _get_tag_fq_name(tag_name)
                    if not ok:
                        return False, result
                    tag_fq_name = result
                    [tag_refs.append(ref) for ref in db_tag_refs
                     if ref['to'] == tag_fq_name]
            else:
                ep = obj_dict.get(ep_name)
                if ep is None:
                    continue
                ep['tag_ids'] = []
                for tag_name in set(ep.get('tags', []) or []):
                    ok, result = _get_tag_fq_name(tag_name)
                    if not ok:
                        return False, result
                    tag_fq_name = result
                    ok, result = cls.server.get_resource_class('tag').locate(
                        tag_fq_name, create_it=False, fields=['tag_id'])
                    if not ok:
                        return False, result
                    tag_dict = result
                    ep['tag_ids'].append(int(tag_dict['tag_id'], 0))
                    tag_refs.append(
                        {'to': tag_fq_name, 'uuid': tag_dict['uuid']})

        if {r['uuid'] for r in tag_refs} != {r['uuid'] for r in db_tag_refs}:
            obj_dict['tag_refs'] = tag_refs

        return True, ''
 def _check_all_applications_flag(obj_dict):
     # all_applications flag is read-only for user
     if not is_internal_request() and 'all_applications' in obj_dict:
         msg = "Application policy set 'all-applications' flag is read-only"
         return (False, (400, msg))
     return True, ""
Exemple #13
0
    def _frs_fix_endpoint_tag(cls, obj_dict, db_obj_dict=None):
        obj_parent_type = obj_dict.get('parent_type')
        obj_fq_name = obj_dict.get('fq_name')
        tag_refs = []
        db_tag_refs = []
        if db_obj_dict:
            obj_fq_name = db_obj_dict['fq_name']
            obj_parent_type = db_obj_dict['parent_type']
            db_tag_refs = db_obj_dict.get('tag_refs', [])

        if (not is_internal_request() and 'tag_refs' in obj_dict
                and (db_obj_dict or obj_dict['tag_refs'])):
            msg = ("Cannot directly define Tags reference from a Firewall "
                   "Rule. Use 'tags' endpoints property in the Firewall Rule")
            return False, (400, msg)

        def _get_tag_fq_name(tag_name):
            # unless global, inherit project id from caller
            if "=" not in tag_name:
                return False, (404, "Invalid tag name '%s'" % tag_name)
            if tag_name[0:7] == 'global:':
                tag_fq_name = [tag_name[7:]]
            # Owned by a policy management, could be a global resource or a
            # global/scoped draft resource
            elif obj_parent_type == PolicyManagement.resource_type:
                # global: [default-pm:sec-res] => [tag-res]
                # draft global: [draft-pm:sec-res] => [tag-res]
                # draft scope: [domain:project:draft-pm:sec-res] =>
                #              [domain:project:tag-res]
                tag_fq_name = obj_fq_name[:-2] + [tag_name]
            # Project scoped resource, tag has to be in same scoped
            elif obj_parent_type == Project.resource_type:
                # scope: [domain:project:sec-res] =>
                #        [domain:project:tag-res]
                tag_fq_name = obj_fq_name[:-1] + [tag_name]
            else:
                msg = (
                    "Firewall rule %s (%s) parent type '%s' is not "
                    "supported as security resource scope" %
                    (obj_parent_type, ':'.join(obj_fq_name), obj_dict['uuid']))
                return False, (400, msg)

            return True, tag_fq_name

        for ep_name in ['endpoint_1', 'endpoint_2']:
            if (ep_name not in obj_dict and db_obj_dict
                    and ep_name in db_obj_dict):
                ep = db_obj_dict.get(ep_name)
                if ep is None:
                    continue
                for tag_name in set(ep.get('tags', [])):
                    ok, result = _get_tag_fq_name(tag_name)
                    if not ok:
                        return False, result
                    tag_fq_name = result
                    [
                        tag_refs.append(ref) for ref in db_tag_refs
                        if ref['to'] == tag_fq_name
                    ]
            else:
                ep = obj_dict.get(ep_name)
                if ep is None:
                    continue
                ep['tag_ids'] = []
                for tag_name in set(ep.get('tags', []) or []):
                    ok, result = _get_tag_fq_name(tag_name)
                    if not ok:
                        return False, result
                    tag_fq_name = result
                    ok, result = cls.server.get_resource_class('tag').locate(
                        tag_fq_name, create_it=False, fields=['tag_id'])
                    if not ok:
                        return False, result
                    tag_dict = result
                    ep['tag_ids'].append(int(tag_dict['tag_id'], 0))
                    tag_refs.append({
                        'to': tag_fq_name,
                        'uuid': tag_dict['uuid']
                    })

        if {r['uuid'] for r in tag_refs} != {r['uuid'] for r in db_tag_refs}:
            obj_dict['tag_refs'] = tag_refs

        return True, ''