PageRenderTime 26ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/heat/tests/aws/test_security_group.py

https://gitlab.com/syjulian/poc-heat-mversion
Python | 1144 lines | 1125 code | 7 blank | 12 comment | 11 complexity | 7e483a66e0aa0064619dca739931885e MD5 | raw file
  1. #
  2. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  3. # not use this file except in compliance with the License. You may obtain
  4. # a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  10. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  11. # License for the specific language governing permissions and limitations
  12. # under the License.
  13. import collections
  14. import copy
  15. import mock
  16. from neutronclient.common import exceptions as neutron_exc
  17. from neutronclient.v2_0 import client as neutronclient
  18. from novaclient.v2 import security_group_rules as nova_sgr
  19. from novaclient.v2 import security_groups as nova_sg
  20. from heat.common import exception
  21. from heat.common import short_id
  22. from heat.common import template_format
  23. from heat.engine.clients.os import nova
  24. from heat.engine import resource
  25. from heat.engine.resources.aws.ec2 import security_group
  26. from heat.engine import rsrc_defn
  27. from heat.engine import scheduler
  28. from heat.engine import stack as parser
  29. from heat.engine import template
  30. from heat.tests import common
  31. from heat.tests.openstack.nova import fakes as fakes_nova
  32. from heat.tests import utils
  33. NovaSG = collections.namedtuple('NovaSG',
  34. ' '.join([
  35. 'name',
  36. 'id',
  37. 'rules',
  38. 'description',
  39. ]))
  40. class SecurityGroupTest(common.HeatTestCase):
  41. test_template_nova = '''
  42. HeatTemplateFormatVersion: '2012-12-12'
  43. Resources:
  44. the_sg:
  45. Type: AWS::EC2::SecurityGroup
  46. Properties:
  47. GroupDescription: HTTP and SSH access
  48. SecurityGroupIngress:
  49. - IpProtocol: tcp
  50. FromPort: "22"
  51. ToPort: "22"
  52. CidrIp: 0.0.0.0/0
  53. - IpProtocol: tcp
  54. FromPort : "80"
  55. ToPort : "80"
  56. CidrIp : 0.0.0.0/0
  57. - IpProtocol: tcp
  58. SourceSecurityGroupName: test
  59. - IpProtocol: icmp
  60. SourceSecurityGroupId: "1"
  61. '''
  62. test_template_nova_bad_source_group = '''
  63. HeatTemplateFormatVersion: '2012-12-12'
  64. Resources:
  65. the_sg:
  66. Type: AWS::EC2::SecurityGroup
  67. Properties:
  68. GroupDescription: HTTP and SSH access
  69. SecurityGroupIngress:
  70. - IpProtocol: tcp
  71. FromPort: "22"
  72. ToPort: "22"
  73. CidrIp: 0.0.0.0/0
  74. - IpProtocol: tcp
  75. FromPort : "80"
  76. ToPort : "80"
  77. CidrIp : 0.0.0.0/0
  78. - IpProtocol: tcp
  79. SourceSecurityGroupName: thisdoesnotexist
  80. - IpProtocol: icmp
  81. SourceSecurityGroupId: "1"
  82. '''
  83. test_template_nova_with_egress = '''
  84. HeatTemplateFormatVersion: '2012-12-12'
  85. Resources:
  86. the_sg:
  87. Type: AWS::EC2::SecurityGroup
  88. Properties:
  89. GroupDescription: HTTP and SSH access
  90. SecurityGroupEgress:
  91. - IpProtocol: tcp
  92. FromPort: "22"
  93. ToPort: "22"
  94. CidrIp: 0.0.0.0/0
  95. '''
  96. test_template_neutron = '''
  97. HeatTemplateFormatVersion: '2012-12-12'
  98. Resources:
  99. the_sg:
  100. Type: AWS::EC2::SecurityGroup
  101. Properties:
  102. GroupDescription: HTTP and SSH access
  103. VpcId: aaaa
  104. SecurityGroupIngress:
  105. - IpProtocol: tcp
  106. FromPort: "22"
  107. ToPort: "22"
  108. CidrIp: 0.0.0.0/0
  109. - IpProtocol: tcp
  110. FromPort : "80"
  111. ToPort : "80"
  112. CidrIp : 0.0.0.0/0
  113. - IpProtocol: tcp
  114. SourceSecurityGroupId: wwww
  115. SecurityGroupEgress:
  116. - IpProtocol: tcp
  117. FromPort: "22"
  118. ToPort: "22"
  119. CidrIp: 10.0.1.0/24
  120. - SourceSecurityGroupName: xxxx
  121. '''
  122. def setUp(self):
  123. super(SecurityGroupTest, self).setUp()
  124. self.fc = fakes_nova.FakeClient()
  125. self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
  126. self.m.StubOutWithMock(nova_sgr.SecurityGroupRuleManager, 'create')
  127. self.m.StubOutWithMock(nova_sgr.SecurityGroupRuleManager, 'delete')
  128. self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'create')
  129. self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'delete')
  130. self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'get')
  131. self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'list')
  132. self.m.StubOutWithMock(nova_sg.SecurityGroupManager, 'update')
  133. self.m.StubOutWithMock(neutronclient.Client, 'create_security_group')
  134. self.m.StubOutWithMock(
  135. neutronclient.Client, 'create_security_group_rule')
  136. self.m.StubOutWithMock(neutronclient.Client, 'show_security_group')
  137. self.m.StubOutWithMock(
  138. neutronclient.Client, 'delete_security_group_rule')
  139. self.m.StubOutWithMock(neutronclient.Client, 'delete_security_group')
  140. self.m.StubOutWithMock(neutronclient.Client, 'update_security_group')
  141. self.patchobject(resource.Resource, 'is_using_neutron',
  142. return_value=True)
  143. def mock_no_neutron(self):
  144. self.patchobject(resource.Resource, 'is_using_neutron',
  145. return_value=False)
  146. def create_stack(self, templ):
  147. self.stack = self.parse_stack(template_format.parse(templ))
  148. self.assertIsNone(self.stack.create())
  149. return self.stack
  150. def parse_stack(self, t):
  151. stack_name = 'test_stack'
  152. tmpl = template.Template(t)
  153. stack = parser.Stack(utils.dummy_context(), stack_name, tmpl)
  154. stack.store()
  155. return stack
  156. def assertResourceState(self, rsrc, ref_id, metadata=None):
  157. metadata = metadata or {}
  158. self.assertIsNone(rsrc.validate())
  159. self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
  160. self.assertEqual(ref_id, rsrc.FnGetRefId())
  161. self.assertEqual(metadata, dict(rsrc.metadata_get()))
  162. def stubout_nova_create_security_group(self):
  163. # create script
  164. self.mock_no_neutron()
  165. nova.NovaClientPlugin._create().AndReturn(self.fc)
  166. nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
  167. id=1,
  168. name='test',
  169. description='FAKE_SECURITY_GROUP',
  170. rules=[],
  171. )])
  172. nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
  173. id=1,
  174. name='test',
  175. description='FAKE_SECURITY_GROUP',
  176. rules=[],
  177. )])
  178. sg_name = utils.PhysName('test_stack', 'the_sg')
  179. nova_sg.SecurityGroupManager.create(
  180. sg_name,
  181. 'HTTP and SSH access').AndReturn(NovaSG(
  182. id=2,
  183. name=sg_name,
  184. description='HTTP and SSH access',
  185. rules=[]))
  186. nova_sgr.SecurityGroupRuleManager.create(
  187. 2, 'tcp', 22, 22, '0.0.0.0/0', None).AndReturn(None)
  188. nova_sgr.SecurityGroupRuleManager.create(
  189. 2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(None)
  190. nova_sgr.SecurityGroupRuleManager.create(
  191. 2, 'tcp', None, None, None, 1).AndReturn(None)
  192. nova_sgr.SecurityGroupRuleManager.create(
  193. 2, 'icmp', None, None, None, '1').AndReturn(None)
  194. return sg_name
  195. def stubout_nova_get_security_group(self, sg_name):
  196. nova_sg.SecurityGroupManager.get(2).AndReturn(NovaSG(
  197. id=2,
  198. name=sg_name,
  199. description='',
  200. rules=[{
  201. "from_port": 22,
  202. "group": {},
  203. "ip_protocol": "tcp",
  204. "to_port": 22,
  205. "parent_group_id": 2,
  206. "ip_range": {
  207. "cidr": "0.0.0.0/0"
  208. },
  209. 'id': 130
  210. }, {
  211. 'from_port': 80,
  212. 'group': {},
  213. 'ip_protocol': 'tcp',
  214. 'to_port': 80,
  215. 'parent_group_id': 2,
  216. 'ip_range': {
  217. 'cidr': '0.0.0.0/0'
  218. },
  219. 'id': 131
  220. }, {
  221. 'from_port': None,
  222. 'group': {
  223. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  224. 'name': 'test'
  225. },
  226. 'ip_protocol': 'tcp',
  227. 'to_port': None,
  228. 'parent_group_id': 2,
  229. 'ip_range': {},
  230. 'id': 132
  231. }, {
  232. 'from_port': None,
  233. 'group': {
  234. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  235. 'name': 'test'
  236. },
  237. 'ip_protocol': 'icmp',
  238. 'to_port': None,
  239. 'parent_group_id': 2,
  240. 'ip_range': {},
  241. 'id': 133
  242. }]
  243. ))
  244. def stubout_nova_delete_security_group_rules(self, sg_name):
  245. self.stubout_nova_get_security_group(sg_name)
  246. nova_sgr.SecurityGroupRuleManager.delete(130).AndReturn(None)
  247. nova_sgr.SecurityGroupRuleManager.delete(131).AndReturn(None)
  248. nova_sgr.SecurityGroupRuleManager.delete(132).AndReturn(None)
  249. nova_sgr.SecurityGroupRuleManager.delete(133).AndReturn(None)
  250. def stubout_neutron_create_security_group(self):
  251. sg_name = utils.PhysName('test_stack', 'the_sg')
  252. neutronclient.Client.create_security_group({
  253. 'security_group': {
  254. 'name': sg_name,
  255. 'description': 'HTTP and SSH access'
  256. }
  257. }).AndReturn({
  258. 'security_group': {
  259. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  260. 'name': sg_name,
  261. 'description': 'HTTP and SSH access',
  262. 'security_group_rules': [{
  263. "direction": "egress",
  264. "ethertype": "IPv4",
  265. "id": "aaaa-1",
  266. "port_range_max": None,
  267. "port_range_min": None,
  268. "protocol": None,
  269. "remote_group_id": None,
  270. "remote_ip_prefix": None,
  271. "security_group_id": "aaaa",
  272. "tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
  273. }, {
  274. "direction": "egress",
  275. "ethertype": "IPv6",
  276. "id": "aaaa-2",
  277. "port_range_max": None,
  278. "port_range_min": None,
  279. "protocol": None,
  280. "remote_group_id": None,
  281. "remote_ip_prefix": None,
  282. "security_group_id": "aaaa",
  283. "tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
  284. }],
  285. 'id': 'aaaa'
  286. }
  287. })
  288. neutronclient.Client.delete_security_group_rule('aaaa-1').AndReturn(
  289. None)
  290. neutronclient.Client.delete_security_group_rule('aaaa-2').AndReturn(
  291. None)
  292. neutronclient.Client.create_security_group_rule({
  293. 'security_group_rule': {
  294. 'direction': 'ingress',
  295. 'remote_group_id': None,
  296. 'remote_ip_prefix': '0.0.0.0/0',
  297. 'port_range_min': 22,
  298. 'ethertype': 'IPv4',
  299. 'port_range_max': 22,
  300. 'protocol': 'tcp',
  301. 'security_group_id': 'aaaa'
  302. }
  303. }).AndReturn({
  304. 'security_group_rule': {
  305. 'direction': 'ingress',
  306. 'remote_group_id': None,
  307. 'remote_ip_prefix': '0.0.0.0/0',
  308. 'port_range_min': 22,
  309. 'ethertype': 'IPv4',
  310. 'port_range_max': 22,
  311. 'protocol': 'tcp',
  312. 'security_group_id': 'aaaa',
  313. 'id': 'bbbb'
  314. }
  315. })
  316. neutronclient.Client.create_security_group_rule({
  317. 'security_group_rule': {
  318. 'direction': 'ingress',
  319. 'remote_group_id': None,
  320. 'remote_ip_prefix': '0.0.0.0/0',
  321. 'port_range_min': 80,
  322. 'ethertype': 'IPv4',
  323. 'port_range_max': 80,
  324. 'protocol': 'tcp',
  325. 'security_group_id': 'aaaa'
  326. }
  327. }).AndReturn({
  328. 'security_group_rule': {
  329. 'direction': 'ingress',
  330. 'remote_group_id': None,
  331. 'remote_ip_prefix': '0.0.0.0/0',
  332. 'port_range_min': 80,
  333. 'ethertype': 'IPv4',
  334. 'port_range_max': 80,
  335. 'protocol': 'tcp',
  336. 'security_group_id': 'aaaa',
  337. 'id': 'cccc'
  338. }
  339. })
  340. neutronclient.Client.create_security_group_rule({
  341. 'security_group_rule': {
  342. 'direction': 'ingress',
  343. 'remote_group_id': 'wwww',
  344. 'remote_ip_prefix': None,
  345. 'port_range_min': None,
  346. 'ethertype': 'IPv4',
  347. 'port_range_max': None,
  348. 'protocol': 'tcp',
  349. 'security_group_id': 'aaaa'
  350. }
  351. }).AndReturn({
  352. 'security_group_rule': {
  353. 'direction': 'ingress',
  354. 'remote_group_id': 'wwww',
  355. 'remote_ip_prefix': None,
  356. 'port_range_min': None,
  357. 'ethertype': 'IPv4',
  358. 'port_range_max': None,
  359. 'protocol': 'tcp',
  360. 'security_group_id': 'aaaa',
  361. 'id': 'dddd'
  362. }
  363. })
  364. neutronclient.Client.create_security_group_rule({
  365. 'security_group_rule': {
  366. 'direction': 'egress',
  367. 'remote_group_id': None,
  368. 'remote_ip_prefix': '10.0.1.0/24',
  369. 'port_range_min': 22,
  370. 'ethertype': 'IPv4',
  371. 'port_range_max': 22,
  372. 'protocol': 'tcp',
  373. 'security_group_id': 'aaaa'
  374. }
  375. }).AndReturn({
  376. 'security_group_rule': {
  377. 'direction': 'egress',
  378. 'remote_group_id': None,
  379. 'remote_ip_prefix': '10.0.1.0/24',
  380. 'port_range_min': 22,
  381. 'ethertype': 'IPv4',
  382. 'port_range_max': 22,
  383. 'protocol': 'tcp',
  384. 'security_group_id': 'aaaa',
  385. 'id': 'eeee'
  386. }
  387. })
  388. neutronclient.Client.create_security_group_rule({
  389. 'security_group_rule': {
  390. 'direction': 'egress',
  391. 'remote_group_id': 'xxxx',
  392. 'remote_ip_prefix': None,
  393. 'port_range_min': None,
  394. 'ethertype': 'IPv4',
  395. 'port_range_max': None,
  396. 'protocol': None,
  397. 'security_group_id': 'aaaa'
  398. }
  399. }).AndReturn({
  400. 'security_group_rule': {
  401. 'direction': 'egress',
  402. 'remote_group_id': 'xxxx',
  403. 'remote_ip_prefix': None,
  404. 'port_range_min': None,
  405. 'ethertype': 'IPv4',
  406. 'port_range_max': None,
  407. 'protocol': None,
  408. 'security_group_id': 'aaaa',
  409. 'id': 'ffff'
  410. }
  411. })
  412. def stubout_neutron_get_security_group(self):
  413. neutronclient.Client.show_security_group('aaaa').AndReturn({
  414. 'security_group': {
  415. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  416. 'name': 'sc1',
  417. 'description': '',
  418. 'security_group_rules': [{
  419. 'direction': 'ingress',
  420. 'protocol': 'tcp',
  421. 'port_range_max': 22,
  422. 'id': 'bbbb',
  423. 'ethertype': 'IPv4',
  424. 'security_group_id': 'aaaa',
  425. 'remote_group_id': None,
  426. 'remote_ip_prefix': '0.0.0.0/0',
  427. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  428. 'port_range_min': 22
  429. }, {
  430. 'direction': 'ingress',
  431. 'protocol': 'tcp',
  432. 'port_range_max': 80,
  433. 'id': 'cccc',
  434. 'ethertype': 'IPv4',
  435. 'security_group_id': 'aaaa',
  436. 'remote_group_id': None,
  437. 'remote_ip_prefix': '0.0.0.0/0',
  438. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  439. 'port_range_min': 80
  440. }, {
  441. 'direction': 'ingress',
  442. 'protocol': 'tcp',
  443. 'port_range_max': None,
  444. 'id': 'dddd',
  445. 'ethertype': 'IPv4',
  446. 'security_group_id': 'aaaa',
  447. 'remote_group_id': 'wwww',
  448. 'remote_ip_prefix': None,
  449. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  450. 'port_range_min': None
  451. }, {
  452. 'direction': 'egress',
  453. 'protocol': 'tcp',
  454. 'port_range_max': 22,
  455. 'id': 'eeee',
  456. 'ethertype': 'IPv4',
  457. 'security_group_id': 'aaaa',
  458. 'remote_group_id': None,
  459. 'remote_ip_prefix': '10.0.1.0/24',
  460. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  461. 'port_range_min': 22
  462. }, {
  463. 'direction': 'egress',
  464. 'protocol': None,
  465. 'port_range_max': None,
  466. 'id': 'ffff',
  467. 'ethertype': 'IPv4',
  468. 'security_group_id': 'aaaa',
  469. 'remote_group_id': 'xxxx',
  470. 'remote_ip_prefix': None,
  471. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  472. 'port_range_min': None
  473. }],
  474. 'id': 'aaaa'}})
  475. def stubout_neutron_delete_security_group_rules(self):
  476. self.stubout_neutron_get_security_group()
  477. neutronclient.Client.delete_security_group_rule('bbbb').AndReturn(None)
  478. neutronclient.Client.delete_security_group_rule('cccc').AndReturn(None)
  479. neutronclient.Client.delete_security_group_rule('dddd').AndReturn(None)
  480. neutronclient.Client.delete_security_group_rule('eeee').AndReturn(None)
  481. neutronclient.Client.delete_security_group_rule('ffff').AndReturn(None)
  482. def test_security_group_nova(self):
  483. # create script
  484. sg_name = self.stubout_nova_create_security_group()
  485. # delete script
  486. self.stubout_nova_delete_security_group_rules(sg_name)
  487. nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
  488. self.m.ReplayAll()
  489. stack = self.create_stack(self.test_template_nova)
  490. sg = stack['the_sg']
  491. self.assertResourceState(sg, utils.PhysName('test_stack', 'the_sg'))
  492. stack.delete()
  493. self.m.VerifyAll()
  494. def test_security_group_nova_bad_source_group(self):
  495. # create script
  496. self.mock_no_neutron()
  497. nova.NovaClientPlugin._create().AndReturn(self.fc)
  498. nova_sg.SecurityGroupManager.list().MultipleTimes().AndReturn([NovaSG(
  499. id=1,
  500. name='test',
  501. description='FAKE_SECURITY_GROUP',
  502. rules=[],
  503. )])
  504. sg_name = utils.PhysName('test_stack', 'the_sg')
  505. nova_sg.SecurityGroupManager.create(
  506. sg_name,
  507. 'HTTP and SSH access').AndReturn(NovaSG(
  508. id=2,
  509. name=sg_name,
  510. description='HTTP and SSH access',
  511. rules=[]))
  512. # delete script
  513. nova_sg.SecurityGroupManager.get(2).AndReturn(NovaSG(
  514. id=2,
  515. name=sg_name,
  516. description='HTTP and SSH access',
  517. rules=[{
  518. "from_port": 22,
  519. "group": {},
  520. "ip_protocol": "tcp",
  521. "to_port": 22,
  522. "parent_group_id": 2,
  523. "ip_range": {
  524. "cidr": "0.0.0.0/0"
  525. },
  526. 'id': 130
  527. }, {
  528. 'from_port': 80,
  529. 'group': {},
  530. 'ip_protocol': 'tcp',
  531. 'to_port': 80,
  532. 'parent_group_id': 2,
  533. 'ip_range': {
  534. 'cidr': '0.0.0.0/0'
  535. },
  536. 'id': 131
  537. }]
  538. ))
  539. nova_sgr.SecurityGroupRuleManager.delete(130).AndReturn(None)
  540. nova_sgr.SecurityGroupRuleManager.delete(131).AndReturn(None)
  541. nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
  542. self.m.ReplayAll()
  543. stack = self.create_stack(self.test_template_nova_bad_source_group)
  544. sg = stack['the_sg']
  545. self.assertEqual(sg.FAILED, sg.status)
  546. self.assertIn('not found', sg.status_reason)
  547. stack.delete()
  548. self.m.VerifyAll()
  549. def test_security_group_nova_exception(self):
  550. # create script
  551. self.mock_no_neutron()
  552. nova.NovaClientPlugin._create().AndReturn(self.fc)
  553. sg_name = utils.PhysName('test_stack', 'the_sg')
  554. nova_sg.SecurityGroupManager.list().MultipleTimes().AndReturn([
  555. NovaSG(
  556. id=2,
  557. name=sg_name,
  558. description='HTTP and SSH access',
  559. rules=[],
  560. ),
  561. NovaSG(
  562. id=1,
  563. name='test',
  564. description='FAKE_SECURITY_GROUP',
  565. rules=[],
  566. )
  567. ])
  568. nova_sgr.SecurityGroupRuleManager.create(
  569. 2, 'tcp', 22, 22, '0.0.0.0/0', None).AndRaise(
  570. fakes_nova.fake_exception(400, 'Rule already exists'))
  571. nova_sgr.SecurityGroupRuleManager.create(
  572. 2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(
  573. fakes_nova.fake_exception(400, 'Rule already exists'))
  574. nova_sgr.SecurityGroupRuleManager.create(
  575. 2, 'tcp', None, None, None, 1).AndReturn(
  576. fakes_nova.fake_exception(400, 'Rule already exists'))
  577. nova_sgr.SecurityGroupRuleManager.create(
  578. 2, 'icmp', None, None, None, '1').AndReturn(
  579. fakes_nova.fake_exception(400, 'Rule already exists'))
  580. # delete script
  581. nova_sg.SecurityGroupManager.get(2).AndReturn(NovaSG(
  582. id=2,
  583. name=sg_name,
  584. description='HTTP and SSH access',
  585. rules=[{
  586. "from_port": 22,
  587. "group": {},
  588. "ip_protocol": "tcp",
  589. "to_port": 22,
  590. "parent_group_id": 2,
  591. "ip_range": {
  592. "cidr": "0.0.0.0/0"
  593. },
  594. 'id': 130
  595. }, {
  596. 'from_port': 80,
  597. 'group': {},
  598. 'ip_protocol': 'tcp',
  599. 'to_port': 80,
  600. 'parent_group_id': 2,
  601. 'ip_range': {
  602. 'cidr': '0.0.0.0/0'
  603. },
  604. 'id': 131
  605. }, {
  606. 'from_port': None,
  607. 'group': {
  608. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  609. 'name': 'test'
  610. },
  611. 'ip_protocol': 'tcp',
  612. 'to_port': None,
  613. 'parent_group_id': 2,
  614. 'ip_range': {},
  615. 'id': 132
  616. }, {
  617. 'from_port': None,
  618. 'group': {
  619. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  620. 'name': 'test'
  621. },
  622. 'ip_protocol': 'icmp',
  623. 'to_port': None,
  624. 'parent_group_id': 2,
  625. 'ip_range': {},
  626. 'id': 133
  627. }]
  628. ))
  629. nova_sgr.SecurityGroupRuleManager.delete(130).AndRaise(
  630. fakes_nova.fake_exception())
  631. nova_sgr.SecurityGroupRuleManager.delete(131).AndRaise(
  632. fakes_nova.fake_exception())
  633. nova_sgr.SecurityGroupRuleManager.delete(132).AndRaise(
  634. fakes_nova.fake_exception())
  635. nova_sgr.SecurityGroupRuleManager.delete(133).AndRaise(
  636. fakes_nova.fake_exception())
  637. nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
  638. nova_sg.SecurityGroupManager.get(2).AndRaise(
  639. fakes_nova.fake_exception())
  640. self.m.ReplayAll()
  641. stack = self.create_stack(self.test_template_nova)
  642. sg = stack['the_sg']
  643. self.assertResourceState(sg, utils.PhysName('test_stack', 'the_sg'))
  644. scheduler.TaskRunner(sg.delete)()
  645. sg.state_set(sg.CREATE, sg.COMPLETE, 'to delete again')
  646. sg.resource_id = 2
  647. stack.delete()
  648. self.m.VerifyAll()
  649. def test_security_group_nova_with_egress_rules(self):
  650. self.mock_no_neutron()
  651. t = template_format.parse(self.test_template_nova_with_egress)
  652. stack = self.parse_stack(t)
  653. sg = stack['the_sg']
  654. self.assertRaises(exception.EgressRuleNotAllowed, sg.validate)
  655. def test_security_group_neutron(self):
  656. # create script
  657. self.stubout_neutron_create_security_group()
  658. # delete script
  659. self.stubout_neutron_delete_security_group_rules()
  660. neutronclient.Client.delete_security_group('aaaa').AndReturn(None)
  661. self.m.ReplayAll()
  662. stack = self.create_stack(self.test_template_neutron)
  663. sg = stack['the_sg']
  664. self.assertResourceState(sg, 'aaaa')
  665. stack.delete()
  666. self.m.VerifyAll()
  667. def test_security_group_neutron_exception(self):
  668. # create script
  669. sg_name = utils.PhysName('test_stack', 'the_sg')
  670. neutronclient.Client.create_security_group({
  671. 'security_group': {
  672. 'name': sg_name,
  673. 'description': 'HTTP and SSH access'
  674. }
  675. }).AndReturn({
  676. 'security_group': {
  677. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  678. 'name': sg_name,
  679. 'description': 'HTTP and SSH access',
  680. 'security_group_rules': [],
  681. 'id': 'aaaa'
  682. }
  683. })
  684. neutronclient.Client.create_security_group_rule({
  685. 'security_group_rule': {
  686. 'direction': 'ingress',
  687. 'remote_group_id': None,
  688. 'remote_ip_prefix': '0.0.0.0/0',
  689. 'port_range_min': 22,
  690. 'ethertype': 'IPv4',
  691. 'port_range_max': 22,
  692. 'protocol': 'tcp',
  693. 'security_group_id': 'aaaa'
  694. }
  695. }).AndRaise(
  696. neutron_exc.Conflict())
  697. neutronclient.Client.create_security_group_rule({
  698. 'security_group_rule': {
  699. 'direction': 'ingress',
  700. 'remote_group_id': None,
  701. 'remote_ip_prefix': '0.0.0.0/0',
  702. 'port_range_min': 80,
  703. 'ethertype': 'IPv4',
  704. 'port_range_max': 80,
  705. 'protocol': 'tcp',
  706. 'security_group_id': 'aaaa'
  707. }
  708. }).AndRaise(
  709. neutron_exc.Conflict())
  710. neutronclient.Client.create_security_group_rule({
  711. 'security_group_rule': {
  712. 'direction': 'ingress',
  713. 'remote_group_id': 'wwww',
  714. 'remote_ip_prefix': None,
  715. 'port_range_min': None,
  716. 'ethertype': 'IPv4',
  717. 'port_range_max': None,
  718. 'protocol': 'tcp',
  719. 'security_group_id': 'aaaa'
  720. }
  721. }).AndRaise(
  722. neutron_exc.Conflict())
  723. neutronclient.Client.create_security_group_rule({
  724. 'security_group_rule': {
  725. 'direction': 'egress',
  726. 'remote_group_id': None,
  727. 'remote_ip_prefix': '10.0.1.0/24',
  728. 'port_range_min': 22,
  729. 'ethertype': 'IPv4',
  730. 'port_range_max': 22,
  731. 'protocol': 'tcp',
  732. 'security_group_id': 'aaaa'
  733. }
  734. }).AndRaise(
  735. neutron_exc.Conflict())
  736. neutronclient.Client.create_security_group_rule({
  737. 'security_group_rule': {
  738. 'direction': 'egress',
  739. 'remote_group_id': 'xxxx',
  740. 'remote_ip_prefix': None,
  741. 'port_range_min': None,
  742. 'ethertype': 'IPv4',
  743. 'port_range_max': None,
  744. 'protocol': None,
  745. 'security_group_id': 'aaaa'
  746. }
  747. }).AndRaise(
  748. neutron_exc.Conflict())
  749. # delete script
  750. neutronclient.Client.show_security_group('aaaa').AndReturn({
  751. 'security_group': {
  752. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  753. 'name': 'sc1',
  754. 'description': '',
  755. 'security_group_rules': [{
  756. 'direction': 'ingress',
  757. 'protocol': 'tcp',
  758. 'port_range_max': 22,
  759. 'id': 'bbbb',
  760. 'ethertype': 'IPv4',
  761. 'security_group_id': 'aaaa',
  762. 'remote_group_id': None,
  763. 'remote_ip_prefix': '0.0.0.0/0',
  764. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  765. 'port_range_min': 22
  766. }, {
  767. 'direction': 'ingress',
  768. 'protocol': 'tcp',
  769. 'port_range_max': 80,
  770. 'id': 'cccc',
  771. 'ethertype': 'IPv4',
  772. 'security_group_id': 'aaaa',
  773. 'remote_group_id': None,
  774. 'remote_ip_prefix': '0.0.0.0/0',
  775. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  776. 'port_range_min': 80
  777. }, {
  778. 'direction': 'ingress',
  779. 'protocol': 'tcp',
  780. 'port_range_max': None,
  781. 'id': 'dddd',
  782. 'ethertype': 'IPv4',
  783. 'security_group_id': 'aaaa',
  784. 'remote_group_id': 'wwww',
  785. 'remote_ip_prefix': None,
  786. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  787. 'port_range_min': None
  788. }, {
  789. 'direction': 'egress',
  790. 'protocol': 'tcp',
  791. 'port_range_max': 22,
  792. 'id': 'eeee',
  793. 'ethertype': 'IPv4',
  794. 'security_group_id': 'aaaa',
  795. 'remote_group_id': None,
  796. 'remote_ip_prefix': '10.0.1.0/24',
  797. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  798. 'port_range_min': 22
  799. }, {
  800. 'direction': 'egress',
  801. 'protocol': None,
  802. 'port_range_max': None,
  803. 'id': 'ffff',
  804. 'ethertype': 'IPv4',
  805. 'security_group_id': 'aaaa',
  806. 'remote_group_id': None,
  807. 'remote_ip_prefix': None,
  808. 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
  809. 'port_range_min': None
  810. }],
  811. 'id': 'aaaa'}})
  812. neutronclient.Client.delete_security_group_rule('bbbb').AndRaise(
  813. neutron_exc.NeutronClientException(status_code=404))
  814. neutronclient.Client.delete_security_group_rule('cccc').AndRaise(
  815. neutron_exc.NeutronClientException(status_code=404))
  816. neutronclient.Client.delete_security_group_rule('dddd').AndRaise(
  817. neutron_exc.NeutronClientException(status_code=404))
  818. neutronclient.Client.delete_security_group_rule('eeee').AndRaise(
  819. neutron_exc.NeutronClientException(status_code=404))
  820. neutronclient.Client.delete_security_group_rule('ffff').AndRaise(
  821. neutron_exc.NeutronClientException(status_code=404))
  822. neutronclient.Client.delete_security_group('aaaa').AndRaise(
  823. neutron_exc.NeutronClientException(status_code=404))
  824. neutronclient.Client.show_security_group('aaaa').AndRaise(
  825. neutron_exc.NeutronClientException(status_code=404))
  826. self.m.ReplayAll()
  827. stack = self.create_stack(self.test_template_neutron)
  828. sg = stack['the_sg']
  829. self.assertResourceState(sg, 'aaaa')
  830. scheduler.TaskRunner(sg.delete)()
  831. sg.state_set(sg.CREATE, sg.COMPLETE, 'to delete again')
  832. sg.resource_id = 'aaaa'
  833. stack.delete()
  834. self.m.VerifyAll()
  835. def test_security_group_nova_update(self):
  836. # create script
  837. sg_name = self.stubout_nova_create_security_group()
  838. # update script
  839. nova_sg.SecurityGroupManager.list().MultipleTimes().AndReturn([
  840. NovaSG(id='1',
  841. name='test',
  842. description='FAKE_SECURITY_GROUP',
  843. rules=[]),
  844. NovaSG(id='2',
  845. name=sg_name,
  846. description='HTTPS access',
  847. rules=[]),
  848. NovaSG(id='3',
  849. name='test2',
  850. description='FAKE_SECURITY_GROUP',
  851. rules=[]),
  852. ])
  853. # remove deleted groups
  854. self.stubout_nova_get_security_group(sg_name)
  855. nova_sgr.SecurityGroupRuleManager.delete(131).AndReturn(None)
  856. nova_sgr.SecurityGroupRuleManager.delete(132).AndReturn(None)
  857. # create missing groups
  858. nova_sgr.SecurityGroupRuleManager.create(
  859. 2, 'tcp', 443, 443, '0.0.0.0/0', None).AndReturn(None)
  860. nova_sgr.SecurityGroupRuleManager.create(
  861. 2, 'tcp', None, None, None, '3').AndReturn(None)
  862. self.m.ReplayAll()
  863. stack = self.create_stack(self.test_template_nova)
  864. sg = stack['the_sg']
  865. self.assertResourceState(sg, utils.PhysName('test_stack', 'the_sg'))
  866. # make updated template
  867. props = copy.deepcopy(sg.properties.data)
  868. props['SecurityGroupIngress'] = [
  869. {'IpProtocol': 'tcp',
  870. 'FromPort': '22',
  871. 'ToPort': '22',
  872. 'CidrIp': '0.0.0.0/0'},
  873. {'IpProtocol': 'tcp',
  874. 'FromPort': '443',
  875. 'ToPort': '443',
  876. 'CidrIp': '0.0.0.0/0'},
  877. {'IpProtocol': 'tcp',
  878. 'SourceSecurityGroupName': 'test2'},
  879. {'IpProtocol': 'icmp',
  880. 'SourceSecurityGroupId': '1'},
  881. ]
  882. after = rsrc_defn.ResourceDefinition(sg.name, sg.type(), props)
  883. scheduler.TaskRunner(sg.update, after)()
  884. self.assertEqual((sg.UPDATE, sg.COMPLETE), sg.state)
  885. self.m.VerifyAll()
  886. def test_security_group_neutron_update(self):
  887. # create script
  888. self.stubout_neutron_create_security_group()
  889. # update script
  890. # delete old not needed rules
  891. self.stubout_neutron_get_security_group()
  892. neutronclient.Client.delete_security_group_rule(
  893. 'bbbb').InAnyOrder().AndReturn(None)
  894. neutronclient.Client.delete_security_group_rule(
  895. 'dddd').InAnyOrder().AndReturn(None)
  896. neutronclient.Client.delete_security_group_rule(
  897. 'eeee').InAnyOrder().AndReturn(None)
  898. # create missing rules
  899. neutronclient.Client.create_security_group_rule({
  900. 'security_group_rule': {
  901. 'direction': 'ingress',
  902. 'remote_group_id': None,
  903. 'remote_ip_prefix': '0.0.0.0/0',
  904. 'port_range_min': 443,
  905. 'ethertype': 'IPv4',
  906. 'port_range_max': 443,
  907. 'protocol': 'tcp',
  908. 'security_group_id': 'aaaa'
  909. }
  910. }).InAnyOrder().AndReturn({
  911. 'security_group_rule': {
  912. 'direction': 'ingress',
  913. 'remote_group_id': None,
  914. 'remote_ip_prefix': '0.0.0.0/0',
  915. 'port_range_min': 443,
  916. 'ethertype': 'IPv4',
  917. 'port_range_max': 443,
  918. 'protocol': 'tcp',
  919. 'security_group_id': 'aaaa',
  920. 'id': 'bbbb'
  921. }
  922. })
  923. neutronclient.Client.create_security_group_rule({
  924. 'security_group_rule': {
  925. 'direction': 'ingress',
  926. 'remote_group_id': 'zzzz',
  927. 'remote_ip_prefix': None,
  928. 'port_range_min': None,
  929. 'ethertype': 'IPv4',
  930. 'port_range_max': None,
  931. 'protocol': 'tcp',
  932. 'security_group_id': 'aaaa'
  933. }
  934. }).InAnyOrder().AndReturn({
  935. 'security_group_rule': {
  936. 'direction': 'ingress',
  937. 'remote_group_id': 'zzzz',
  938. 'remote_ip_prefix': None,
  939. 'port_range_min': None,
  940. 'ethertype': 'IPv4',
  941. 'port_range_max': None,
  942. 'protocol': 'tcp',
  943. 'security_group_id': 'aaaa',
  944. 'id': 'dddd'
  945. }
  946. })
  947. neutronclient.Client.create_security_group_rule({
  948. 'security_group_rule': {
  949. 'direction': 'egress',
  950. 'remote_group_id': None,
  951. 'remote_ip_prefix': '0.0.0.0/0',
  952. 'port_range_min': 22,
  953. 'ethertype': 'IPv4',
  954. 'port_range_max': 22,
  955. 'protocol': 'tcp',
  956. 'security_group_id': 'aaaa'
  957. }
  958. }).InAnyOrder().AndReturn({
  959. 'security_group_rule': {
  960. 'direction': 'egress',
  961. 'remote_group_id': None,
  962. 'remote_ip_prefix': '0.0.0.0/0',
  963. 'port_range_min': 22,
  964. 'ethertype': 'IPv4',
  965. 'port_range_max': 22,
  966. 'protocol': 'tcp',
  967. 'security_group_id': 'aaaa',
  968. 'id': 'eeee'
  969. }
  970. })
  971. self.m.ReplayAll()
  972. stack = self.create_stack(self.test_template_neutron)
  973. sg = stack['the_sg']
  974. self.assertResourceState(sg, 'aaaa')
  975. # make updated template
  976. props = copy.deepcopy(sg.properties.data)
  977. props['SecurityGroupIngress'] = [
  978. {'IpProtocol': 'tcp',
  979. 'FromPort': '80',
  980. 'ToPort': '80',
  981. 'CidrIp': '0.0.0.0/0'},
  982. {'IpProtocol': 'tcp',
  983. 'FromPort': '443',
  984. 'ToPort': '443',
  985. 'CidrIp': '0.0.0.0/0'},
  986. {'IpProtocol': 'tcp',
  987. 'SourceSecurityGroupId': 'zzzz'},
  988. ]
  989. props['SecurityGroupEgress'] = [
  990. {'IpProtocol': 'tcp',
  991. 'FromPort': '22',
  992. 'ToPort': '22',
  993. 'CidrIp': '0.0.0.0/0'},
  994. {'SourceSecurityGroupName': 'xxxx'},
  995. ]
  996. after = rsrc_defn.ResourceDefinition(sg.name, sg.type(), props)
  997. scheduler.TaskRunner(sg.update, after)()
  998. self.assertEqual((sg.UPDATE, sg.COMPLETE), sg.state)
  999. self.m.VerifyAll()
  1000. def test_security_group_neutron_update_with_empty_rules(self):
  1001. # create script
  1002. self.stubout_neutron_create_security_group()
  1003. # update script
  1004. # delete old not needed rules
  1005. self.stubout_neutron_get_security_group()
  1006. neutronclient.Client.delete_security_group_rule(
  1007. 'eeee').InAnyOrder().AndReturn(None)
  1008. neutronclient.Client.delete_security_group_rule(
  1009. 'ffff').InAnyOrder().AndReturn(None)
  1010. self.m.ReplayAll()
  1011. stack = self.create_stack(self.test_template_neutron)
  1012. sg = stack['the_sg']
  1013. self.assertResourceState(sg, 'aaaa')
  1014. # make updated template
  1015. props = copy.deepcopy(sg.properties.data)
  1016. del props['SecurityGroupEgress']
  1017. after = rsrc_defn.ResourceDefinition(sg.name, sg.type(), props)
  1018. scheduler.TaskRunner(sg.update, after)()
  1019. self.assertEqual((sg.UPDATE, sg.COMPLETE), sg.state)
  1020. self.m.VerifyAll()
  1021. @mock.patch.object(security_group.SecurityGroup, 'is_using_neutron')
  1022. def test_security_group_refid_rsrc_name(self, mock_using_neutron):
  1023. mock_using_neutron.return_value = False
  1024. t = template_format.parse(self.test_template_nova)
  1025. stack = utils.parse_stack(t)
  1026. rsrc = stack['the_sg']
  1027. rsrc.id = '123'
  1028. rsrc.uuid = '9bfb9456-3fe8-41f4-b318-9dba18eeef74'
  1029. rsrc.action = 'CREATE'
  1030. expected = '%s-%s-%s' % (rsrc.stack.name,
  1031. rsrc.name,
  1032. short_id.get_id(rsrc.uuid))
  1033. self.assertEqual(expected, rsrc.FnGetRefId())
  1034. @mock.patch.object(security_group.SecurityGroup, 'is_using_neutron')
  1035. def test_security_group_refid_rsrc_id(self, mock_using_neutron):
  1036. mock_using_neutron.return_value = True
  1037. t = template_format.parse(self.test_template_nova)
  1038. stack = utils.parse_stack(t)
  1039. rsrc = stack['the_sg']
  1040. rsrc.resource_id = 'phy-rsrc-id'
  1041. self.assertEqual('phy-rsrc-id', rsrc.FnGetRefId())
  1042. def test_security_group_refid_convg_cache_data(self):
  1043. t = template_format.parse(self.test_template_nova)
  1044. cache_data = {'the_sg': {
  1045. 'uuid': mock.ANY,
  1046. 'id': mock.ANY,
  1047. 'action': 'CREATE',
  1048. 'status': 'COMPLETE',
  1049. 'reference_id': 'convg_xyz'
  1050. }}
  1051. stack = utils.parse_stack(t, cache_data=cache_data)
  1052. rsrc = stack['the_sg']
  1053. self.assertEqual('convg_xyz', rsrc.FnGetRefId())