summaryrefslogtreecommitdiff
path: root/src/migration-scripts/ipsec
diff options
context:
space:
mode:
Diffstat (limited to 'src/migration-scripts/ipsec')
-rwxr-xr-xsrc/migration-scripts/ipsec/4-to-514
-rwxr-xr-xsrc/migration-scripts/ipsec/5-to-693
-rwxr-xr-xsrc/migration-scripts/ipsec/6-to-7169
-rwxr-xr-xsrc/migration-scripts/ipsec/7-to-8125
4 files changed, 401 insertions, 0 deletions
diff --git a/src/migration-scripts/ipsec/4-to-5 b/src/migration-scripts/ipsec/4-to-5
index b64aa8462..4e959a7bf 100755
--- a/src/migration-scripts/ipsec/4-to-5
+++ b/src/migration-scripts/ipsec/4-to-5
@@ -1,4 +1,18 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2019 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
# log-modes have changed, keyword all to any
diff --git a/src/migration-scripts/ipsec/5-to-6 b/src/migration-scripts/ipsec/5-to-6
new file mode 100755
index 000000000..e9adee01b
--- /dev/null
+++ b/src/migration-scripts/ipsec/5-to-6
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Remove deprecated strongSwan options from VyOS CLI
+# - vpn ipsec nat-traversal enable
+# - vpn ipsec nat-networks allowed-network
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['vpn', 'ipsec']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+# Delete CLI nodes whose config options got removed by strongSwan
+for cli_node in ['nat-traversal', 'nat-networks']:
+ if config.exists(base + [cli_node]):
+ config.delete(base + [cli_node])
+
+# Remove options only valid in Openswan
+if config.exists(base + ['site-to-site', 'peer']):
+ for peer in config.list_nodes(base + ['site-to-site', 'peer']):
+ if not config.exists(base + ['site-to-site', 'peer', peer, 'tunnel']):
+ continue
+ for tunnel in config.list_nodes(base + ['site-to-site', 'peer', peer, 'tunnel']):
+ # allow-public-networks - Sets a value in ipsec.conf that was only ever valid in Openswan on kernel 2.6
+ nat_networks = base + ['site-to-site', 'peer', peer, 'tunnel', tunnel, 'allow-nat-networks']
+ if config.exists(nat_networks):
+ config.delete(nat_networks)
+
+ # allow-nat-networks - Also sets a value only valid in Openswan
+ public_networks = base + ['site-to-site', 'peer', peer, 'tunnel', tunnel, 'allow-public-networks']
+ if config.exists(public_networks):
+ config.delete(public_networks)
+
+# Rename "logging log-level" and "logging log-modes" to something more human friendly
+log = base + ['logging']
+if config.exists(log):
+ config.rename(log, 'log')
+ log = base + ['log']
+
+log_level = log + ['log-level']
+if config.exists(log_level):
+ config.rename(log_level, 'level')
+
+log_mode = log + ['log-modes']
+if config.exists(log_mode):
+ config.rename(log_mode, 'subsystem')
+
+# Rename "ipsec-interfaces interface" to "interface"
+base_interfaces = base + ['ipsec-interfaces', 'interface']
+if config.exists(base_interfaces):
+ config.copy(base_interfaces, base + ['interface'])
+ config.delete(base_interfaces)
+
+# Remove deprecated "auto-update" option
+tmp = base + ['auto-update']
+if config.exists(tmp):
+ config.delete(tmp)
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ exit(1)
diff --git a/src/migration-scripts/ipsec/6-to-7 b/src/migration-scripts/ipsec/6-to-7
new file mode 100755
index 000000000..788a87095
--- /dev/null
+++ b/src/migration-scripts/ipsec/6-to-7
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Migrate /config/auth certificates and keys into PKI configuration
+
+import os
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+from vyos.pki import load_certificate
+from vyos.pki import load_crl
+from vyos.pki import load_private_key
+from vyos.pki import encode_certificate
+from vyos.pki import encode_private_key
+from vyos.util import run
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+pki_base = ['pki']
+ipsec_site_base = ['vpn', 'ipsec', 'site-to-site', 'peer']
+
+config = ConfigTree(config_file)
+changes_made = False
+
+AUTH_DIR = '/config/auth'
+
+def wrapped_pem_to_config_value(pem):
+ return "".join(pem.strip().split("\n")[1:-1])
+
+if config.exists(ipsec_site_base):
+ config.set(pki_base + ['ca'])
+ config.set_tag(pki_base + ['ca'])
+
+ config.set(pki_base + ['certificate'])
+ config.set_tag(pki_base + ['certificate'])
+
+ for peer in config.list_nodes(ipsec_site_base):
+ if not config.exists(ipsec_site_base + [peer, 'authentication', 'x509']):
+ continue
+
+ changes_made = True
+
+ peer_x509_base = ipsec_site_base + [peer, 'authentication', 'x509']
+ pki_name = 'peer_' + peer.replace(".", "-")
+
+ if config.exists(peer_x509_base + ['cert-file']):
+ cert_file = config.return_value(peer_x509_base + ['cert-file'])
+ cert_path = os.path.join(AUTH_DIR, cert_file)
+ cert = None
+
+ if os.path.isfile(cert_path):
+ if not os.access(cert_path, os.R_OK):
+ run(f'sudo chmod 644 {cert_path}')
+
+ with open(cert_path, 'r') as f:
+ cert_data = f.read()
+ cert = load_certificate(cert_data, wrap_tags=False)
+
+ if cert:
+ cert_pem = encode_certificate(cert)
+ config.set(pki_base + ['certificate', pki_name, 'certificate'], value=wrapped_pem_to_config_value(cert_pem))
+ config.set(peer_x509_base + ['certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate certificate on peer "{peer}"')
+
+ config.delete(peer_x509_base + ['cert-file'])
+
+ if config.exists(peer_x509_base + ['ca-cert-file']):
+ ca_cert_file = config.return_value(peer_x509_base + ['ca-cert-file'])
+ ca_cert_path = os.path.join(AUTH_DIR, ca_cert_file)
+ ca_cert = None
+
+ if os.path.isfile(ca_cert_path):
+ if not os.access(ca_cert_path, os.R_OK):
+ run(f'sudo chmod 644 {ca_cert_path}')
+
+ with open(ca_cert_path, 'r') as f:
+ ca_cert_data = f.read()
+ ca_cert = load_certificate(ca_cert_data, wrap_tags=False)
+
+ if ca_cert:
+ ca_cert_pem = encode_certificate(ca_cert)
+ config.set(pki_base + ['ca', pki_name, 'certificate'], value=wrapped_pem_to_config_value(ca_cert_pem))
+ config.set(peer_x509_base + ['ca-certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate CA certificate on peer "{peer}"')
+
+ config.delete(peer_x509_base + ['ca-cert-file'])
+
+ if config.exists(peer_x509_base + ['crl-file']):
+ crl_file = config.return_value(peer_x509_base + ['crl-file'])
+ crl_path = os.path.join(AUTH_DIR, crl_file)
+ crl = None
+
+ if os.path.isfile(crl_path):
+ if not os.access(crl_path, os.R_OK):
+ run(f'sudo chmod 644 {crl_path}')
+
+ with open(crl_path, 'r') as f:
+ crl_data = f.read()
+ crl = load_crl(crl_data, wrap_tags=False)
+
+ if crl:
+ crl_pem = encode_certificate(crl)
+ config.set(pki_base + ['ca', pki_name, 'crl'], value=wrapped_pem_to_config_value(crl_pem))
+ else:
+ print(f'Failed to migrate CRL on peer "{peer}"')
+
+ config.delete(peer_x509_base + ['crl-file'])
+
+ if config.exists(peer_x509_base + ['key', 'file']):
+ key_file = config.return_value(peer_x509_base + ['key', 'file'])
+ key_passphrase = None
+
+ if config.exists(peer_x509_base + ['key', 'password']):
+ key_passphrase = config.return_value(peer_x509_base + ['key', 'password'])
+
+ key_path = os.path.join(AUTH_DIR, key_file)
+ key = None
+
+ if os.path.isfile(key_path):
+ if not os.access(key_path, os.R_OK):
+ run(f'sudo chmod 644 {key_path}')
+
+ with open(key_path, 'r') as f:
+ key_data = f.read()
+ key = load_private_key(key_data, passphrase=key_passphrase, wrap_tags=False)
+
+ if key:
+ key_pem = encode_private_key(key, passphrase=key_passphrase)
+ config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem))
+
+ if key_passphrase:
+ config.set(pki_base + ['certificate', pki_name, 'private', 'password-protected'])
+ config.set(peer_x509_base + ['private-key-passphrase'], value=key_passphrase)
+ else:
+ print(f'Failed to migrate private key on peer "{peer}"')
+
+ config.delete(peer_x509_base + ['key'])
+
+if changes_made:
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ sys.exit(1)
diff --git a/src/migration-scripts/ipsec/7-to-8 b/src/migration-scripts/ipsec/7-to-8
new file mode 100755
index 000000000..5d48b2875
--- /dev/null
+++ b/src/migration-scripts/ipsec/7-to-8
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Migrate rsa keys into PKI configuration
+
+import base64
+import os
+import struct
+
+from cryptography.hazmat.primitives.asymmetric import rsa
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+from vyos.pki import load_public_key
+from vyos.pki import load_private_key
+from vyos.pki import encode_public_key
+from vyos.pki import encode_private_key
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+pki_base = ['pki']
+ipsec_site_base = ['vpn', 'ipsec', 'site-to-site', 'peer']
+rsa_keys_base = ['vpn', 'rsa-keys']
+
+config = ConfigTree(config_file)
+
+LOCAL_KEY_PATHS = ['/config/auth/', '/config/ipsec.d/rsa-keys/']
+
+def migrate_from_vyatta_key(data):
+ data = base64.b64decode(data[2:])
+ length = struct.unpack('B', data[:1])[0]
+ e = int.from_bytes(data[1:1+length], 'big')
+ n = int.from_bytes(data[1+length:], 'big')
+ public_numbers = rsa.RSAPublicNumbers(e, n)
+ return public_numbers.public_key()
+
+def wrapped_pem_to_config_value(pem):
+ return "".join(pem.strip().split("\n")[1:-1])
+
+local_key_name = 'localhost'
+
+if config.exists(rsa_keys_base):
+ if not config.exists(pki_base + ['key-pair']):
+ config.set(pki_base + ['key-pair'])
+ config.set_tag(pki_base + ['key-pair'])
+
+ if config.exists(rsa_keys_base + ['local-key', 'file']):
+ local_file = config.return_value(rsa_keys_base + ['local-key', 'file'])
+ local_path = None
+ local_key = None
+
+ for path in LOCAL_KEY_PATHS:
+ full_path = os.path.join(path, local_file)
+ if os.path.exists(full_path):
+ local_path = full_path
+ break
+
+ if local_path:
+ with open(local_path, 'r') as f:
+ local_key_data = f.read()
+ local_key = load_private_key(local_key_data, wrap_tags=False)
+
+ if local_key:
+ local_key_pem = encode_private_key(local_key)
+ config.set(pki_base + ['key-pair', local_key_name, 'private', 'key'], value=wrapped_pem_to_config_value(local_key_pem))
+ else:
+ print('Failed to migrate local RSA key')
+
+ if config.exists(rsa_keys_base + ['rsa-key-name']):
+ for rsa_name in config.list_nodes(rsa_keys_base + ['rsa-key-name']):
+ if not config.exists(rsa_keys_base + ['rsa-key-name', rsa_name, 'rsa-key']):
+ continue
+
+ vyatta_key = config.return_value(rsa_keys_base + ['rsa-key-name', rsa_name, 'rsa-key'])
+ public_key = migrate_from_vyatta_key(vyatta_key)
+
+ if public_key:
+ public_key_pem = encode_public_key(public_key)
+ config.set(pki_base + ['key-pair', rsa_name, 'public', 'key'], value=wrapped_pem_to_config_value(public_key_pem))
+ else:
+ print(f'Failed to migrate rsa-key "{rsa_name}"')
+
+ config.delete(rsa_keys_base)
+
+if config.exists(ipsec_site_base):
+ for peer in config.list_nodes(ipsec_site_base):
+ mode = config.return_value(ipsec_site_base + [peer, 'authentication', 'mode'])
+
+ if mode != 'rsa':
+ continue
+
+ config.set(ipsec_site_base + [peer, 'authentication', 'rsa', 'local-key'], value=local_key_name)
+
+ remote_key_name = config.return_value(ipsec_site_base + [peer, 'authentication', 'rsa-key-name'])
+ config.set(ipsec_site_base + [peer, 'authentication', 'rsa', 'remote-key'], value=remote_key_name)
+ config.delete(ipsec_site_base + [peer, 'authentication', 'rsa-key-name'])
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ sys.exit(1)