From 3f67d9de998bebfb0f7ccb8ebda2a8bb99ed248f Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Fri, 14 Feb 2020 08:12:04 +0100 Subject: [PATCH] Do disruptive firewall initialization once The UFW default allow calls result in all existing firewall rules being removed and reinstated. Due to the side effect of active connections being terminated we only want to do this once. Change-Id: I300af4bbfeb6a309d103d00fe3362364a1d7cbb3 Closes-Bug: #1863093 --- src/lib/charm/openstack/ovn_central.py | 18 +++++++++++++----- src/reactive/ovn_central_handlers.py | 8 ++++++++ unit_tests/test_lib_charms_ovn_central.py | 11 ++++++++++- .../test_reactive_ovn_central_handlers.py | 7 +++++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/lib/charm/openstack/ovn_central.py b/src/lib/charm/openstack/ovn_central.py index b341aea..59433f5 100644 --- a/src/lib/charm/openstack/ovn_central.py +++ b/src/lib/charm/openstack/ovn_central.py @@ -299,6 +299,19 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm): }, }) + @staticmethod + def initialize_firewall(): + """Initialize firewall. + + Note that this function is disruptive to active connections and should + only be called when necessary. + """ + # set default allow + ch_ufw.enable() + ch_ufw.default_policy('allow', 'incoming') + ch_ufw.default_policy('allow', 'outgoing') + ch_ufw.default_policy('allow', 'routed') + def configure_firewall(self, port_addr_map): """Configure firewall. @@ -311,11 +324,6 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm): """ ufw_comment = 'charm-' + self.name - # set default allow - ch_ufw.enable() - ch_ufw.default_policy('allow', 'incoming') - ch_ufw.default_policy('allow', 'outgoing') - ch_ufw.default_policy('allow', 'routed') # reject connection to protected ports for port in set().union(*port_addr_map.keys()): ch_ufw.modify_access(src=None, dst='any', port=port, diff --git a/src/reactive/ovn_central_handlers.py b/src/reactive/ovn_central_handlers.py index fc8882b..b00ec8e 100644 --- a/src/reactive/ovn_central_handlers.py +++ b/src/reactive/ovn_central_handlers.py @@ -32,6 +32,14 @@ charm.use_defaults( ) +@reactive.when_none('charm.firewall_initialized') +def initialize_firewall(): + """Do one-time initialization of firewall.""" + with charm.provide_charm_instance() as ovn_charm: + ovn_charm.initialize_firewall() + reactive.set_flag('charm.firewall_initialized') + + @reactive.when_none('leadership.set.nb_cid', 'leadership.set.sb_cid') @reactive.when('config.rendered', 'certificates.connected', diff --git a/unit_tests/test_lib_charms_ovn_central.py b/unit_tests/test_lib_charms_ovn_central.py index cc800dd..ec5e042 100644 --- a/unit_tests/test_lib_charms_ovn_central.py +++ b/unit_tests/test_lib_charms_ovn_central.py @@ -219,6 +219,16 @@ class TestOVNCentralCharm(Helper): mock.call('sb', {3: {'inactivity_probe': 42000}}), ]) + def test_initialize_firewall(self): + self.patch_object(ovn_central, 'ch_ufw') + self.target.initialize_firewall() + self.ch_ufw.enable.assert_called_once_with() + self.ch_ufw.default_policy.assert_has_calls([ + mock.call('allow', 'incoming'), + mock.call('allow', 'outgoing'), + mock.call('allow', 'routed'), + ]) + def test_configure_firewall(self): self.patch_object(ovn_central, 'ch_ufw') self.ch_ufw.status.return_value = [ @@ -235,7 +245,6 @@ class TestOVNCentralCharm(Helper): (1, 2, 3, 4,): ('a.b.c.d', 'e.f.g.h',), (1, 2,): ('i.j.k.l', 'm.n.o.p',), }) - self.ch_ufw.enable.assert_called_once_with() self.ch_ufw.modify_access.assert_has_calls([ mock.call(src=None, dst='any', port=1, proto='tcp', action='reject', diff --git a/unit_tests/test_reactive_ovn_central_handlers.py b/unit_tests/test_reactive_ovn_central_handlers.py index ba381f1..0514e21 100644 --- a/unit_tests/test_reactive_ovn_central_handlers.py +++ b/unit_tests/test_reactive_ovn_central_handlers.py @@ -35,6 +35,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): 'configure_firewall': ('run-default-update-status',), 'enable_default_certificates': ('run-default-update-status', 'leadership.is_leader',), + 'initialize_firewall': ('charm.firewall_initialized',), 'initialize_ovsdbs': ('run-default-update-status', 'leadership.set.nb_cid', 'leadership.set.sb_cid',), @@ -83,6 +84,12 @@ class TestOvnCentralHandlers(test_utils.PatchHelper): self.target self.provide_charm_instance().__exit__.return_value = None + def test_initialize_firewall(self): + self.patch_object(handlers.reactive, 'set_flag') + handlers.initialize_firewall() + self.target.initialize_firewall.assert_called_once_with() + self.set_flag.assert_called_once_with('charm.firewall_initialized') + def test_announce_leader_ready(self): self.patch_object(handlers.reactive, 'endpoint_from_name') self.patch_object(handlers.reactive, 'endpoint_from_flag')