From 321392b9a7d288167b0155284c0b7d30af44e5b3 Mon Sep 17 00:00:00 2001 From: Dongcan Ye Date: Thu, 12 Jul 2018 09:00:13 +0000 Subject: [PATCH] Match IPSEC SA established state While using IKE policy with version v2, the IPsec siteconnection status always down. From librewan wiki[1], the "phase2" in IKEv2 mistakenly calls itself a PARENT SA which same as "phase1", This is a known bug for some versions of libreswan. For the newer versions of libreswan(3.20+), the "IPsec SA established" will successful output if phase2 state established. Here we match the "established" and "newest IPSEC" for an established IPSEC SA. [1] https://libreswan.org/wiki/How_to_read_status_output Change-Id: Iffff7d00f48e69fbc53bb45df17d6a5be6760a6d Closes-Bug: #1781354 --- .../services/vpn/device_drivers/ipsec.py | 4 +- .../services/vpn/device_drivers/test_ipsec.py | 41 +++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/neutron_vpnaas/services/vpn/device_drivers/ipsec.py b/neutron_vpnaas/services/vpn/device_drivers/ipsec.py index dc8cf9ae0..cc3723b45 100644 --- a/neutron_vpnaas/services/vpn/device_drivers/ipsec.py +++ b/neutron_vpnaas/services/vpn/device_drivers/ipsec.py @@ -184,9 +184,9 @@ class BaseSwanProcess(object): STATUS_RE = '\d\d\d "([a-f0-9\-]+).* (unrouted|erouted);' STATUS_NOT_RUNNING_RE = 'Command:.*ipsec.*status.*Exit code: [1|3]$' STATUS_IPSEC_SA_ESTABLISHED_RE = ( - '\d{3} #\d+: "([a-f0-9\-]+).*IPsec SA established.*') + '\d{3} #\d+: "([a-f0-9\-]+).*established.*newest IPSEC') STATUS_IPSEC_SA_ESTABLISHED_RE2 = ( - '\d{3} #\d+: "([a-f0-9\-\/x]+).*IPsec SA established.*') + '\d{3} #\d+: "([a-f0-9\-\/x]+).*established.*newest IPSEC') def __init__(self, conf, process_id, vpnservice, namespace): self.conf = conf diff --git a/neutron_vpnaas/tests/unit/services/vpn/device_drivers/test_ipsec.py b/neutron_vpnaas/tests/unit/services/vpn/device_drivers/test_ipsec.py index 19f31e7d1..03371ada4 100644 --- a/neutron_vpnaas/tests/unit/services/vpn/device_drivers/test_ipsec.py +++ b/neutron_vpnaas/tests/unit/services/vpn/device_drivers/test_ipsec.py @@ -292,12 +292,19 @@ EXPECTED_IPSEC_STRONGSWAN_SECRET_CONF = ''' ''' % FAKE_VPNSERVICE_ID PLUTO_ACTIVE_STATUS = """000 "%(conn_id)s/0x1": erouted;\n -000 #4: "%(conn_id)s/0x1":500 STATE_QUICK_R2 (IPsec SA established);""" % { +000 #4: "%(conn_id)s/0x1":500 STATE_QUICK_R2 (IPsec SA established); \ +newest IPSEC;""" % { + 'conn_id': FAKE_IPSEC_SITE_CONNECTION2_ID} +PLUTO_ACTIVE_STATUS_IKEV2 = """000 "%(conn_id)s/0x1": erouted;\n +000 #4: "%(conn_id)s/0x1":500 STATE_PARENT_R2 (PARENT SA established); \ +newest IPSEC;""" % { 'conn_id': FAKE_IPSEC_SITE_CONNECTION2_ID} PLUTO_MULTIPLE_SUBNETS_ESTABLISHED_STATUS = """000 "%(conn_id1)s/1x1": erouted;\n -000 #4: "%(conn_id1)s/1x1":500 STATE_QUICK_R2 (IPsec SA established);\n +000 #4: "%(conn_id1)s/1x1":500 STATE_QUICK_R2 (IPsec SA established); \ +newest IPSEC;\n 000 "%(conn_id2)s/2x1": erouted;\n -000 #4: "%(conn_id2)s/2x1":500 STATE_QUICK_R2 (IPsec SA established);\n""" % { +000 #4: "%(conn_id2)s/2x1":500 STATE_QUICK_R2 (IPsec SA established); \ +newest IPSEC;\n""" % { 'conn_id1': FAKE_IPSEC_SITE_CONNECTION1_ID, 'conn_id2': FAKE_IPSEC_SITE_CONNECTION2_ID} PLUTO_ACTIVE_NO_IPSEC_SA_STATUS = """000 "%(conn_id)s/0x1": erouted;\n @@ -798,6 +805,29 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver): self.assertEqual(constants.ACTIVE, ipsec_site_conn[connection_id]['status']) + def _test_status_handling_for_ike_v2_active_connection(self, + active_status): + """Test status handling for active connection.""" + router_id = self.router.router_id + connection_id = FAKE_IPSEC_SITE_CONNECTION2_ID + ike_policy = {'ike_version': 'v2', + 'encryption_algorithm': 'aes-128', + 'auth_algorithm': 'sha1', + 'pfs': 'group5', + 'lifetime_value': 3600} + vpn_service = FAKE_VPN_SERVICE + for isc in vpn_service["ipsec_site_connections"]: + isc['ikepolicy'] = ike_policy + self.driver.ensure_process(router_id, vpn_service) + self._execute.return_value = active_status + self.driver.report_status(mock.Mock()) + process_status = self.driver.process_status_cache[ + router_id] + ipsec_site_conn = process_status['ipsec_site_connections'] + self.assertEqual(constants.ACTIVE, process_status['status']) + self.assertEqual(constants.ACTIVE, + ipsec_site_conn[connection_id]['status']) + def _test_connection_names_handling_for_multiple_subnets(self, active_status): """Test connection names handling for multiple subnets.""" @@ -1394,6 +1424,11 @@ class TestOpenSwanProcess(IPSecDeviceLegacy): """Test status handling for active connection.""" self._test_status_handling_for_active_connection(PLUTO_ACTIVE_STATUS) + def test_status_handling_for_ike_v2_active_connection(self): + """Test status handling for active connection.""" + self._test_status_handling_for_ike_v2_active_connection( + PLUTO_ACTIVE_STATUS_IKEV2) + def test_status_handling_for_deleted_connection(self): """Test status handling for deleted connection.""" self._test_status_handling_for_deleted_connection(NOT_RUNNING_STATUS)