From 8a5611f9b2fa632ccfcd04523ee42f69b223ea6e Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 2 Sep 2011 13:44:10 +0200 Subject: Fix protocol-less security groups. --- nova/tests/test_libvirt.py | 11 +++++++++++ nova/virt/libvirt/firewall.py | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 8c6775b29..f0aa2a918 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1033,6 +1033,13 @@ class IptablesFirewallTestCase(test.TestCase): 'to_port': 81, 'group_id': src_secgroup['id']}) + db.security_group_rule_create(admin_ctxt, + {'parent_group_id': secgroup['id'], + 'group_id': src_secgroup['id']}) + + db.instance_add_security_group(admin_ctxt, instance_ref['id'], + secgroup['id']) + db.instance_add_security_group(admin_ctxt, instance_ref['id'], secgroup['id']) db.instance_add_security_group(admin_ctxt, src_instance_ref['id'], @@ -1106,6 +1113,10 @@ class IptablesFirewallTestCase(test.TestCase): self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, "TCP port 80/81 acceptance rule wasn't added") + regex = re.compile('-A .* -j ACCEPT -s %s' % (src_ip,)) + self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, + "TCP port 80/81 acceptance rule wasn't added") + regex = re.compile('-A .* -j ACCEPT -p tcp ' '-m multiport --dports 80:81 -s 192.168.10.0/24') self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, diff --git a/nova/virt/libvirt/firewall.py b/nova/virt/libvirt/firewall.py index c2f4f91e8..dfa1deba7 100644 --- a/nova/virt/libvirt/firewall.py +++ b/nova/virt/libvirt/firewall.py @@ -663,7 +663,9 @@ class IptablesFirewallDriver(FirewallDriver): if version == 6 and rule.protocol == 'icmp': protocol = 'icmpv6' - args = ['-j ACCEPT', '-p', protocol] + args = ['-j ACCEPT'] + if protocol: + args += ['-p', protocol] if protocol in ['udp', 'tcp']: if rule.from_port == rule.to_port: -- cgit From 077a6971016b112fa7133f2b00aaed5d922386e1 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Sun, 4 Sep 2011 21:06:10 +0200 Subject: Accidentally added instance to security group twice in the test. Fixed. --- nova/tests/test_libvirt.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index f0aa2a918..1254c3299 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1037,9 +1037,6 @@ class IptablesFirewallTestCase(test.TestCase): {'parent_group_id': secgroup['id'], 'group_id': src_secgroup['id']}) - db.instance_add_security_group(admin_ctxt, instance_ref['id'], - secgroup['id']) - db.instance_add_security_group(admin_ctxt, instance_ref['id'], secgroup['id']) db.instance_add_security_group(admin_ctxt, src_instance_ref['id'], -- cgit From 7d923d28d673340af1e168f99e7178cd01ea3ac3 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 5 Sep 2011 09:32:14 +0200 Subject: Make a security group rule that references another security group return ipPermission for each of tcp, udp, and icmp. --- nova/api/ec2/cloud.py | 15 +++++++++++---- nova/tests/test_cloud.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index fe44191c8..14f5f69e2 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -572,18 +572,25 @@ class CloudController(object): g['ipPermissions'] = [] for rule in group.rules: r = {} - r['ipProtocol'] = rule.protocol - r['fromPort'] = rule.from_port - r['toPort'] = rule.to_port r['groups'] = [] r['ipRanges'] = [] if rule.group_id: source_group = db.security_group_get(context, rule.group_id) r['groups'] += [{'groupName': source_group.name, 'userId': source_group.project_id}] + for protocol, min_port, max_port in (('icmp', -1, -1), + ('tcp', 1, 65535), + ('udp', 1, 65536)): + r['ipProtocol'] = protocol + r['fromPort'] = min_port + r['toPort'] = max_port + g['ipPermissions'] += [dict(r)] else: + r['ipProtocol'] = rule.protocol + r['fromPort'] = rule.from_port + r['toPort'] = rule.to_port r['ipRanges'] += [{'cidrIp': rule.cidr}] - g['ipPermissions'] += [r] + g['ipPermissions'] += [r] return g def _rule_args_to_dict(self, context, kwargs): diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 3fe6a9b42..f5a99fa2c 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -305,6 +305,36 @@ class CloudTestCase(test.TestCase): 'ip_protocol': u'tcp'}]} self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + def test_describe_security_group_ingress_groups(self): + kwargs = {'project_id': self.context.project_id, 'name': 'test'} + sec = db.security_group_create(self.context, + {'project_id': 'someuser', + 'name': 'somegroup1'}) + sec = db.security_group_create(self.context, + {'project_id': 'someuser', + 'name': 'othergroup2'}) + sec = db.security_group_create(self.context, kwargs) + authz = self.cloud.authorize_security_group_ingress + kwargs = {'ip_permissions': [{ + 'groups': {'1': {'user_id': u'someuser', + 'group_name': u'somegroup1'}, + '2': {'user_id': u'someuser', + 'group_name': u'othergroup2'}}}]} + self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + describe = self.cloud.describe_security_groups + groups = describe(self.context, group_name=['test']) + self.assertEquals(len(groups['securityGroupInfo']), 1) + for proto, min_port, max_port in (('icmp', -1, -1), + ('udp', 1, 65536), + ('tcp', 1, 65535)): + rules = filter(lambda g:g['ipProtocol'] == proto, + groups['securityGroupInfo'][0]['ipPermissions']) + self.assertEquals(len(rules), 2, + "Expected 2 rules for protocol %s" % proto) + for rule in rules: + self.assertEquals(rule['fromPort'], min_port) + self.assertEquals(rule['toPort'], max_port) + def test_revoke_security_group_ingress(self): kwargs = {'project_id': self.context.project_id, 'name': 'test'} sec = db.security_group_create(self.context, kwargs) -- cgit From 21e31635e699c5a1d5c64ddda03516174567483f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 5 Sep 2011 12:05:47 +0200 Subject: Clean up security groups after use --- nova/tests/test_cloud.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index f5a99fa2c..c5bfdd0f8 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -307,20 +307,20 @@ class CloudTestCase(test.TestCase): def test_describe_security_group_ingress_groups(self): kwargs = {'project_id': self.context.project_id, 'name': 'test'} - sec = db.security_group_create(self.context, + sec1 = db.security_group_create(self.context, kwargs) + sec2 = db.security_group_create(self.context, {'project_id': 'someuser', 'name': 'somegroup1'}) - sec = db.security_group_create(self.context, + sec3 = db.security_group_create(self.context, {'project_id': 'someuser', 'name': 'othergroup2'}) - sec = db.security_group_create(self.context, kwargs) authz = self.cloud.authorize_security_group_ingress kwargs = {'ip_permissions': [{ 'groups': {'1': {'user_id': u'someuser', 'group_name': u'somegroup1'}, '2': {'user_id': u'someuser', 'group_name': u'othergroup2'}}}]} - self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + self.assertTrue(authz(self.context, group_name=sec1['name'], **kwargs)) describe = self.cloud.describe_security_groups groups = describe(self.context, group_name=['test']) self.assertEquals(len(groups['securityGroupInfo']), 1) @@ -334,6 +334,9 @@ class CloudTestCase(test.TestCase): for rule in rules: self.assertEquals(rule['fromPort'], min_port) self.assertEquals(rule['toPort'], max_port) + db.security_group_destroy(self.context, sec3['id']) + db.security_group_destroy(self.context, sec2['id']) + db.security_group_destroy(self.context, sec1['id']) def test_revoke_security_group_ingress(self): kwargs = {'project_id': self.context.project_id, 'name': 'test'} -- cgit From 95fc404a5e3588d9f40cf7236fbda129346d134d Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 5 Sep 2011 12:06:13 +0200 Subject: Adjust test_api to account to multiple rules getting returned for a single set rule. --- nova/tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index 526d1c490..e9f1145dd 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -515,7 +515,7 @@ class ApiEc2TestCase(test.TestCase): # be good enough for that. for group in rv: if group.name == security_group_name: - self.assertEquals(len(group.rules), 1) + self.assertEquals(len(group.rules), 3) self.assertEquals(len(group.rules[0].grants), 1) self.assertEquals(str(group.rules[0].grants[0]), '%s-%s' % (other_security_group_name, 'fake')) -- cgit From 63c4cc459a5b27040610ca9071ac578ecd43c059 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 15 Sep 2011 18:15:19 +0200 Subject: Return three rules for describe_security_groups if a rule refers to a foreign group, but does not specify protocol/port. --- nova/api/ec2/cloud.py | 18 +++++++++++------ nova/tests/test_cloud.py | 52 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 14f5f69e2..5c876a3b7 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -578,13 +578,19 @@ class CloudController(object): source_group = db.security_group_get(context, rule.group_id) r['groups'] += [{'groupName': source_group.name, 'userId': source_group.project_id}] - for protocol, min_port, max_port in (('icmp', -1, -1), - ('tcp', 1, 65535), - ('udp', 1, 65536)): - r['ipProtocol'] = protocol - r['fromPort'] = min_port - r['toPort'] = max_port + if rule.protocol: + r['ipProtocol'] = rule.protocol + r['fromPort'] = rule.from_port + r['toPort'] = rule.to_port g['ipPermissions'] += [dict(r)] + else: + for protocol, min_port, max_port in (('icmp', -1, -1), + ('tcp', 1, 65535), + ('udp', 1, 65536)): + r['ipProtocol'] = protocol + r['fromPort'] = min_port + r['toPort'] = max_port + g['ipPermissions'] += [dict(r)] else: r['ipProtocol'] = rule.protocol r['fromPort'] = rule.from_port diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index c5bfdd0f8..96aebdd54 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -315,25 +315,47 @@ class CloudTestCase(test.TestCase): {'project_id': 'someuser', 'name': 'othergroup2'}) authz = self.cloud.authorize_security_group_ingress - kwargs = {'ip_permissions': [{ - 'groups': {'1': {'user_id': u'someuser', - 'group_name': u'somegroup1'}, - '2': {'user_id': u'someuser', - 'group_name': u'othergroup2'}}}]} + kwargs = {'ip_permissions': [ + {'groups': {'1': {'user_id': u'someuser', + 'group_name': u'somegroup1'}}}, + {'ip_protocol': 'tcp', + 'from_port': 80, + 'to_port': 80, + 'groups': {'1': {'user_id': u'someuser', + 'group_name': u'othergroup2'}}}]} self.assertTrue(authz(self.context, group_name=sec1['name'], **kwargs)) describe = self.cloud.describe_security_groups groups = describe(self.context, group_name=['test']) self.assertEquals(len(groups['securityGroupInfo']), 1) - for proto, min_port, max_port in (('icmp', -1, -1), - ('udp', 1, 65536), - ('tcp', 1, 65535)): - rules = filter(lambda g:g['ipProtocol'] == proto, - groups['securityGroupInfo'][0]['ipPermissions']) - self.assertEquals(len(rules), 2, - "Expected 2 rules for protocol %s" % proto) - for rule in rules: - self.assertEquals(rule['fromPort'], min_port) - self.assertEquals(rule['toPort'], max_port) + actual_rules = groups['securityGroupInfo'][0]['ipPermissions'] + self.assertEquals(len(actual_rules), 4) + expected_rules = [{'fromPort': -1, + 'groups': [{'groupName': 'somegroup1', + 'userId': 'someuser'}], + 'ipProtocol': 'icmp', + 'ipRanges': [], + 'toPort': -1}, + {'fromPort': 1, + 'groups': [{'groupName': u'somegroup1', + 'userId': u'someuser'}], + 'ipProtocol': 'tcp', + 'ipRanges': [], + 'toPort': 65535}, + {'fromPort': 1, + 'groups': [{'groupName': u'somegroup1', + 'userId': u'someuser'}], + 'ipProtocol': 'udp', + 'ipRanges': [], + 'toPort': 65536}, + {'fromPort': 80, + 'groups': [{'groupName': u'othergroup2', + 'userId': u'someuser'}], + 'ipProtocol': u'tcp', + 'ipRanges': [], + 'toPort': 80}] + for rule in expected_rules: + self.assertTrue(rule in actual_rules) + db.security_group_destroy(self.context, sec3['id']) db.security_group_destroy(self.context, sec2['id']) db.security_group_destroy(self.context, sec1['id']) -- cgit From 1d2a5bd706736bff2e2d82ebeb813438493cea41 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 16 Sep 2011 14:28:57 +0200 Subject: Make sure grantee_group is eagerly loaded. --- nova/db/sqlalchemy/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index b99667afc..6c3c2d038 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2790,12 +2790,14 @@ def security_group_rule_get_by_security_group(context, security_group_id, result = session.query(models.SecurityGroupIngressRule).\ filter_by(deleted=can_read_deleted(context)).\ filter_by(parent_group_id=security_group_id).\ + options(joinedload_all('grantee_group')).\ all() else: # TODO(vish): Join to group and check for project_id result = session.query(models.SecurityGroupIngressRule).\ filter_by(deleted=False).\ filter_by(parent_group_id=security_group_id).\ + options(joinedload_all('grantee_group')).\ all() return result -- cgit From 2d3027da762cdac0c5a12adee15d1bb28fb7bf10 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 16 Sep 2011 21:27:25 +0200 Subject: Fix failing test. --- nova/tests/test_libvirt.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 769bc5291..b7c1ef1ab 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1008,10 +1008,6 @@ class IptablesFirewallTestCase(test.TestCase): 'to_port': 81, 'group_id': src_secgroup['id']}) - db.security_group_rule_create(admin_ctxt, - {'parent_group_id': secgroup['id'], - 'group_id': src_secgroup['id']}) - db.instance_add_security_group(admin_ctxt, instance_ref['id'], secgroup['id']) db.instance_add_security_group(admin_ctxt, src_instance_ref['id'], @@ -1094,10 +1090,6 @@ class IptablesFirewallTestCase(test.TestCase): self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, "TCP port 80/81 acceptance rule wasn't added") - regex = re.compile('-A .* -j ACCEPT -s %s' % (src_ip,)) - self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, - "TCP port 80/81 acceptance rule wasn't added") - regex = re.compile('-A .* -j ACCEPT -p tcp ' '-m multiport --dports 80:81 -s 192.168.10.0/24') self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, -- cgit