Add support for source security groups

This patch adds support for the SourceSecurityGroupName and
SourceSecurityGroupId properties. It covers Nova and Neutron.

Change-Id: Ic12512dfb4375ccccbe1282bb48b80cde16ceb9d
Fixes: bug #1193415
This commit is contained in:
Simon Pasquier
2013-08-14 15:00:44 +02:00
parent 093638e0c6
commit 82f7086e23
4 changed files with 352 additions and 47 deletions

View File

@@ -15,6 +15,7 @@
import collections
from heat.engine import clients
from heat.common import exception
from heat.common import template_format
from heat.engine import parser
from heat.engine import resource
@@ -55,6 +56,24 @@ Resources:
FromPort : 80
ToPort : 80
CidrIp : 0.0.0.0/0
- IpProtocol: tcp
SourceSecurityGroupName: test
- IpProtocol: icmp
SourceSecurityGroupId: 1
'''
test_template_nova_with_egress = '''
HeatTemplateFormatVersion: '2012-12-12'
Resources:
the_sg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: HTTP and SSH access
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
'''
test_template_neutron = '''
@@ -74,11 +93,14 @@ Resources:
FromPort : 80
ToPort : 80
CidrIp : 0.0.0.0/0
- IpProtocol: tcp
SourceSecurityGroupId: wwww
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.1.0/24
- SourceSecurityGroupName: xxxx
'''
def setUp(self):
@@ -142,9 +164,13 @@ Resources:
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', 22, 22, '0.0.0.0/0').AndReturn(None)
2, 'tcp', 22, 22, '0.0.0.0/0', None).AndReturn(None)
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', 80, 80, '0.0.0.0/0').AndReturn(None)
2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(None)
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', None, None, None, 1).AndReturn(None)
nova_sgr.SecurityGroupRuleManager.create(
2, 'icmp', None, None, None, 1).AndReturn(None)
# delete script
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -172,6 +198,28 @@ Resources:
'cidr': '0.0.0.0/0'
},
'id': 131
}, {
'from_port': None,
'group': {
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'name': 'test'
},
'ip_protocol': 'tcp',
'to_port': None,
'parent_group_id': 2,
'ip_range': {},
'id': 132
}, {
'from_port': None,
'group': {
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'name': 'test'
},
'ip_protocol': 'icmp',
'to_port': None,
'parent_group_id': 2,
'ip_range': {},
'id': 133
}]
))
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -179,6 +227,10 @@ Resources:
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.delete(131).AndReturn(None)
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.delete(132).AndReturn(None)
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.delete(133).AndReturn(None)
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
self.m.ReplayAll()
@@ -197,20 +249,36 @@ Resources:
#create script
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
sg_name = utils.PhysName('test_stack', 'the_sg')
nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
id=2,
name=sg_name,
description='HTTP and SSH access',
rules=[],
)])
nova_sg.SecurityGroupManager.list().AndReturn([
NovaSG(
id=2,
name=sg_name,
description='HTTP and SSH access',
rules=[],
),
NovaSG(
id=1,
name='test',
description='FAKE_SECURITY_GROUP',
rules=[],
)
])
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', 22, 22, '0.0.0.0/0').AndRaise(
2, 'tcp', 22, 22, '0.0.0.0/0', None).AndRaise(
clients.novaclient.exceptions.BadRequest(
400, 'Rule already exists'))
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', 80, 80, '0.0.0.0/0').AndReturn(
2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(
clients.novaclient.exceptions.BadRequest(
400, 'Rule already exists'))
nova_sgr.SecurityGroupRuleManager.create(
2, 'tcp', None, None, None, 1).AndReturn(
clients.novaclient.exceptions.BadRequest(
400, 'Rule already exists'))
nova_sgr.SecurityGroupRuleManager.create(
2, 'icmp', None, None, None, 1).AndReturn(
clients.novaclient.exceptions.BadRequest(
400, 'Rule already exists'))
@@ -240,6 +308,28 @@ Resources:
'cidr': '0.0.0.0/0'
},
'id': 131
}, {
'from_port': None,
'group': {
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'name': 'test'
},
'ip_protocol': 'tcp',
'to_port': None,
'parent_group_id': 2,
'ip_range': {},
'id': 132
}, {
'from_port': None,
'group': {
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'name': 'test'
},
'ip_protocol': 'icmp',
'to_port': None,
'parent_group_id': 2,
'ip_range': {},
'id': 133
}]
))
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -249,6 +339,12 @@ Resources:
nova_sgr.SecurityGroupRuleManager.delete(131).AndRaise(
clients.novaclient.exceptions.NotFound('goneburger'))
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.delete(132).AndRaise(
clients.novaclient.exceptions.NotFound('goneburger'))
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sgr.SecurityGroupRuleManager.delete(133).AndRaise(
clients.novaclient.exceptions.NotFound('goneburger'))
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -271,6 +367,13 @@ Resources:
self.m.VerifyAll()
def test_security_group_nova_with_egress_rules(self):
t = template_format.parse(self.test_template_nova_with_egress)
stack = self.parse_stack(t)
sg = stack['the_sg']
self.assertRaises(exception.EgressRuleNotAllowed, sg.validate)
@utils.stack_delete_after
def test_security_group_neutron(self):
#create script
@@ -287,7 +390,29 @@ Resources:
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'name': sg_name,
'description': 'HTTP and SSH access',
'security_group_rules': [],
'security_group_rules': [{
"direction": "egress",
"ethertype": "IPv4",
"id": "aaaa-1",
"port_range_max": None,
"port_range_min": None,
"protocol": None,
"remote_group_id": None,
"remote_ip_prefix": None,
"security_group_id": "aaaa",
"tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
}, {
"direction": "egress",
"ethertype": "IPv6",
"id": "aaaa-2",
"port_range_max": None,
"port_range_min": None,
"protocol": None,
"remote_group_id": None,
"remote_ip_prefix": None,
"security_group_id": "aaaa",
"tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
}],
'id': 'aaaa'
}
})
@@ -295,6 +420,7 @@ Resources:
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 22,
'ethertype': 'IPv4',
@@ -305,6 +431,7 @@ Resources:
}).AndReturn({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 22,
'ethertype': 'IPv4',
@@ -317,6 +444,7 @@ Resources:
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 80,
'ethertype': 'IPv4',
@@ -327,6 +455,7 @@ Resources:
}).AndReturn({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 80,
'ethertype': 'IPv4',
@@ -336,9 +465,38 @@ Resources:
'id': 'cccc'
}
})
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': 'wwww',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': 'tcp',
'security_group_id': 'aaaa'
}
}).AndReturn({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': 'wwww',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': 'tcp',
'security_group_id': 'aaaa',
'id': 'dddd'
}
})
neutronclient.Client.delete_security_group_rule('aaaa-1').AndReturn(
None)
neutronclient.Client.delete_security_group_rule('aaaa-2').AndReturn(
None)
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': None,
'remote_ip_prefix': '10.0.1.0/24',
'port_range_min': 22,
'ethertype': 'IPv4',
@@ -349,13 +507,38 @@ Resources:
}).AndReturn({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': None,
'remote_ip_prefix': '10.0.1.0/24',
'port_range_min': 22,
'ethertype': 'IPv4',
'port_range_max': 22,
'protocol': 'tcp',
'security_group_id': 'aaaa',
'id': 'dddd'
'id': 'eeee'
}
})
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': 'xxxx',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': None,
'security_group_id': 'aaaa'
}
}).AndReturn({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': 'xxxx',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': None,
'security_group_id': 'aaaa',
'id': 'ffff'
}
})
@@ -372,6 +555,7 @@ Resources:
'id': 'bbbb',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 22
@@ -382,24 +566,50 @@ Resources:
'id': 'cccc',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 80
}, {
'direction': 'egress',
'direction': 'ingress',
'protocol': 'tcp',
'port_range_max': 22,
'port_range_max': None,
'id': 'dddd',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': 'wwww',
'remote_ip_prefix': None,
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': None
}, {
'direction': 'egress',
'protocol': 'tcp',
'port_range_max': 22,
'id': 'eeee',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '10.0.1.0/24',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 22
}, {
'direction': 'egress',
'protocol': None,
'port_range_max': None,
'id': 'ffff',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': None,
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': None
}],
'id': 'aaaa'}})
neutronclient.Client.delete_security_group_rule('bbbb').AndReturn(None)
neutronclient.Client.delete_security_group_rule('cccc').AndReturn(None)
neutronclient.Client.delete_security_group_rule('dddd').AndReturn(None)
neutronclient.Client.delete_security_group_rule('eeee').AndReturn(None)
neutronclient.Client.delete_security_group_rule('ffff').AndReturn(None)
neutronclient.Client.delete_security_group('aaaa').AndReturn(None)
self.m.ReplayAll()
@@ -437,6 +647,7 @@ Resources:
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 22,
'ethertype': 'IPv4',
@@ -449,6 +660,7 @@ Resources:
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'port_range_min': 80,
'ethertype': 'IPv4',
@@ -458,9 +670,23 @@ Resources:
}
}).AndRaise(
NeutronClientException(status_code=409))
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'remote_group_id': 'wwww',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': 'tcp',
'security_group_id': 'aaaa'
}
}).AndRaise(
NeutronClientException(status_code=409))
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': None,
'remote_ip_prefix': '10.0.1.0/24',
'port_range_min': 22,
'ethertype': 'IPv4',
@@ -470,6 +696,19 @@ Resources:
}
}).AndRaise(
NeutronClientException(status_code=409))
neutronclient.Client.create_security_group_rule({
'security_group_rule': {
'direction': 'egress',
'remote_group_id': 'xxxx',
'remote_ip_prefix': None,
'port_range_min': None,
'ethertype': 'IPv4',
'port_range_max': None,
'protocol': None,
'security_group_id': 'aaaa'
}
}).AndRaise(
NeutronClientException(status_code=409))
# delete script
neutronclient.Client.show_security_group('aaaa').AndReturn({
@@ -484,6 +723,7 @@ Resources:
'id': 'bbbb',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 22
@@ -494,19 +734,43 @@ Resources:
'id': 'cccc',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 80
}, {
'direction': 'egress',
'direction': 'ingress',
'protocol': 'tcp',
'port_range_max': 22,
'port_range_max': None,
'id': 'dddd',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': 'wwww',
'remote_ip_prefix': None,
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': None
}, {
'direction': 'egress',
'protocol': 'tcp',
'port_range_max': 22,
'id': 'eeee',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': '10.0.1.0/24',
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': 22
}, {
'direction': 'egress',
'protocol': None,
'port_range_max': None,
'id': 'ffff',
'ethertype': 'IPv4',
'security_group_id': 'aaaa',
'remote_group_id': None,
'remote_ip_prefix': None,
'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
'port_range_min': None
}],
'id': 'aaaa'}})
neutronclient.Client.delete_security_group_rule('bbbb').AndRaise(
@@ -515,6 +779,10 @@ Resources:
NeutronClientException(status_code=404))
neutronclient.Client.delete_security_group_rule('dddd').AndRaise(
NeutronClientException(status_code=404))
neutronclient.Client.delete_security_group_rule('eeee').AndRaise(
NeutronClientException(status_code=404))
neutronclient.Client.delete_security_group_rule('ffff').AndRaise(
NeutronClientException(status_code=404))
neutronclient.Client.delete_security_group('aaaa').AndRaise(
NeutronClientException(status_code=404))