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 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
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, ''
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, ""
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, ''