Merge "Add popular IP protocols for security group"
This commit is contained in:
commit
eee37a86a5
@ -138,7 +138,7 @@ def icmpv6_header_match_supported():
|
||||
table=ovs_const.ARP_SPOOF_TABLE,
|
||||
priority=1,
|
||||
dl_type=n_consts.ETHERTYPE_IPV6,
|
||||
nw_proto=n_consts.PROTO_NUM_ICMP_V6,
|
||||
nw_proto=n_consts.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=n_consts.ICMPV6_TYPE_NA,
|
||||
nd_target='fdf8:f53b:82e4::10',
|
||||
actions="NORMAL")
|
||||
|
@ -125,14 +125,71 @@ SUBNET_ALLOCATION_EXT_ALIAS = 'subnet_allocation'
|
||||
ETHERTYPE_IPV6 = 0x86DD
|
||||
|
||||
# Protocol names and numbers for Security Groups/Firewalls
|
||||
PROTO_NAME_TCP = 'tcp'
|
||||
PROTO_NAME_AH = 'ah'
|
||||
PROTO_NAME_DCCP = 'dccp'
|
||||
PROTO_NAME_EGP = 'egp'
|
||||
PROTO_NAME_ESP = 'esp'
|
||||
PROTO_NAME_GRE = 'gre'
|
||||
PROTO_NAME_ICMP = 'icmp'
|
||||
PROTO_NAME_ICMP_V6 = 'icmpv6'
|
||||
PROTO_NAME_IGMP = 'igmp'
|
||||
PROTO_NAME_IPV6_ENCAP = 'ipv6-encap'
|
||||
PROTO_NAME_IPV6_FRAG = 'ipv6-frag'
|
||||
PROTO_NAME_IPV6_ICMP = 'ipv6-icmp'
|
||||
PROTO_NAME_IPV6_NONXT = 'ipv6-nonxt'
|
||||
PROTO_NAME_IPV6_OPTS = 'ipv6-opts'
|
||||
PROTO_NAME_IPV6_ROUTE = 'ipv6-route'
|
||||
PROTO_NAME_OSPF = 'ospf'
|
||||
PROTO_NAME_PGM = 'pgm'
|
||||
PROTO_NAME_RSVP = 'rsvp'
|
||||
PROTO_NAME_SCTP = 'sctp'
|
||||
PROTO_NAME_TCP = 'tcp'
|
||||
PROTO_NAME_UDP = 'udp'
|
||||
PROTO_NUM_TCP = 6
|
||||
PROTO_NAME_UDPLITE = 'udplite'
|
||||
PROTO_NAME_VRRP = 'vrrp'
|
||||
|
||||
PROTO_NUM_AH = 51
|
||||
PROTO_NUM_DCCP = 33
|
||||
PROTO_NUM_EGP = 8
|
||||
PROTO_NUM_ESP = 50
|
||||
PROTO_NUM_GRE = 47
|
||||
PROTO_NUM_ICMP = 1
|
||||
PROTO_NUM_ICMP_V6 = 58
|
||||
PROTO_NUM_IGMP = 2
|
||||
PROTO_NUM_IPV6_ENCAP = 41
|
||||
PROTO_NUM_IPV6_FRAG = 44
|
||||
PROTO_NUM_IPV6_ICMP = 58
|
||||
PROTO_NUM_IPV6_NONXT = 59
|
||||
PROTO_NUM_IPV6_OPTS = 60
|
||||
PROTO_NUM_IPV6_ROUTE = 43
|
||||
PROTO_NUM_OSPF = 89
|
||||
PROTO_NUM_PGM = 113
|
||||
PROTO_NUM_RSVP = 46
|
||||
PROTO_NUM_SCTP = 132
|
||||
PROTO_NUM_TCP = 6
|
||||
PROTO_NUM_UDP = 17
|
||||
PROTO_NUM_UDPLITE = 136
|
||||
PROTO_NUM_VRRP = 112
|
||||
|
||||
IP_PROTOCOL_MAP = {PROTO_NAME_AH: PROTO_NUM_AH,
|
||||
PROTO_NAME_DCCP: PROTO_NUM_DCCP,
|
||||
PROTO_NAME_EGP: PROTO_NUM_EGP,
|
||||
PROTO_NAME_ESP: PROTO_NUM_ESP,
|
||||
PROTO_NAME_GRE: PROTO_NUM_GRE,
|
||||
PROTO_NAME_ICMP: PROTO_NUM_ICMP,
|
||||
PROTO_NAME_IGMP: PROTO_NUM_IGMP,
|
||||
PROTO_NAME_IPV6_ENCAP: PROTO_NUM_IPV6_ENCAP,
|
||||
PROTO_NAME_IPV6_FRAG: PROTO_NUM_IPV6_FRAG,
|
||||
PROTO_NAME_IPV6_ICMP: PROTO_NUM_IPV6_ICMP,
|
||||
PROTO_NAME_IPV6_NONXT: PROTO_NUM_IPV6_NONXT,
|
||||
PROTO_NAME_IPV6_OPTS: PROTO_NUM_IPV6_OPTS,
|
||||
PROTO_NAME_IPV6_ROUTE: PROTO_NUM_IPV6_ROUTE,
|
||||
PROTO_NAME_OSPF: PROTO_NUM_OSPF,
|
||||
PROTO_NAME_PGM: PROTO_NUM_PGM,
|
||||
PROTO_NAME_RSVP: PROTO_NUM_RSVP,
|
||||
PROTO_NAME_SCTP: PROTO_NUM_SCTP,
|
||||
PROTO_NAME_TCP: PROTO_NUM_TCP,
|
||||
PROTO_NAME_UDP: PROTO_NUM_UDP,
|
||||
PROTO_NAME_UDPLITE: PROTO_NUM_UDPLITE,
|
||||
PROTO_NAME_VRRP: PROTO_NUM_VRRP}
|
||||
|
||||
# List of ICMPv6 types that should be allowed by default:
|
||||
# Multicast Listener Query (130),
|
||||
|
@ -38,11 +38,6 @@ from neutron.extensions import securitygroup as ext_sg
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
IP_PROTOCOL_MAP = {constants.PROTO_NAME_TCP: constants.PROTO_NUM_TCP,
|
||||
constants.PROTO_NAME_UDP: constants.PROTO_NUM_UDP,
|
||||
constants.PROTO_NAME_ICMP: constants.PROTO_NUM_ICMP,
|
||||
constants.PROTO_NAME_ICMP_V6: constants.PROTO_NUM_ICMP_V6}
|
||||
|
||||
|
||||
class SecurityGroup(model_base.HasStandardAttributes, model_base.BASEV2,
|
||||
model_base.HasId, model_base.HasTenant):
|
||||
@ -420,7 +415,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
||||
# problems with comparing int and string in PostgreSQL. Here this
|
||||
# string is converted to int to give an opportunity to use it as
|
||||
# before.
|
||||
return int(IP_PROTOCOL_MAP.get(protocol, protocol))
|
||||
return int(constants.IP_PROTOCOL_MAP.get(protocol, protocol))
|
||||
|
||||
def _validate_port_range(self, rule):
|
||||
"""Check that port_range is valid."""
|
||||
@ -452,7 +447,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
||||
|
||||
def _validate_ethertype_and_protocol(self, rule):
|
||||
"""Check if given ethertype and protocol are valid or not"""
|
||||
if rule['protocol'] == constants.PROTO_NAME_ICMP_V6:
|
||||
if rule['protocol'] in [constants.PROTO_NAME_IPV6_ENCAP,
|
||||
constants.PROTO_NAME_IPV6_FRAG,
|
||||
constants.PROTO_NAME_IPV6_ICMP,
|
||||
constants.PROTO_NAME_IPV6_NONXT,
|
||||
constants.PROTO_NAME_IPV6_OPTS,
|
||||
constants.PROTO_NAME_IPV6_ROUTE]:
|
||||
if rule['ethertype'] == constants.IPv4:
|
||||
raise ext_sg.SecurityGroupEthertypeConflictWithProtocol(
|
||||
ethertype=rule['ethertype'], protocol=rule['protocol'])
|
||||
|
@ -432,7 +432,7 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
|
||||
for ra_ip in ra_ips:
|
||||
ra_rule = {'direction': 'ingress',
|
||||
'ethertype': n_const.IPv6,
|
||||
'protocol': n_const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': n_const.PROTO_NAME_IPV6_ICMP,
|
||||
'source_ip_prefix': ra_ip,
|
||||
'source_port_range_min': n_const.ICMPV6_TYPE_RA}
|
||||
port['security_group_rules'].append(ra_rule)
|
||||
|
@ -211,8 +211,7 @@ def _validate_name_not_default(data, valid_values=None):
|
||||
|
||||
attr.validators['type:name_not_default'] = _validate_name_not_default
|
||||
|
||||
sg_supported_protocols = [None, const.PROTO_NAME_TCP, const.PROTO_NAME_UDP,
|
||||
const.PROTO_NAME_ICMP, const.PROTO_NAME_ICMP_V6]
|
||||
sg_supported_protocols = [None] + list(const.IP_PROTOCOL_MAP.keys())
|
||||
sg_supported_ethertypes = ['IPv4', 'IPv6']
|
||||
|
||||
# Attribute Map
|
||||
|
@ -116,14 +116,15 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||
for ip in ip_addresses:
|
||||
self.install_normal(
|
||||
table_id=constants.ARP_SPOOF_TABLE, priority=2,
|
||||
dl_type=const.ETHERTYPE_IPV6, nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
dl_type=const.ETHERTYPE_IPV6,
|
||||
nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=const.ICMPV6_TYPE_NA, nd_target=ip, in_port=port)
|
||||
|
||||
# Now that the rules are ready, direct icmpv6 neighbor advertisement
|
||||
# traffic from the port into the anti-spoof table.
|
||||
self.add_flow(table=constants.LOCAL_SWITCHING,
|
||||
priority=10, dl_type=const.ETHERTYPE_IPV6,
|
||||
nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=const.ICMPV6_TYPE_NA, in_port=port,
|
||||
actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE))
|
||||
|
||||
@ -147,7 +148,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||
self.delete_flows(table_id=constants.LOCAL_SWITCHING,
|
||||
in_port=port, proto='arp')
|
||||
self.delete_flows(table_id=constants.LOCAL_SWITCHING,
|
||||
in_port=port, nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
in_port=port, nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=const.ICMPV6_TYPE_NA)
|
||||
self.delete_arp_spoofing_allow_rules(port)
|
||||
|
||||
|
@ -612,7 +612,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'port_range_min': 23,
|
||||
'source_ip_prefix': fake_prefix},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -727,7 +727,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -801,7 +801,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -870,7 +870,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -926,7 +926,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -1032,7 +1032,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'port_range_min': 23,
|
||||
'dest_ip_prefix': fake_prefix},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
@ -1097,7 +1097,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
'remote_group_id': sg2_id,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_ICMP_V6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
|
@ -16,6 +16,7 @@ import testtools
|
||||
|
||||
from neutron.callbacks import exceptions
|
||||
from neutron.callbacks import registry
|
||||
from neutron.common import constants
|
||||
from neutron import context
|
||||
from neutron.db import common_db_mixin
|
||||
from neutron.db import securitygroups_db
|
||||
@ -83,3 +84,22 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
|
||||
with testtools.ExpectedException(
|
||||
securitygroup.SecurityGroupRuleNotFound):
|
||||
self.mixin.delete_security_group_rule(self.ctx, 'foo_rule')
|
||||
|
||||
def test_validate_ethertype_and_protocol(self):
|
||||
fake_ipv4_rules = [{'protocol': constants.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': constants.IPv4},
|
||||
{'protocol': constants.PROTO_NAME_IPV6_ENCAP,
|
||||
'ethertype': constants.IPv4},
|
||||
{'protocol': constants.PROTO_NAME_IPV6_ROUTE,
|
||||
'ethertype': constants.IPv4},
|
||||
{'protocol': constants.PROTO_NAME_IPV6_FRAG,
|
||||
'ethertype': constants.IPv4},
|
||||
{'protocol': constants.PROTO_NAME_IPV6_NONXT,
|
||||
'ethertype': constants.IPv4},
|
||||
{'protocol': constants.PROTO_NAME_IPV6_OPTS,
|
||||
'ethertype': constants.IPv4}]
|
||||
# test wrong protocols
|
||||
for rule in fake_ipv4_rules:
|
||||
with testtools.ExpectedException(
|
||||
securitygroup.SecurityGroupEthertypeConflictWithProtocol):
|
||||
self.mixin._validate_ethertype_and_protocol(rule)
|
||||
|
@ -427,7 +427,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||
with self.security_group(name, description) as sg:
|
||||
security_group_id = sg['security_group']['id']
|
||||
rule = self._build_security_group_rule(
|
||||
security_group_id, 'ingress', const.PROTO_NAME_ICMP_V6)
|
||||
security_group_id, 'ingress', const.PROTO_NAME_IPV6_ICMP)
|
||||
res = self._create_security_group_rule(self.fmt, rule)
|
||||
self.deserialize(self.fmt, res)
|
||||
self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
|
||||
@ -813,7 +813,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||
direction = "ingress"
|
||||
ethertype = const.IPv6
|
||||
remote_ip_prefix = "2001::f401:56ff:fefe:d3dc/128"
|
||||
protocol = const.PROTO_NAME_ICMP_V6
|
||||
protocol = const.PROTO_NAME_IPV6_ICMP
|
||||
# ICMPV6 type
|
||||
port_range_min = const.ICMPV6_TYPE_RA
|
||||
# ICMPV6 code
|
||||
@ -1348,7 +1348,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||
with self.security_group() as sg:
|
||||
rule = {'security_group_id': sg['security_group']['id'],
|
||||
'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'ethertype': const.IPv4,
|
||||
'tenant_id': 'test-tenant'}
|
||||
|
||||
res = self._create_security_group_rule(
|
||||
@ -1363,11 +1363,11 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||
with self.security_group() as sg:
|
||||
rule_v4 = {'security_group_id': sg['security_group']['id'],
|
||||
'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'ethertype': const.IPv4,
|
||||
'tenant_id': 'test-tenant'}
|
||||
rule_v6 = {'security_group_id': sg['security_group']['id'],
|
||||
'direction': 'ingress',
|
||||
'ethertype': 'IPv6',
|
||||
'ethertype': const.IPv6,
|
||||
'tenant_id': 'test-tenant'}
|
||||
|
||||
rules = {'security_group_rules': [rule_v4, rule_v6]}
|
||||
|
@ -194,17 +194,17 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||
expected = [
|
||||
call.add_flow(dl_type=const.ETHERTYPE_IPV6, actions='normal',
|
||||
icmp_type=const.ICMPV6_TYPE_NA,
|
||||
nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
nd_target='2001:db8::1',
|
||||
priority=2, table=24, in_port=8888),
|
||||
call.add_flow(dl_type=const.ETHERTYPE_IPV6, actions='normal',
|
||||
icmp_type=const.ICMPV6_TYPE_NA,
|
||||
nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
nd_target='fdf8:f53b:82e4::1/128',
|
||||
priority=2, table=24, in_port=8888),
|
||||
call.add_flow(dl_type=const.ETHERTYPE_IPV6,
|
||||
icmp_type=const.ICMPV6_TYPE_NA,
|
||||
nw_proto=const.PROTO_NUM_ICMP_V6,
|
||||
nw_proto=const.PROTO_NUM_IPV6_ICMP,
|
||||
priority=10, table=0, in_port=8888,
|
||||
actions='resubmit(,24)')
|
||||
]
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
prelude: >
|
||||
Add popular IP protocols to the security group code. End-users can
|
||||
specify protocol names instead of protocol numbers in both RESTful
|
||||
API and python-neutronclient CLI.
|
||||
upgrade:
|
||||
- Add popular IP protocols to security group code.
|
Loading…
Reference in New Issue
Block a user