Skip to content

Commit

Permalink
Gateway_less_Fwd: ACL should have rule to deny traffic to ip-fabric
Browse files Browse the repository at this point in the history
Closes-Bug: 1724891

Change-Id: I8025cfee261474582c1d12d362d80f98dbfa5801
(cherry picked from commit 8e263ac)
  • Loading branch information
npchandran committed Nov 22, 2017
1 parent 7cf98a1 commit f65e6c0
Show file tree
Hide file tree
Showing 7 changed files with 412 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/config/api-server/vnc_cfg_api_server.py
Expand Up @@ -2789,7 +2789,8 @@ def _db_init_entries(self):
self.config_log(msg, level=SandeshLevel.SYS_ERR)

ip_fab_vn = self.create_singleton_entry(
VirtualNetwork(cfgm_common.IP_FABRIC_VN_FQ_NAME[-1]))
VirtualNetwork(cfgm_common.IP_FABRIC_VN_FQ_NAME[-1],
is_provider_network=True))
self.create_singleton_entry(
RoutingInstance(cfgm_common.IP_FABRIC_VN_FQ_NAME[-1], ip_fab_vn,
routing_instance_is_default=True))
Expand Down
93 changes: 90 additions & 3 deletions src/config/api-server/vnc_cfg_types.py
Expand Up @@ -2322,6 +2322,76 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs):

class VirtualNetworkServer(Resource, VirtualNetwork):

@classmethod
def _check_is_provider_network_property(cls, obj_dict, db_conn,
vn_ref=None):
# no further checks if is_provider_network is not set
if 'is_provider_network' not in obj_dict:
return (True, '')
if not vn_ref:
# must be set as False for non provider VN
if obj_dict.get('is_provider_network'):
return (False,
'Non provider VN (%s) can not be '
'configured with is_provider_network = True' % (
obj_dict.get('uuid')))
else:
# compare obj_dict with db and fail
# if not same as this is a read-only property
if obj_dict.get('is_provider_network') != \
vn_ref.get('is_provider_network', False):
return (False,
'Update is_provider_network property of VN (%s) '
'is not allowed' % obj_dict.get('uuid'))
return (True, '')
# end _check_is_provider_network_property

@classmethod
def _check_provider_network(cls, obj_dict, db_conn, vn_ref=None):
# no further checks if not linked
# to a provider network
if not obj_dict.get('virtual_network_refs'):
return (True, '')
# retrieve this VN
if not vn_ref:
vn_ref = {'uuid': obj_dict['uuid'],
'is_provider_network': obj_dict.get(
'is_provider_network')}
uuids = [vn['uuid'] for vn in obj_dict.get('virtual_network_refs')]

# if not a provider_vn, not more
# than one virtual_network_refs is allowed
if not vn_ref.get('is_provider_network') and \
len(obj_dict.get('virtual_network_refs')) != 1:
return(False,
'Non Provider VN (%s) can connect to one provider VN but '
'trying to connect to VN (%s)' % (vn_ref['uuid'], uuids))

# retrieve vn_refs of linked VNs
(ok, provider_vns, _) = db_conn.dbe_list('virtual_network',
obj_uuids=uuids,
field_names=[
'is_provider_network'],
filters={
'is_provider_network': [
True]})
if not ok:
return (ok, 'Error reading VN refs (%s)' % uuids)
if vn_ref.get('is_provider_network'):
# this is a provider-VN, no linked provider_vns is expected
if provider_vns:
return (False,
'Provider VN (%s) can not connect to another '
'provider VN (%s)' % (vn_ref.get('uuid'), uuids))
else:
# this is a non-provider VN, only one provider vn is expected
if len(provider_vns) != 1:
return (False,
'Non Provider VN (%s) can connect only to one '
'provider VN but not (%s)' % (
vn_ref.get('uuid'), uuids))
return (True, '')

@classmethod
def _check_route_targets(cls, obj_dict, db_conn):
if 'route_target_list' not in obj_dict:
Expand Down Expand Up @@ -2588,6 +2658,15 @@ def undo_vn_id():
if not ok:
return (False, (400, error))

(ok, error) = cls._check_is_provider_network_property(obj_dict,
db_conn)
if not ok:
return (False, (400, error))

(ok, error) = cls._check_provider_network(obj_dict, db_conn)
if not ok:
return (False, (400, error))

# Check if network forwarding mode support BGP VPN types
ok, result = BgpvpnServer.check_network_supports_vpn_type(
db_conn, obj_dict)
Expand Down Expand Up @@ -2653,9 +2732,7 @@ def post_dbe_create(cls, tenant_name, obj_dict, db_conn):

@classmethod
def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs):
if ((fq_name == cfgm_common.IP_FABRIC_VN_FQ_NAME) or
(fq_name == cfgm_common.LINK_LOCAL_VN_FQ_NAME)):
# Ignore ip-fabric subnet updates
if ((fq_name == cfgm_common.LINK_LOCAL_VN_FQ_NAME)):
return True, ""

# neutron <-> vnc sharing
Expand Down Expand Up @@ -2697,6 +2774,16 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs):
new_vn_id != read_result.get('virtual_network_network_id')):
return (False, (403, "Cannot update the virtual network ID"))

(ok, error) = cls._check_is_provider_network_property(obj_dict,
db_conn, vn_ref=read_result)
if not ok:
return (False, (400, error))

(ok, error) = cls._check_provider_network(obj_dict,
db_conn, vn_ref=read_result)
if not ok:
return (False, (400, error))

(ok, response) = cls._is_multi_policy_service_chain_supported(obj_dict,
read_result)
if not ok:
Expand Down
14 changes: 10 additions & 4 deletions src/config/api-server/vnc_db.py
Expand Up @@ -1046,18 +1046,24 @@ def _dbe_resync(self, obj_type, obj_uuids):
obj_uuid,
'logical_router',
router['uuid'])
do_update = False
if 'network_ipam_refs' in obj_dict:
ipam_refs = obj_dict['network_ipam_refs']
do_update = False
for ipam in ipam_refs:
vnsn = ipam['attr']
ipam_subnets = vnsn['ipam_subnets']
if (self.update_subnet_uuid(ipam_subnets)):
if not do_update:
do_update = True
if do_update:
self.cassandra_db.object_update(
'virtual_network', obj_uuid, obj_dict)
# set is_provider_network property as True
# for ip-fabric network
if obj_dict['fq_name'][-1] == 'ip-fabric' and \
not obj_dict.get('is_provider_network', False):
do_update = True
obj_dict['is_provider_network'] = True
if do_update:
self._object_db.object_update(
'virtual_network', obj_uuid, obj_dict)

elif obj_type == 'virtual_machine_interface':
device_owner = obj_dict.get('virtual_machine_interface_device_owner')
Expand Down
28 changes: 28 additions & 0 deletions src/config/schema-transformer/config_db.py
Expand Up @@ -1337,6 +1337,34 @@ def evaluate(self):
acl_list.append(acl)
# end for rule

# Add provider-network to any vn deny
if self.obj.get_is_provider_network():
provider_to_any_acl = self.add_acl_rule(
AddressType(virtual_network=self.name),
PortType(),
AddressType(virtual_network="any"),
PortType(),
"any",
RULE_IMPLICIT_DENY_UUID,
ActionListType("deny"),
'<>')
acl_list.append(provider_to_any_acl)
else:
linked_vns = self.obj.get_virtual_network_refs() or []
for linked_vn in linked_vns:
provider_vn = ':'.join(linked_vn['to'])
# add this vn to provider-network deny
this_vn_to_provider_acl = self.add_acl_rule(
AddressType(virtual_network=self.name),
PortType(),
AddressType(virtual_network=provider_vn),
PortType(),
"any",
RULE_IMPLICIT_DENY_UUID,
ActionListType("deny"),
'<>')
acl_list.append(this_vn_to_provider_acl)

# Create any-vn to any-vn allow
match = MatchConditionType(
"any", AddressType(virtual_network="any"), PortType(),
Expand Down
6 changes: 5 additions & 1 deletion src/config/schema-transformer/test/test_case.py
Expand Up @@ -121,7 +121,11 @@ def frame_rule_addresses(self, addr):
for addr in addrs:
if addr["type"] == "vn":
vn = addr["value"]
rule_kwargs.update({'virtual_network' : vn.get_fq_name_str()})
if isinstance(vn, basestring):
rule_kwargs.update({'virtual_network': vn})
else:
rule_kwargs.update(
{'virtual_network': vn.get_fq_name_str()})
elif addr["type"] == "cidr_list":
subnets = []
for cidr in addr["value"]:
Expand Down

0 comments on commit f65e6c0

Please sign in to comment.