Merge "Don't include encryption algorithm in phase2alg for the AH protocol"

This commit is contained in:
Jenkins 2015-08-13 19:50:46 +00:00 committed by Gerrit Code Review
commit 86f6f88970
3 changed files with 195 additions and 33 deletions

View File

@ -6,8 +6,9 @@ conn %default
keylife=60m
keyingtries=%forever
{% for ipsec_site_connection in vpnservice.ipsec_site_connections if ipsec_site_connection.admin_state_up
%}conn {{ipsec_site_connection.id}}
{% if vpnservice.subnet.ip_version == 6 %}
-%}
conn {{ipsec_site_connection.id}}
{% if vpnservice.subnet.ip_version == 6 -%}
# To recognize the given IP addresses in this config
# as IPv6 addresses by pluto whack. Default is ipv4
connaddrfamily=ipv6
@ -15,11 +16,11 @@ conn %default
# Assign gateway address as leftnexthop
leftnexthop={{ipsec_site_connection.external_ip}}
# rightnexthop is not mandatory for ipsec, so no need in ipv6.
{% else %}
{% else -%}
# NOTE: a default route is required for %defaultroute to work...
leftnexthop=%defaultroute
rightnexthop=%defaultroute
{% endif %}
{% endif -%}
left={{ipsec_site_connection.external_ip}}
leftid={{ipsec_site_connection.external_ip}}
auto={{ipsec_site_connection.initiator}}
@ -63,11 +64,17 @@ conn %default
##########################
# [transform_protocol]
auth={{ipsec_site_connection.ipsecpolicy.transform_protocol}}
{% if ipsec_site_connection.ipsecpolicy.transform_protocol == "ah" -%}
# AH protocol does not support encryption
# [auth_algorithm]-[pfs]
phase2alg={{ipsec_site_connection.ipsecpolicy.auth_algorithm}};{{ipsec_site_connection.ipsecpolicy.pfs}}
{% else -%}
# [encryption_algorithm]-[auth_algorithm]-[pfs]
phase2alg={{ipsec_site_connection.ipsecpolicy.encryption_algorithm}}-{{ipsec_site_connection.ipsecpolicy.auth_algorithm}};{{ipsec_site_connection.ipsecpolicy.pfs}}
{% endif -%}
# [encapsulation_mode]
type={{ipsec_site_connection.ipsecpolicy.encapsulation_mode}}
# [lifetime_value]
lifetime={{ipsec_site_connection.ipsecpolicy.lifetime_value}}s
# lifebytes=100000 if lifetime_units=kilobytes (IKEv2 only)
{% endfor %}
{% endfor -%}

View File

@ -1,3 +1,4 @@
# Configuration for {{vpnservice.name}} {% for ipsec_site_connection in vpnservice.ipsec_site_connections %}
# Configuration for {{vpnservice.name}}
{% for ipsec_site_connection in vpnservice.ipsec_site_connections -%}
{{vpnservice.external_ip}} {{ipsec_site_connection.peer_id}} : PSK "{{ipsec_site_connection.psk}}"
{% endfor %}

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import difflib
import mock
import socket
@ -60,6 +61,7 @@ FAKE_VPN_SERVICE = {
'ipsec_site_connections': [
{'peer_cidrs': ['20.0.0.0/24',
'30.0.0.0/24'],
'admin_state_up': True,
'id': FAKE_IPSEC_SITE_CONNECTION1_ID,
'external_ip': '50.0.0.4',
'peer_address': '30.0.0.5',
@ -71,6 +73,7 @@ FAKE_VPN_SERVICE = {
'status': constants.PENDING_CREATE},
{'peer_cidrs': ['40.0.0.0/24',
'50.0.0.0/24'],
'admin_state_up': True,
'external_ip': '50.0.0.4',
'peer_address': '50.0.0.5',
'peer_id': '50.0.0.5',
@ -82,6 +85,108 @@ FAKE_VPN_SERVICE = {
'status': constants.PENDING_CREATE}]
}
AUTH_ESP = '''esp
# [encryption_algorithm]-[auth_algorithm]-[pfs]
phase2alg=aes128-sha1;modp1536'''
AUTH_AH = '''ah
# AH protocol does not support encryption
# [auth_algorithm]-[pfs]
phase2alg=sha1;modp1536'''
OPENSWAN_CONNECTION_DETAILS = '''# rightsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
# [mtu]
# Note It looks like not supported in the strongswan driver
# ignore it now
# [dpd_action]
dpdaction=
# [dpd_interval]
dpddelay=
# [dpd_timeout]
dpdtimeout=
# [auth_mode]
authby=secret
######################
# IKEPolicy params
######################
#ike version
ikev2=never
# [encryption_algorithm]-[auth_algorithm]-[pfs]
ike=aes128-sha1;modp1536
# [lifetime_value]
ikelifetime=s
# NOTE: it looks lifetime_units=kilobytes can't be enforced \
(could be seconds, hours, days...)
##########################
# IPsecPolicys params
##########################
# [transform_protocol]
auth=%(auth_mode)s
# [encapsulation_mode]
type=
# [lifetime_value]
lifetime=s
# lifebytes=100000 if lifetime_units=kilobytes (IKEv2 only)
'''
EXPECTED_OPENSWAN_CONF = """
# Configuration for myvpn
config setup
nat_traversal=yes
conn %(default_id)s
ikelifetime=480m
keylife=60m
keyingtries=%%forever
conn %(conn1_id)s
# NOTE: a default route is required for %%defaultroute to work...
leftnexthop=%%defaultroute
rightnexthop=%%defaultroute
left=50.0.0.4
leftid=50.0.0.4
auto=start
# NOTE:REQUIRED
# [subnet]
leftsubnet=10.0.0.0/24
# leftsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
######################
# ipsec_site_connections
######################
# [peer_address]
right=30.0.0.5
# [peer_id]
rightid=30.0.0.5
# [peer_cidrs]
rightsubnets={ 20.0.0.0/24 30.0.0.0/24 }
%(conn_details)sconn %(conn2_id)s
# NOTE: a default route is required for %%defaultroute to work...
leftnexthop=%%defaultroute
rightnexthop=%%defaultroute
left=50.0.0.4
leftid=50.0.0.4
auto=start
# NOTE:REQUIRED
# [subnet]
leftsubnet=10.0.0.0/24
# leftsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
######################
# ipsec_site_connections
######################
# [peer_address]
right=50.0.0.5
# [peer_id]
rightid=50.0.0.5
# [peer_cidrs]
rightsubnets={ 40.0.0.0/24 50.0.0.0/24 }
%(conn_details)s
"""
EXPECTED_IPSEC_OPENSWAN_SECRET_CONF = '''
# Configuration for myvpn
50.0.0.4 30.0.0.5 : PSK "password"
50.0.0.4 50.0.0.5 : PSK "password"'''
EXPECTED_IPSEC_STRONGSWAN_CONF = '''
# Configuration for myvpn
config setup
@ -166,6 +271,16 @@ class BaseIPsecDeviceDriver(base.BaseTestCase):
'interface_driver': mock.sentinel.interface_driver}
self.iptables = mock.Mock()
self.apply_mock = mock.Mock()
self.vpnservice = copy.deepcopy(FAKE_VPN_SERVICE)
@staticmethod
def generate_diff(a, b):
"""Generates unified diff of a and b."""
by_lines = lambda x: x.splitlines(True)
a, b = list(by_lines(a)), list(by_lines(b))
diff = difflib.unified_diff(a, b, fromfile="expected",
tofile="actual")
return diff
class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
@ -199,7 +314,7 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
def test_create_router(self):
process = mock.Mock(openswan_ipsec.OpenSwanProcess)
process.vpnservice = FAKE_VPN_SERVICE
process.vpnservice = self.vpnservice
self.driver.processes = {
FAKE_ROUTER_ID: process}
self.driver.create_router(self.router)
@ -209,7 +324,7 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
def test_destroy_router(self):
process_id = _uuid()
process = mock.Mock()
process.vpnservice = FAKE_VPN_SERVICE
process.vpnservice = self.vpnservice
self.driver.processes = {
process_id: process}
self.driver.destroy_router(process_id)
@ -260,7 +375,7 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
sync_router_ids)
def test__sync_vpn_processes_new_vpn_service(self):
new_vpnservice = FAKE_VPN_SERVICE
new_vpnservice = self.vpnservice
router_id = new_vpnservice['router_id']
self.driver.processes = {}
with mock.patch.object(self.driver, 'ensure_process') as ensure_p:
@ -277,14 +392,14 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
the existing vpnservice processes.
"""
process = mock.Mock()
vpnservice = FAKE_VPN_SERVICE
process.vpnservice = vpnservice
process.vpnservice = self.vpnservice
process.connection_status = {}
self.driver.processes = {
vpnservice['router_id']: process}
self.vpnservice['router_id']: process}
router_id_no_vpn = _uuid()
with mock.patch.object(self.driver, 'ensure_process') as ensure_p:
self.driver._sync_vpn_processes([vpnservice], [router_id_no_vpn])
self.driver._sync_vpn_processes([self.vpnservice],
[router_id_no_vpn])
self.assertEqual(ensure_p.call_count, 0)
def test__sync_vpn_processes_router_with_no_vpn_and_no_vpn_services(self):
@ -304,13 +419,12 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
is updated, _sync_vpn_processes restart/update the existing vpnservices
which are not yet stored in driver.processes.
"""
vpnservice = FAKE_VPN_SERVICE
router_id = FAKE_ROUTER_ID
self.driver.process_status_cache = {}
self.driver.processes = {}
with mock.patch.object(self.driver, 'ensure_process') as ensure_p:
ensure_p.side_effect = self.fake_ensure_process
self.driver._sync_vpn_processes([vpnservice], [router_id])
self.driver._sync_vpn_processes([self.vpnservice], [router_id])
self._test_add_nat_rule_helper()
self.driver.processes[router_id].update.assert_called_once_with()
@ -348,7 +462,7 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
process = self.driver.processes.get(process_id)
if not process:
process = mock.Mock()
process.vpnservice = FAKE_VPN_SERVICE
process.vpnservice = self.vpnservice
process.connection_status = {}
process.status = constants.ACTIVE
process.updated_pending_status = True
@ -392,7 +506,7 @@ class IPSecDeviceLegacy(BaseIPsecDeviceDriver):
context = mock.Mock()
process_id = _uuid()
process = mock.Mock()
process.vpnservice = FAKE_VPN_SERVICE
process.vpnservice = self.vpnservice
self.driver.processes = {
process_id: process}
self.driver.sync(context, [])
@ -557,14 +671,53 @@ class IPSecDeviceDVR(BaseIPsecDeviceDriver):
'fake_chain', 'fake_rule', top=True)
class TestOpenSwanProcess(base.BaseTestCase):
def setUp(self):
super(TestOpenSwanProcess, self).setUp()
self.process = openswan_ipsec.OpenSwanProcess(mock.ANY,
class TestOpenSwanProcess(BaseIPsecDeviceDriver):
def setUp(self, driver=openswan_ipsec.OpenSwanDriver,
ipsec_process=openswan_ipsec.OpenSwanProcess):
super(TestOpenSwanProcess, self).setUp(driver, ipsec_process)
self.conf.register_opts(openswan_ipsec.openswan_opts,
'openswan')
self.conf.set_override('state_path', '/tmp')
self.process = openswan_ipsec.OpenSwanProcess(self.conf,
'foo-process-id',
FAKE_VPN_SERVICE,
self.vpnservice,
mock.ANY)
self._execute = mock.patch.object(self.process, '_execute').start()
def _test_config_files_on_create(self, proto, auth_mode):
"""Verify that the content of config files are correct on create."""
auth_proto = {'transform_protocol': proto}
for conn in self.vpnservice['ipsec_site_connections']:
conn['ipsecpolicy'].update(auth_proto)
content = self.process._gen_config_content(
self.conf.openswan.ipsec_config_template,
self.vpnservice)
conn_details = OPENSWAN_CONNECTION_DETAILS % {'auth_mode': auth_mode}
expected_openswan_conf = EXPECTED_OPENSWAN_CONF % {
'default_id': '%default',
'conn1_id': FAKE_IPSEC_SITE_CONNECTION1_ID,
'conn2_id': FAKE_IPSEC_SITE_CONNECTION2_ID,
'conn_details': conn_details}
res_diff = self.generate_diff(expected_openswan_conf.strip(),
content.strip())
self.assertEqual(expected_openswan_conf.strip(),
str(content.strip()), message=''.join(res_diff))
content = self.process._gen_config_content(
self.conf.openswan.ipsec_secret_template,
self.vpnservice)
res_diff = self.generate_diff(
EXPECTED_IPSEC_OPENSWAN_SECRET_CONF.strip(),
content.strip())
self.assertEqual(EXPECTED_IPSEC_OPENSWAN_SECRET_CONF.strip(),
str(content.strip()), message=''.join(res_diff))
def test_config_files_on_create_esp_transform_protocol(self):
self._test_config_files_on_create('esp', AUTH_ESP)
def test_config_files_on_create_ah_transform_protocol(self):
self._test_config_files_on_create('ah', AUTH_AH)
def test__resolve_fqdn(self):
with mock.patch.object(socket, 'getaddrinfo') as mock_getaddr_info:
@ -643,9 +796,10 @@ class TestOpenSwanProcess(base.BaseTestCase):
class TestLibreSwanProcess(base.BaseTestCase):
def setUp(self):
super(TestLibreSwanProcess, self).setUp()
self.vpnservice = copy.deepcopy(FAKE_VPN_SERVICE)
self.ipsec_process = libreswan_ipsec.LibreSwanProcess(mock.ANY,
'foo-process-id',
FAKE_VPN_SERVICE,
self.vpnservice,
mock.ANY)
def test_ensure_configs(self):
@ -680,25 +834,25 @@ class IPsecStrongswanDeviceDriverLegacy(IPSecDeviceLegacy):
'strongswan')
self.conf.set_override('state_path', '/tmp')
self.driver.agent_rpc.get_vpn_services_on_host.return_value = [
FAKE_VPN_SERVICE]
self.vpnservice]
def test_config_files_on_create(self):
"""Verify that the content of config files are correct on create."""
process = self.driver.ensure_process(self.router.router_id,
FAKE_VPN_SERVICE)
self.vpnservice)
content = process._gen_config_content(
self.conf.strongswan.ipsec_config_template,
FAKE_VPN_SERVICE)
self.vpnservice)
self.assertEqual(EXPECTED_IPSEC_STRONGSWAN_CONF.strip(),
str(content.strip()))
content = process._gen_config_content(
self.conf.strongswan.strongswan_config_template,
FAKE_VPN_SERVICE)
self.vpnservice)
self.assertEqual(EXPECTED_STRONGSWAN_DEFAULT_CONF.strip(),
str(content.strip()))
content = process._gen_config_content(
self.conf.strongswan.ipsec_secret_template,
FAKE_VPN_SERVICE)
self.vpnservice)
self.assertEqual(EXPECTED_IPSEC_STRONGSWAN_SECRET_CONF.strip(),
str(content.strip()))
@ -706,7 +860,7 @@ class IPsecStrongswanDeviceDriverLegacy(IPSecDeviceLegacy):
"""Test status handling for downed connection."""
router_id = self.router.router_id
connection_id = FAKE_IPSEC_SITE_CONNECTION2_ID
self.driver.ensure_process(router_id, FAKE_VPN_SERVICE)
self.driver.ensure_process(router_id, self.vpnservice)
self._execute.return_value = DOWN_STATUS
self.driver.report_status(mock.Mock())
process_status = self.driver.process_status_cache[router_id]
@ -719,7 +873,7 @@ class IPsecStrongswanDeviceDriverLegacy(IPSecDeviceLegacy):
"""Test status handling for actived connection."""
router_id = self.router.router_id
connection_id = FAKE_IPSEC_SITE_CONNECTION2_ID
self.driver.ensure_process(router_id, FAKE_VPN_SERVICE)
self.driver.ensure_process(router_id, self.vpnservice)
self._execute.return_value = ACTIVE_STATUS
self.driver.report_status(mock.Mock())
process_status = self.driver.process_status_cache[
@ -732,7 +886,7 @@ class IPsecStrongswanDeviceDriverLegacy(IPSecDeviceLegacy):
def test_status_handling_for_deleted_connection(self):
"""Test status handling for deleted connection."""
router_id = self.router.router_id
self.driver.ensure_process(router_id, FAKE_VPN_SERVICE)
self.driver.ensure_process(router_id, self.vpnservice)
self._execute.return_value = NOT_RUNNING_STATUS
self.driver.report_status(mock.Mock())
process_status = self.driver.process_status_cache[router_id]
@ -743,7 +897,7 @@ class IPsecStrongswanDeviceDriverLegacy(IPSecDeviceLegacy):
def test_update_connection_status(self):
"""Test the status of ipsec-site-connection parsed correctly."""
router_id = self.router.router_id
process = self.driver.ensure_process(router_id, FAKE_VPN_SERVICE)
process = self.driver.ensure_process(router_id, self.vpnservice)
self._execute.return_value = NOT_RUNNING_STATUS
self.assertFalse(process.active)
# An empty return value to simulate that the StrongSwan process