Firewall services for OpenStack Neutron.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

851 lines
40 KiB

  1. # Copyright 2013 Big Switch Networks, Inc.
  2. # All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. import mock
  16. from neutron.api import extensions as api_ext
  17. from neutron.common import config
  18. from neutron.tests.common import helpers
  19. from neutron.tests import fake_notifier
  20. from neutron.tests.unit.extensions import test_agent
  21. from neutron.tests.unit.extensions import test_l3 as test_l3_plugin
  22. from neutron_lib.api import attributes as attr
  23. from neutron_lib.api.definitions import firewall as fwaas_def
  24. from neutron_lib.api.definitions import firewallrouterinsertion
  25. from neutron_lib import constants as nl_constants
  26. from neutron_lib import context
  27. from neutron_lib.exceptions import firewall_v1 as f_exc
  28. from neutron_lib.plugins import constants as plugin_constants
  29. from neutron_lib.plugins import directory
  30. from oslo_config import cfg
  31. from oslo_utils import uuidutils
  32. import six
  33. import testtools
  34. from webob import exc
  35. from neutron_fwaas.db.firewall import firewall_db as fdb
  36. import neutron_fwaas.extensions
  37. from neutron_fwaas.extensions import firewall
  38. from neutron_fwaas.services.firewall import fwaas_plugin
  39. from neutron_fwaas.tests import base
  40. from neutron_fwaas.tests.unit.db.firewall import (
  41. test_firewall_db as test_db_firewall)
  42. extensions_path = neutron_fwaas.extensions.__path__[0]
  43. FW_PLUGIN_KLASS = (
  44. "neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin"
  45. )
  46. class FirewallTestExtensionManager(test_l3_plugin.L3TestExtensionManager):
  47. def get_resources(self):
  48. res = super(FirewallTestExtensionManager, self).get_resources()
  49. fwaas_def.RESOURCE_ATTRIBUTE_MAP['firewalls'].update(
  50. firewallrouterinsertion.RESOURCE_ATTRIBUTE_MAP['firewalls'])
  51. return res + firewall.Firewall.get_resources()
  52. def get_actions(self):
  53. return []
  54. def get_request_extensions(self):
  55. return []
  56. class TestFirewallRouterInsertionBase(
  57. test_db_firewall.FirewallPluginDbTestCase):
  58. def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
  59. self.agentapi_del_fw_p = mock.patch(test_db_firewall.DELETEFW_PATH,
  60. create=True, new=test_db_firewall.FakeAgentApi().delete_firewall)
  61. self.agentapi_del_fw_p.start()
  62. # the plugin without L3 support
  63. plugin = 'neutron.tests.unit.extensions.test_l3.TestNoL3NatPlugin'
  64. # the L3 service plugin
  65. l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
  66. 'TestL3NatAgentSchedulingServicePlugin')
  67. cfg.CONF.set_override('api_extensions_path', extensions_path)
  68. self.saved_attr_map = {}
  69. for resource, attrs in six.iteritems(attr.RESOURCES):
  70. self.saved_attr_map[resource] = attrs.copy()
  71. if not fw_plugin:
  72. fw_plugin = FW_PLUGIN_KLASS
  73. service_plugins = {'l3_plugin_name': l3_plugin,
  74. 'fw_plugin_name': fw_plugin}
  75. if not ext_mgr:
  76. ext_mgr = FirewallTestExtensionManager()
  77. super(test_db_firewall.FirewallPluginDbTestCase, self).setUp(
  78. plugin=plugin, service_plugins=service_plugins, ext_mgr=ext_mgr)
  79. self.addCleanup(self.restore_attribute_map)
  80. self.setup_notification_driver()
  81. self.l3_plugin = directory.get_plugin(plugin_constants.L3)
  82. self.plugin = directory.get_plugin('FIREWALL')
  83. self.callbacks = self.plugin.endpoints[0]
  84. def restore_attribute_map(self):
  85. # Remove the fwaasrouterinsertion extension
  86. fwaas_def.RESOURCE_ATTRIBUTE_MAP['firewalls'].pop('router_ids')
  87. # Restore the original RESOURCE_ATTRIBUTE_MAP
  88. attr.RESOURCES = self.saved_attr_map
  89. def _create_firewall(self, fmt, name, description, firewall_policy_id=None,
  90. admin_state_up=True, expected_res_status=None,
  91. **kwargs):
  92. tenant_id = kwargs.get('tenant_id', self._tenant_id)
  93. router_ids = kwargs.get('router_ids')
  94. if firewall_policy_id is None:
  95. res = self._create_firewall_policy(fmt, 'fwp',
  96. description="firewall_policy",
  97. shared=True,
  98. firewall_rules=[],
  99. audited=True)
  100. firewall_policy = self.deserialize(fmt or self.fmt, res)
  101. firewall_policy_id = firewall_policy["firewall_policy"]["id"]
  102. data = {'firewall': {'name': name,
  103. 'description': description,
  104. 'firewall_policy_id': firewall_policy_id,
  105. 'admin_state_up': admin_state_up,
  106. 'tenant_id': tenant_id}}
  107. if router_ids is not None:
  108. data['firewall']['router_ids'] = router_ids
  109. firewall_req = self.new_create_request('firewalls', data, fmt)
  110. firewall_res = firewall_req.get_response(self.ext_api)
  111. if expected_res_status:
  112. self.assertEqual(expected_res_status, firewall_res.status_int)
  113. return firewall_res
  114. class TestFirewallCallbacks(TestFirewallRouterInsertionBase):
  115. def test_set_firewall_status(self):
  116. ctx = context.get_admin_context()
  117. with self.firewall_policy() as fwp:
  118. fwp_id = fwp['firewall_policy']['id']
  119. with self.firewall(
  120. firewall_policy_id=fwp_id,
  121. admin_state_up=test_db_firewall.ADMIN_STATE_UP
  122. ) as fw:
  123. fw_id = fw['firewall']['id']
  124. res = self.callbacks.set_firewall_status(ctx, fw_id,
  125. nl_constants.ACTIVE)
  126. fw_db = self.plugin.get_firewall(ctx, fw_id)
  127. self.assertEqual(nl_constants.ACTIVE, fw_db['status'])
  128. self.assertTrue(res)
  129. res = self.callbacks.set_firewall_status(ctx, fw_id,
  130. nl_constants.ERROR)
  131. fw_db = self.plugin.get_firewall(ctx, fw_id)
  132. self.assertEqual(nl_constants.ERROR, fw_db['status'])
  133. self.assertFalse(res)
  134. def test_set_firewall_status_pending_delete(self):
  135. ctx = context.get_admin_context()
  136. with self.firewall_policy() as fwp:
  137. fwp_id = fwp['firewall_policy']['id']
  138. with self.firewall(
  139. firewall_policy_id=fwp_id,
  140. admin_state_up=test_db_firewall.ADMIN_STATE_UP
  141. ) as fw:
  142. fw_id = fw['firewall']['id']
  143. fw_db = self.plugin._get_firewall(ctx, fw_id)
  144. fw_db['status'] = nl_constants.PENDING_DELETE
  145. ctx.session.flush()
  146. res = self.callbacks.set_firewall_status(ctx, fw_id,
  147. nl_constants.ACTIVE)
  148. fw_db = self.plugin.get_firewall(ctx, fw_id)
  149. self.assertEqual(nl_constants.PENDING_DELETE, fw_db['status'])
  150. self.assertFalse(res)
  151. def test_firewall_deleted(self):
  152. ctx = context.get_admin_context()
  153. with self.firewall_policy() as fwp:
  154. fwp_id = fwp['firewall_policy']['id']
  155. with self.firewall(firewall_policy_id=fwp_id,
  156. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  157. do_delete=False) as fw:
  158. fw_id = fw['firewall']['id']
  159. with ctx.session.begin(subtransactions=True):
  160. fw_db = self.plugin._get_firewall(ctx, fw_id)
  161. fw_db['status'] = nl_constants.PENDING_DELETE
  162. ctx.session.flush()
  163. res = self.callbacks.firewall_deleted(ctx, fw_id)
  164. self.assertTrue(res)
  165. self.assertRaises(f_exc.FirewallNotFound,
  166. self.plugin.get_firewall,
  167. ctx, fw_id)
  168. def test_firewall_deleted_concurrently(self):
  169. ctx = context.get_admin_context()
  170. alt_ctx = context.get_admin_context()
  171. _get_firewall = self.plugin._get_firewall
  172. def getdelete(context, firewall_id):
  173. fw_db = _get_firewall(context, firewall_id)
  174. # NOTE(cby): Use a different session to simulate a concurrent del
  175. self.plugin.delete_db_firewall_object(alt_ctx, firewall_id)
  176. return fw_db
  177. with self.firewall_policy() as fwp:
  178. fwp_id = fwp['firewall_policy']['id']
  179. with self.firewall(
  180. firewall_policy_id=fwp_id,
  181. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  182. do_delete=False
  183. ) as fw:
  184. fw_id = fw['firewall']['id']
  185. with ctx.session.begin(subtransactions=True):
  186. fw_db = self.plugin._get_firewall(ctx, fw_id)
  187. fw_db['status'] = nl_constants.PENDING_DELETE
  188. ctx.session.flush()
  189. with mock.patch.object(
  190. self.plugin, '_get_firewall', side_effect=getdelete
  191. ):
  192. observed = self.callbacks.firewall_deleted(ctx, fw_id)
  193. self.assertTrue(observed)
  194. self.assertRaises(f_exc.FirewallNotFound,
  195. self.plugin.get_firewall,
  196. ctx, fw_id)
  197. def test_firewall_deleted_not_found(self):
  198. ctx = context.get_admin_context()
  199. observed = self.callbacks.firewall_deleted(ctx, 'notfound')
  200. self.assertTrue(observed)
  201. def test_firewall_deleted_error(self):
  202. ctx = context.get_admin_context()
  203. with self.firewall_policy() as fwp:
  204. fwp_id = fwp['firewall_policy']['id']
  205. with self.firewall(
  206. firewall_policy_id=fwp_id,
  207. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  208. ) as fw:
  209. fw_id = fw['firewall']['id']
  210. res = self.callbacks.firewall_deleted(ctx, fw_id)
  211. self.assertFalse(res)
  212. fw_db = self.plugin._get_firewall(ctx, fw_id)
  213. self.assertEqual(nl_constants.ERROR, fw_db['status'])
  214. def test_get_firewall_for_tenant(self):
  215. tenant_id = 'test-tenant'
  216. ctx = context.Context('', tenant_id)
  217. with self.firewall_rule(name='fwr1', tenant_id=tenant_id) as fwr1, \
  218. self.firewall_rule(name='fwr2', tenant_id=tenant_id) as fwr2, \
  219. self.firewall_rule(name='fwr3', tenant_id=tenant_id) as fwr3:
  220. with self.firewall_policy(tenant_id=tenant_id) as fwp:
  221. fwp_id = fwp['firewall_policy']['id']
  222. fr = [fwr1, fwr2, fwr3]
  223. fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
  224. data = {'firewall_policy':
  225. {'firewall_rules': fw_rule_ids}}
  226. req = self.new_update_request('firewall_policies', data,
  227. fwp_id)
  228. res = req.get_response(self.ext_api)
  229. attrs = self._get_test_firewall_attrs()
  230. attrs['firewall_policy_id'] = fwp_id
  231. with self.firewall(
  232. firewall_policy_id=fwp_id,
  233. tenant_id=tenant_id,
  234. admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw:
  235. fw_id = fw['firewall']['id']
  236. res = self.callbacks.get_firewalls_for_tenant(ctx)
  237. fw_rules = (
  238. self.plugin._make_firewall_dict_with_rules(ctx,
  239. fw_id)
  240. )
  241. fw_rules['add-router-ids'] = []
  242. fw_rules['del-router-ids'] = []
  243. self.assertEqual(fw_rules, res[0])
  244. self._compare_firewall_rule_lists(
  245. fwp_id, fr, res[0]['firewall_rule_list'])
  246. class TestFirewallAgentApi(base.BaseTestCase):
  247. def setUp(self):
  248. super(TestFirewallAgentApi, self).setUp()
  249. self.api = fwaas_plugin.FirewallAgentApi('topic', 'host')
  250. def test_init(self):
  251. self.assertEqual('topic', self.api.client.target.topic)
  252. self.assertEqual('host', self.api.host)
  253. def _call_test_helper(self, method_name, host):
  254. with mock.patch.object(self.api.client, 'cast') as rpc_mock, \
  255. mock.patch.object(self.api.client, 'prepare') as prepare_mock:
  256. prepare_mock.return_value = self.api.client
  257. getattr(self.api, method_name)(mock.sentinel.context, 'test', host)
  258. prepare_args = {'server': host}
  259. prepare_mock.assert_called_once_with(**prepare_args)
  260. rpc_mock.assert_called_once_with(mock.sentinel.context, method_name,
  261. firewall='test', host='host')
  262. def test_create_firewall(self):
  263. self._call_test_helper('create_firewall', 'host')
  264. def test_update_firewall(self):
  265. self._call_test_helper('update_firewall', 'host')
  266. def test_delete_firewall(self):
  267. self._call_test_helper('delete_firewall', 'host')
  268. class TestFirewallPluginBase(TestFirewallRouterInsertionBase,
  269. test_l3_plugin.L3NatTestCaseMixin):
  270. def setUp(self):
  271. super(TestFirewallPluginBase, self).setUp(fw_plugin=FW_PLUGIN_KLASS)
  272. fake_notifier.reset()
  273. def test_create_firewall_routers_not_specified(self):
  274. """neutron firewall-create test-policy """
  275. with self.router(name='router1', admin_state_up=True,
  276. tenant_id=self._tenant_id):
  277. with self.router(name='router2', admin_state_up=True,
  278. tenant_id=self._tenant_id):
  279. with self.firewall() as fw1:
  280. self.assertEqual(nl_constants.PENDING_CREATE,
  281. fw1['firewall']['status'])
  282. def test_create_firewall_routers_specified(self):
  283. """neutron firewall-create test-policy --router-ids "r1 r2" """
  284. with self.router(name='router1', admin_state_up=True,
  285. tenant_id=self._tenant_id) as router1:
  286. with self.router(name='router2', admin_state_up=True,
  287. tenant_id=self._tenant_id) as router2:
  288. router_ids = [router1['router']['id'], router2['router']['id']]
  289. with self.firewall(router_ids=router_ids) as fw1:
  290. self.assertEqual(nl_constants.PENDING_CREATE,
  291. fw1['firewall']['status'])
  292. def test_create_firewall_routers_present_empty_list_specified(self):
  293. """neutron firewall-create test-policy --router-ids "" """
  294. with self.router(name='router1', admin_state_up=True,
  295. tenant_id=self._tenant_id):
  296. with self.router(name='router2', admin_state_up=True,
  297. tenant_id=self._tenant_id):
  298. router_ids = []
  299. with self.firewall(router_ids=router_ids) as fw1:
  300. self.assertEqual(nl_constants.INACTIVE,
  301. fw1['firewall']['status'])
  302. def test_create_firewall_no_routers_empty_list_specified(self):
  303. """neutron firewall-create test-policy --router-ids "" """
  304. router_ids = []
  305. with self.firewall(router_ids=router_ids) as fw1:
  306. self.assertEqual(nl_constants.INACTIVE,
  307. fw1['firewall']['status'])
  308. def test_create_second_firewall_on_same_tenant(self):
  309. """fw1 created with default routers, fw2 no routers on same tenant."""
  310. with self.router(name='router1', admin_state_up=True,
  311. tenant_id=self._tenant_id):
  312. with self.router(name='router2', admin_state_up=True,
  313. tenant_id=self._tenant_id):
  314. router_ids = []
  315. with self.firewall() as fw1:
  316. with self.firewall(router_ids=router_ids) as fw2:
  317. self.assertEqual(nl_constants.PENDING_CREATE,
  318. fw1['firewall']['status'])
  319. self.assertEqual(nl_constants.INACTIVE,
  320. fw2['firewall']['status'])
  321. def test_create_firewall_admin_not_affected_by_other_tenant(self):
  322. # Create fw with admin after creating fw with other tenant
  323. with self.firewall(tenant_id='other-tenant') as fw1:
  324. with self.firewall() as fw2:
  325. self.assertEqual('other-tenant', fw1['firewall']['tenant_id'])
  326. self.assertEqual(self._tenant_id, fw2['firewall']['tenant_id'])
  327. def test_update_firewall_calls_get_dvr_hosts_for_router(self):
  328. ctx = context.get_admin_context()
  329. name = "user_fw"
  330. attrs = self._get_test_firewall_attrs(name)
  331. check_attr1 = getattr(self.l3_plugin,
  332. "get_l3_agents_hosting_routers", False)
  333. check_attr2 = getattr(self.l3_plugin,
  334. "_get_dvr_hosts_for_router", False)
  335. # For third-party L3-service plugins do not run this test
  336. if check_attr1 is False or check_attr2 is False:
  337. return
  338. with self.router(name='router1', admin_state_up=True,
  339. tenant_id=self._tenant_id) as router1:
  340. with self.firewall_policy() as fwp:
  341. fwp_id = fwp['firewall_policy']['id']
  342. attrs['firewall_policy_id'] = fwp_id
  343. with self.firewall(
  344. firewall_policy_id=fwp_id,
  345. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  346. router_ids=[router1['router']['id']]
  347. ) as firewall:
  348. fw_id = firewall['firewall']['id']
  349. self.callbacks.set_firewall_status(ctx, fw_id,
  350. nl_constants.ACTIVE)
  351. with mock.patch.object(
  352. self.l3_plugin,
  353. 'get_l3_agents_hosting_routers') as s_hosts, \
  354. mock.patch.object(
  355. self.plugin,
  356. '_check_dvr_extensions') as dvr_exts, \
  357. mock.patch.object(
  358. self.l3_plugin,
  359. '_get_dvr_hosts_for_router') as u_hosts:
  360. self.plugin.update_firewall(ctx, fw_id, firewall)
  361. dvr_exts.return_value = True
  362. self.assertTrue(u_hosts.called)
  363. self.assertTrue(s_hosts.called)
  364. def test_update_firewall(self):
  365. ctx = context.get_admin_context()
  366. name = "new_firewall1"
  367. attrs = self._get_test_firewall_attrs(name)
  368. with self.router(name='router1', admin_state_up=True,
  369. tenant_id=self._tenant_id) as router1:
  370. with self.firewall_policy() as fwp:
  371. fwp_id = fwp['firewall_policy']['id']
  372. attrs['firewall_policy_id'] = fwp_id
  373. with self.firewall(
  374. firewall_policy_id=fwp_id,
  375. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  376. router_ids=[router1['router']['id']]
  377. ) as firewall:
  378. fw_id = firewall['firewall']['id']
  379. res = self.callbacks.set_firewall_status(ctx, fw_id,
  380. nl_constants.ACTIVE)
  381. data = {'firewall': {'name': name}}
  382. req = self.new_update_request('firewalls', data, fw_id)
  383. res = self.deserialize(self.fmt,
  384. req.get_response(self.ext_api))
  385. attrs = self._replace_firewall_status(attrs,
  386. nl_constants.
  387. PENDING_CREATE,
  388. nl_constants.
  389. PENDING_UPDATE)
  390. for k, v in six.iteritems(attrs):
  391. self.assertEqual(v, res['firewall'][k])
  392. def test_update_firewall_fails_when_firewall_pending(self):
  393. name = "new_firewall1"
  394. attrs = self._get_test_firewall_attrs(name)
  395. with self.router(name='router1', admin_state_up=True,
  396. tenant_id=self._tenant_id) as router1:
  397. with self.firewall_policy() as fwp:
  398. fwp_id = fwp['firewall_policy']['id']
  399. attrs['firewall_policy_id'] = fwp_id
  400. with self.firewall(
  401. firewall_policy_id=fwp_id,
  402. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  403. router_ids=[router1['router']['id']]
  404. ) as firewall:
  405. fw_id = firewall['firewall']['id']
  406. data = {'firewall': {'name': name}}
  407. req = self.new_update_request('firewalls', data, fw_id)
  408. res = req.get_response(self.ext_api)
  409. self.assertEqual(exc.HTTPConflict.code, res.status_int)
  410. def test_update_firewall_with_router_when_firewall_inactive(self):
  411. name = "firewall1"
  412. attrs = self._get_test_firewall_attrs(name)
  413. with self.router(name='router1', admin_state_up=True,
  414. tenant_id=self._tenant_id) as router1:
  415. with self.firewall_policy() as fwp:
  416. fwp_id = fwp['firewall_policy']['id']
  417. attrs['firewall_policy_id'] = fwp_id
  418. with self.firewall(
  419. name=name,
  420. firewall_policy_id=fwp_id,
  421. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  422. router_ids=[]
  423. ) as firewall:
  424. fw_id = firewall['firewall']['id']
  425. data = {
  426. 'firewall': {'router_ids': [router1['router']['id']]}}
  427. req = self.new_update_request('firewalls', data, fw_id)
  428. res = self.deserialize(self.fmt,
  429. req.get_response(self.ext_api))
  430. attrs = self._replace_firewall_status(attrs,
  431. nl_constants.
  432. PENDING_CREATE,
  433. nl_constants.
  434. PENDING_UPDATE)
  435. for k, v in six.iteritems(attrs):
  436. self.assertEqual(v, res['firewall'][k])
  437. @testtools.skip('bug/1622694')
  438. def test_update_firewall_shared_fails_for_non_admin(self):
  439. ctx = context.get_admin_context()
  440. with self.router(name='router1', admin_state_up=True,
  441. tenant_id=self._tenant_id) as router1:
  442. with self.firewall_policy() as fwp:
  443. fwp_id = fwp['firewall_policy']['id']
  444. with self.firewall(
  445. firewall_policy_id=fwp_id,
  446. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  447. tenant_id='noadmin',
  448. router_ids=[router1['router']['id']]
  449. ) as firewall:
  450. fw_id = firewall['firewall']['id']
  451. self.callbacks.set_firewall_status(ctx, fw_id,
  452. nl_constants.ACTIVE)
  453. data = {'firewall': {'shared': True}}
  454. req = self.new_update_request(
  455. 'firewalls', data, fw_id,
  456. context=context.Context('', 'noadmin'))
  457. res = req.get_response(self.ext_api)
  458. self.assertEqual(exc.HTTPForbidden.code, res.status_int)
  459. def test_update_firewall_policy_fails_when_firewall_pending(self):
  460. name = "new_firewall1"
  461. attrs = self._get_test_firewall_attrs(name)
  462. with self.router(name='router1', admin_state_up=True,
  463. tenant_id=self._tenant_id):
  464. with self.firewall_policy() as fwp:
  465. fwp_id = fwp['firewall_policy']['id']
  466. attrs['firewall_policy_id'] = fwp_id
  467. with self.firewall(
  468. firewall_policy_id=fwp_id,
  469. admin_state_up=test_db_firewall.ADMIN_STATE_UP
  470. ):
  471. data = {'firewall_policy': {'name': name}}
  472. req = self.new_update_request('firewall_policies',
  473. data, fwp_id)
  474. res = req.get_response(self.ext_api)
  475. self.assertEqual(exc.HTTPConflict.code, res.status_int)
  476. def test_update_firewall_rule_fails_when_firewall_pending(self):
  477. with self.router(name='router1', admin_state_up=True,
  478. tenant_id=self._tenant_id):
  479. with self.firewall_rule(name='fwr1') as fr:
  480. with self.firewall_policy() as fwp:
  481. fwp_id = fwp['firewall_policy']['id']
  482. fr_id = fr['firewall_rule']['id']
  483. fw_rule_ids = [fr_id]
  484. data = {'firewall_policy':
  485. {'firewall_rules': fw_rule_ids}}
  486. req = self.new_update_request('firewall_policies', data,
  487. fwp_id)
  488. req.get_response(self.ext_api)
  489. with self.firewall(
  490. firewall_policy_id=fwp_id,
  491. admin_state_up=test_db_firewall.ADMIN_STATE_UP
  492. ):
  493. data = {'firewall_rule': {'protocol': 'udp'}}
  494. req = self.new_update_request('firewall_rules',
  495. data, fr_id)
  496. res = req.get_response(self.ext_api)
  497. self.assertEqual(exc.HTTPConflict.code, res.status_int)
  498. def test_delete_firewall_with_no_routers(self):
  499. ctx = context.get_admin_context()
  500. # stop the AgentRPC patch for this one to test pending states
  501. self.agentapi_del_fw_p.stop()
  502. with self.firewall_policy() as fwp:
  503. fwp_id = fwp['firewall_policy']['id']
  504. with self.firewall(
  505. firewall_policy_id=fwp_id,
  506. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  507. do_delete=False
  508. ) as fw:
  509. fw_id = fw['firewall']['id']
  510. req = self.new_delete_request('firewalls', fw_id)
  511. res = req.get_response(self.ext_api)
  512. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  513. self.assertRaises(f_exc.FirewallNotFound,
  514. self.plugin.get_firewall,
  515. ctx, fw_id)
  516. def test_delete_firewall_after_agent_delete(self):
  517. ctx = context.get_admin_context()
  518. with self.firewall_policy() as fwp:
  519. fwp_id = fwp['firewall_policy']['id']
  520. with self.firewall(firewall_policy_id=fwp_id,
  521. do_delete=False) as fw:
  522. fw_id = fw['firewall']['id']
  523. req = self.new_delete_request('firewalls', fw_id)
  524. res = req.get_response(self.ext_api)
  525. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  526. self.assertRaises(f_exc.FirewallNotFound,
  527. self.plugin.get_firewall,
  528. ctx, fw_id)
  529. def test_make_firewall_dict_with_in_place_rules(self):
  530. ctx = context.get_admin_context()
  531. with self.firewall_rule(name='fwr1') as fwr1, \
  532. self.firewall_rule(name='fwr2') as fwr2, \
  533. self.firewall_rule(name='fwr3') as fwr3:
  534. with self.firewall_policy() as fwp:
  535. fr = [fwr1, fwr2, fwr3]
  536. fwp_id = fwp['firewall_policy']['id']
  537. fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
  538. data = {'firewall_policy':
  539. {'firewall_rules': fw_rule_ids}}
  540. req = self.new_update_request('firewall_policies', data,
  541. fwp_id)
  542. req.get_response(self.ext_api)
  543. attrs = self._get_test_firewall_attrs()
  544. attrs['firewall_policy_id'] = fwp_id
  545. with self.firewall(
  546. firewall_policy_id=fwp_id,
  547. admin_state_up=test_db_firewall.ADMIN_STATE_UP,
  548. router_ids=[]
  549. ) as fw:
  550. fw_id = fw['firewall']['id']
  551. fw_rules = (
  552. self.plugin._make_firewall_dict_with_rules(ctx,
  553. fw_id)
  554. )
  555. self.assertEqual(fw_id, fw_rules['id'])
  556. self._compare_firewall_rule_lists(
  557. fwp_id, fr, fw_rules['firewall_rule_list'])
  558. def test_make_firewall_dict_with_in_place_rules_no_policy(self):
  559. ctx = context.get_admin_context()
  560. with self.firewall() as fw:
  561. fw_id = fw['firewall']['id']
  562. fw_rules = self.plugin._make_firewall_dict_with_rules(ctx, fw_id)
  563. self.assertEqual([], fw_rules['firewall_rule_list'])
  564. def test_list_firewalls(self):
  565. with self.firewall_policy() as fwp:
  566. fwp_id = fwp['firewall_policy']['id']
  567. with self.firewall(name='fw1', firewall_policy_id=fwp_id,
  568. description='fw') as fwalls:
  569. self._test_list_resources('firewall', [fwalls],
  570. query_params='description=fw')
  571. def test_list_firewalls_with_filtering(self):
  572. with self.router(name='my_router', admin_state_up=True,
  573. tenant_id=self._tenant_id) as router:
  574. router_id = router['router']['id']
  575. with self.firewall_policy() as fwp:
  576. fwp_id = fwp['firewall_policy']['id']
  577. with self.firewall(name='fw1', firewall_policy_id=fwp_id,
  578. description='fw',
  579. router_ids=[router_id]) as fwalls:
  580. filter_pattern = None
  581. fw = fwalls['firewall']
  582. for filter_pattern in fw:
  583. query_params = 'fields=%s' % filter_pattern
  584. expect = [{filter_pattern: fw[filter_pattern]}]
  585. self._test_list_resources('firewall', expect,
  586. query_params=query_params)
  587. def test_insert_rule(self):
  588. ctx = context.get_admin_context()
  589. with self.firewall_rule() as fwr:
  590. fr_id = fwr['firewall_rule']['id']
  591. rule_info = {'firewall_rule_id': fr_id}
  592. with self.firewall_policy() as fwp:
  593. fwp_id = fwp['firewall_policy']['id']
  594. with self.firewall(firewall_policy_id=fwp_id) as fw:
  595. fw_id = fw['firewall']['id']
  596. self.plugin.insert_rule(ctx, fwp_id, rule_info)
  597. fw_rules = self.plugin._make_firewall_dict_with_rules(
  598. ctx, fw_id)
  599. self.assertEqual(1, len(fw_rules['firewall_rule_list']))
  600. self.assertEqual(fr_id,
  601. fw_rules['firewall_rule_list'][0]['id'])
  602. def test_insert_rule_notif(self):
  603. ctx = context.get_admin_context()
  604. with self.firewall_rule() as fwr:
  605. fr_id = fwr['firewall_rule']['id']
  606. rule_info = {'firewall_rule_id': fr_id}
  607. with self.firewall_policy() as fwp:
  608. fwp_id = fwp['firewall_policy']['id']
  609. with self.firewall(firewall_policy_id=fwp_id):
  610. self.plugin.insert_rule(ctx, fwp_id, rule_info)
  611. notifications = fake_notifier.NOTIFICATIONS
  612. expected_event_type = 'firewall_policy.update.insert_rule'
  613. event_types = [event['event_type'] for event in notifications]
  614. self.assertIn(expected_event_type, event_types)
  615. def test_remove_rule(self):
  616. ctx = context.get_admin_context()
  617. with self.firewall_rule() as fwr:
  618. fr_id = fwr['firewall_rule']['id']
  619. rule_info = {'firewall_rule_id': fr_id}
  620. with self.firewall_policy(firewall_rules=[fr_id]) as fwp:
  621. fwp_id = fwp['firewall_policy']['id']
  622. with self.firewall(firewall_policy_id=fwp_id) as fw:
  623. fw_id = fw['firewall']['id']
  624. self.plugin.remove_rule(ctx, fwp_id, rule_info)
  625. fw_rules = self.plugin._make_firewall_dict_with_rules(
  626. ctx, fw_id)
  627. self.assertEqual([], fw_rules['firewall_rule_list'])
  628. def test_remove_rule_notif(self):
  629. ctx = context.get_admin_context()
  630. with self.firewall_rule() as fwr:
  631. fr_id = fwr['firewall_rule']['id']
  632. rule_info = {'firewall_rule_id': fr_id}
  633. with self.firewall_policy(firewall_rules=[fr_id]) as fwp:
  634. fwp_id = fwp['firewall_policy']['id']
  635. with self.firewall(firewall_policy_id=fwp_id):
  636. self.plugin.remove_rule(ctx, fwp_id, rule_info)
  637. notifications = fake_notifier.NOTIFICATIONS
  638. expected_event_type = 'firewall_policy.update.remove_rule'
  639. event_types = [event['event_type'] for event in notifications]
  640. self.assertIn(expected_event_type, event_types)
  641. def test_firewall_quota_lower(self):
  642. """Test quota using overridden value."""
  643. cfg.CONF.set_override('quota_firewall', 3, group='QUOTAS')
  644. with self.firewall(name='quota1'), \
  645. self.firewall(name='quota2'), \
  646. self.firewall(name='quota3'):
  647. data = {'firewall': {'name': 'quota4',
  648. 'firewall_policy_id': None,
  649. 'tenant_id': self._tenant_id,
  650. 'shared': False}}
  651. req = self.new_create_request('firewalls', data, 'json')
  652. res = req.get_response(self.ext_api)
  653. self.assertIn('Quota exceeded', res.body.decode('utf-8'))
  654. self.assertEqual(exc.HTTPConflict.code, res.status_int)
  655. def test_firewall_quota_default(self):
  656. """Test quota using default value."""
  657. with self.firewall(name='quota1'), \
  658. self.firewall(name='quota2'), \
  659. self.firewall(name='quota3'), \
  660. self.firewall(name='quota4'), \
  661. self.firewall(name='quota5'), \
  662. self.firewall(name='quota6'), \
  663. self.firewall(name='quota7'), \
  664. self.firewall(name='quota8'), \
  665. self.firewall(name='quota9'), \
  666. self.firewall(name='quota10'):
  667. data = {'firewall': {'name': 'quota11',
  668. 'firewall_policy_id': None,
  669. 'tenant_id': self._tenant_id,
  670. 'shared': False}}
  671. req = self.new_create_request('firewalls', data, 'json')
  672. res = req.get_response(self.ext_api)
  673. self.assertIn('Quota exceeded', res.body.decode('utf-8'))
  674. self.assertEqual(exc.HTTPConflict.code, res.status_int)
  675. class TestFirewallRouterPluginBase(test_db_firewall.FirewallPluginDbTestCase,
  676. test_l3_plugin.L3NatTestCaseMixin,
  677. test_agent.AgentDBTestMixIn):
  678. def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
  679. self.agentapi_del_fw_p = mock.patch(test_db_firewall.DELETEFW_PATH,
  680. create=True, new=test_db_firewall.FakeAgentApi().delete_firewall)
  681. self.agentapi_del_fw_p.start()
  682. self.client_mock = mock.MagicMock(name="mocked client")
  683. mock.patch('neutron.common.rpc.get_client'
  684. ).start().return_value = self.client_mock
  685. # the L3 routing with L3 agent scheduling service plugin
  686. l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
  687. 'TestL3NatAgentSchedulingServicePlugin')
  688. cfg.CONF.set_override('api_extensions_path', extensions_path)
  689. if not fw_plugin:
  690. fw_plugin = FW_PLUGIN_KLASS
  691. service_plugins = {'l3_plugin_name': l3_plugin,
  692. 'fw_plugin_name': fw_plugin}
  693. fdb.Firewall_db_mixin.\
  694. supported_extension_aliases = ["fwaas",
  695. "fwaasrouterinsertion"]
  696. fdb.Firewall_db_mixin.path_prefix = fwaas_def.API_PREFIX
  697. super(test_db_firewall.FirewallPluginDbTestCase, self).setUp(
  698. ext_mgr=ext_mgr,
  699. service_plugins=service_plugins
  700. )
  701. if not ext_mgr:
  702. ext_mgr = FirewallTestExtensionManager()
  703. app = config.load_paste_app('extensions_test_app')
  704. self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
  705. self.l3_plugin = directory.get_plugin(plugin_constants.L3)
  706. self.plugin = directory.get_plugin('FIREWALL')
  707. def test_get_firewall_tenant_ids_on_host_with_associated_router(self):
  708. agent = helpers.register_l3_agent("host1")
  709. tenant_id = uuidutils.generate_uuid()
  710. ctxt = context.get_admin_context()
  711. with self.router(name='router1', admin_state_up=True,
  712. tenant_id=tenant_id) as router1:
  713. router_id = router1['router']['id']
  714. self.l3_plugin.add_router_to_l3_agent(ctxt, agent.id,
  715. router_id)
  716. with self.firewall(tenant_id=tenant_id,
  717. router_ids=[router_id]):
  718. tenant_ids = self.plugin.get_firewall_tenant_ids_on_host(
  719. ctxt, 'host1')
  720. self.assertEqual([tenant_id], tenant_ids)
  721. def test_get_firewall_tenant_ids_on_host_without_associated_router(self):
  722. agent1 = helpers.register_l3_agent("host1")
  723. helpers.register_l3_agent("host2")
  724. tenant_id = uuidutils.generate_uuid()
  725. ctxt = context.get_admin_context()
  726. with self.router(name='router1', admin_state_up=True,
  727. tenant_id=tenant_id) as router1:
  728. router_id = router1['router']['id']
  729. self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
  730. router_id)
  731. with self.firewall(tenant_id=tenant_id,
  732. router_ids=[router_id]):
  733. tenant_ids = self.plugin.get_firewall_tenant_ids_on_host(
  734. ctxt, 'host_2')
  735. self.assertEqual([], tenant_ids)
  736. def test_get_firewall_tenant_ids_on_host_with_routers(self):
  737. agent1 = helpers.register_l3_agent("host1")
  738. tenant_id1 = uuidutils.generate_uuid()
  739. tenant_id2 = uuidutils.generate_uuid()
  740. ctxt = context.get_admin_context()
  741. with self.router(name='router1', admin_state_up=True,
  742. tenant_id=tenant_id1) as router1:
  743. with self.router(name='router2', admin_state_up=True,
  744. tenant_id=tenant_id2) as router2:
  745. router_id1 = router1['router']['id']
  746. router_id2 = router2['router']['id']
  747. self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
  748. router_id1)
  749. self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
  750. router_id2)
  751. with self.firewall(tenant_id=tenant_id1,
  752. router_ids=[router_id1]):
  753. with self.firewall(tenant_id=tenant_id2,
  754. router_ids=[router_id2]):
  755. tenant_ids = (self.plugin
  756. .get_firewall_tenant_ids_on_host(
  757. ctxt, 'host1'))
  758. self.assertItemsEqual([tenant_id1, tenant_id2],
  759. tenant_ids)