summaryrefslogtreecommitdiff
path: root/src/op_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/op_mode')
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py2
-rwxr-xr-xsrc/op_mode/ikev2_profile_generator.py230
-rwxr-xr-xsrc/op_mode/ping.py4
-rwxr-xr-xsrc/op_mode/pki.py189
-rwxr-xr-xsrc/op_mode/show_dhcp.py7
-rwxr-xr-xsrc/op_mode/show_dhcpv6.py6
-rwxr-xr-xsrc/op_mode/show_vrf.py7
-rwxr-xr-xsrc/op_mode/wireguard.py159
-rwxr-xr-xsrc/op_mode/wireguard_client.py2
9 files changed, 376 insertions, 230 deletions
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py
index 1fb61d263..d79b6c024 100755
--- a/src/op_mode/dns_forwarding_statistics.py
+++ b/src/op_mode/dns_forwarding_statistics.py
@@ -11,7 +11,7 @@ PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
OUT_TMPL_SRC = """
DNS forwarding statistics:
-Cache entries: {{ cache_entries -}}
+Cache entries: {{ cache_entries }}
Cache size: {{ cache_size }} kbytes
"""
diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py
new file mode 100755
index 000000000..d45525431
--- /dev/null
+++ b/src/op_mode/ikev2_profile_generator.py
@@ -0,0 +1,230 @@
+#!/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/>.
+
+import argparse
+
+from jinja2 import Template
+from sys import exit
+from socket import getfqdn
+from cryptography.x509.oid import NameOID
+
+from vyos.config import Config
+from vyos.pki import load_certificate
+from vyos.template import render_to_string
+from vyos.util import ask_input
+
+# Apple profiles only support one IKE/ESP encryption cipher and hash, whereas
+# VyOS comes with a multitude of different proposals for a connection.
+#
+# We take all available proposals from the VyOS CLI and ask the user which one
+# he would like to get enabled in his profile - thus there is limited possibility
+# to select a proposal that is not supported on the connection profile.
+#
+# IOS supports IKE-SA encryption algorithms:
+# - DES
+# - 3DES
+# - AES-128
+# - AES-256
+# - AES-128-GCM
+# - AES-256-GCM
+# - ChaCha20Poly1305
+#
+vyos2apple_cipher = {
+ '3des' : '3DES',
+ 'aes128' : 'AES-128',
+ 'aes256' : 'AES-256',
+ 'aes128gcm128' : 'AES-128-GCM',
+ 'aes256gcm128' : 'AES-256-GCM',
+ 'chacha20poly1305' : 'ChaCha20Poly1305',
+}
+
+# Windows supports IKE-SA encryption algorithms:
+# - DES3
+# - AES128
+# - AES192
+# - AES256
+# - GCMAES128
+# - GCMAES192
+# - GCMAES256
+#
+vyos2windows_cipher = {
+ '3des' : 'DES3',
+ 'aes128' : 'AES128',
+ 'aes192' : 'AES192',
+ 'aes256' : 'AES256',
+ 'aes128gcm128' : 'GCMAES128',
+ 'aes192gcm128' : 'GCMAES192',
+ 'aes256gcm128' : 'GCMAES256',
+}
+
+# IOS supports IKE-SA integrity algorithms:
+# - SHA1-96
+# - SHA1-160
+# - SHA2-256
+# - SHA2-384
+# - SHA2-512
+#
+vyos2apple_integrity = {
+ 'sha1' : 'SHA1-96',
+ 'sha1_160' : 'SHA1-160',
+ 'sha256' : 'SHA2-256',
+ 'sha384' : 'SHA2-384',
+ 'sha512' : 'SHA2-512',
+}
+
+# Windows supports IKE-SA integrity algorithms:
+# - SHA1-96
+# - SHA1-160
+# - SHA2-256
+# - SHA2-384
+# - SHA2-512
+#
+vyos2windows_integrity = {
+ 'sha1' : 'SHA196',
+ 'sha256' : 'SHA256',
+ 'aes128gmac' : 'GCMAES128',
+ 'aes192gmac' : 'GCMAES192',
+ 'aes256gmac' : 'GCMAES256',
+}
+
+# IOS 14.2 and later do no support dh-group 1,2 and 5. Supported DH groups would
+# be: 14, 15, 16, 17, 18, 19, 20, 21, 31
+ios_supported_dh_groups = ['14', '15', '16', '17', '18', '19', '20', '21', '31']
+# Windows 10 only allows a limited set of DH groups
+windows_supported_dh_groups = ['1', '2', '14', '24']
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--os', const='all', nargs='?', choices=['ios', 'windows'], help='Operating system used for config generation', required=True)
+parser.add_argument("--connection", action="store", help='IPsec IKEv2 remote-access connection name from CLI', required=True)
+parser.add_argument("--remote", action="store", help='VPN connection remote-address where the client will connect to', required=True)
+parser.add_argument("--profile", action="store", help='IKEv2 profile name used in the profile list on the device')
+parser.add_argument("--name", action="store", help='VPN connection name as seen in the VPN application later')
+args = parser.parse_args()
+
+ipsec_base = ['vpn', 'ipsec']
+config_base = ipsec_base + ['remote-access', 'connection']
+pki_base = ['pki']
+conf = Config()
+if not conf.exists(config_base):
+ exit('IPSec remote-access is not configured!')
+
+profile_name = 'VyOS IKEv2 Profile'
+if args.profile:
+ profile_name = args.profile
+
+vpn_name = 'VyOS IKEv2 VPN'
+if args.name:
+ vpn_name = args.name
+
+conn_base = config_base + [args.connection]
+if not conf.exists(conn_base):
+ exit(f'IPSec remote-access connection "{args.connection}" does not exist!')
+
+data = conf.get_config_dict(conn_base, key_mangling=('-', '_'),
+ get_first_key=True, no_tag_node_value_mangle=True)
+
+data['profile_name'] = profile_name
+data['vpn_name'] = vpn_name
+data['remote'] = args.remote
+# This is a reverse-DNS style unique identifier used to detect duplicate profiles
+tmp = getfqdn().split('.')
+tmp = reversed(tmp)
+data['rfqdn'] = '.'.join(tmp)
+
+pki = conf.get_config_dict(pki_base, get_first_key=True)
+ca_name = data['authentication']['x509']['ca_certificate']
+cert_name = data['authentication']['x509']['certificate']
+
+ca_cert = load_certificate(pki['ca'][ca_name]['certificate'])
+cert = load_certificate(pki['certificate'][cert_name]['certificate'])
+
+data['ca_cn'] = ca_cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
+data['cert_cn'] = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
+data['ca_cert'] = conf.return_value(pki_base + ['ca', ca_name, 'certificate'])
+
+esp_proposals = conf.get_config_dict(ipsec_base + ['esp-group', data['esp_group'], 'proposal'],
+ key_mangling=('-', '_'), get_first_key=True)
+ike_proposal = conf.get_config_dict(ipsec_base + ['ike-group', data['ike_group'], 'proposal'],
+ key_mangling=('-', '_'), get_first_key=True)
+
+
+# This script works only for Apple iOS/iPadOS and Windows. Both operating systems
+# have different limitations thus we load the limitations based on the operating
+# system used.
+
+vyos2client_cipher = vyos2apple_cipher if args.os == 'ios' else vyos2windows_cipher;
+vyos2client_integrity = vyos2apple_integrity if args.os == 'ios' else vyos2windows_integrity;
+supported_dh_groups = ios_supported_dh_groups if args.os == 'ios' else windows_supported_dh_groups;
+
+# Create a dictionary containing client conform IKE settings
+ike = {}
+count = 1
+for _, proposal in ike_proposal.items():
+ if {'dh_group', 'encryption', 'hash'} <= set(proposal):
+ if (proposal['encryption'] in set(vyos2client_cipher) and
+ proposal['hash'] in set(vyos2client_integrity) and
+ proposal['dh_group'] in set(supported_dh_groups)):
+
+ # We 're-code' from the VyOS IPSec proposals to the Apple naming scheme
+ proposal['encryption'] = vyos2client_cipher[ proposal['encryption'] ]
+ proposal['hash'] = vyos2client_integrity[ proposal['hash'] ]
+
+ ike.update( { str(count) : proposal } )
+ count += 1
+
+# Create a dictionary containing Apple conform ESP settings
+esp = {}
+count = 1
+for _, proposal in esp_proposals.items():
+ if {'encryption', 'hash'} <= set(proposal):
+ if proposal['encryption'] in set(vyos2client_cipher) and proposal['hash'] in set(vyos2client_integrity):
+ # We 're-code' from the VyOS IPSec proposals to the Apple naming scheme
+ proposal['encryption'] = vyos2client_cipher[ proposal['encryption'] ]
+ proposal['hash'] = vyos2client_integrity[ proposal['hash'] ]
+
+ esp.update( { str(count) : proposal } )
+ count += 1
+try:
+ if len(ike) > 1:
+ # Propare the input questions for the user
+ tmp = '\n'
+ for number, options in ike.items():
+ tmp += f'({number}) Encryption {options["encryption"]}, Integrity {options["hash"]}, DH group {options["dh_group"]}\n'
+ tmp += '\nSelect one of the above IKE groups: '
+ data['ike_encryption'] = ike[ ask_input(tmp, valid_responses=list(ike)) ]
+ else:
+ data['ike_encryption'] = ike['1']
+
+ if len(esp) > 1:
+ tmp = '\n'
+ for number, options in esp.items():
+ tmp += f'({number}) Encryption {options["encryption"]}, Integrity {options["hash"]}\n'
+ tmp += '\nSelect one of the above ESP groups: '
+ data['esp_encryption'] = esp[ ask_input(tmp, valid_responses=list(esp)) ]
+ else:
+ data['esp_encryption'] = esp['1']
+
+except KeyboardInterrupt:
+ exit("Interrupted")
+
+print('\n\n==== <snip> ====')
+if args.os == 'ios':
+ print(render_to_string('ipsec/ios_profile.tmpl', data))
+ print('==== </snip> ====\n')
+ print('Save the XML from above to a new file named "vyos.mobileconfig" and E-Mail it to your phone.')
+elif args.os == 'windows':
+ print(render_to_string('ipsec/windows_profile.tmpl', data))
+ print('==== </snip> ====\n')
diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py
index 924a889db..2144ab53c 100755
--- a/src/op_mode/ping.py
+++ b/src/op_mode/ping.py
@@ -51,7 +51,7 @@ options = {
'help': 'Number of seconds before ping exits'
},
'do-not-fragment': {
- 'ping': '{command} -M dont',
+ 'ping': '{command} -M do',
'type': 'noarg',
'help': 'Set DF-bit flag to 1 for no fragmentation'
},
@@ -220,6 +220,8 @@ if __name__ == '__main__':
try:
ip = socket.gethostbyname(host)
+ except UnicodeError:
+ sys.exit(f'ping: Unknown host: {host}')
except socket.gaierror:
ip = host
diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py
index 7dbeb4097..297270cf1 100755
--- a/src/op_mode/pki.py
+++ b/src/op_mode/pki.py
@@ -38,6 +38,8 @@ from vyos.util import cmd
CERT_REQ_END = '-----END CERTIFICATE REQUEST-----'
+auth_dir = '/config/auth'
+
# Helper Functions
def get_default_values():
@@ -215,7 +217,7 @@ def install_wireguard_key(name, private_key, public_key):
print("")
print("Public key for use on peer configuration: " + public_key)
else:
- print("set interfaces wireguard [INTERFACE] peer %s pubkey '%s'" % (name, public_key))
+ print("set interfaces wireguard [INTERFACE] peer %s public-key '%s'" % (name, public_key))
print("")
print("Private key for use on peer configuration: " + private_key)
@@ -230,6 +232,22 @@ def ask_passphrase():
passphrase = ask_input('Enter passphrase:')
return passphrase
+def write_file(filename, contents):
+ full_path = os.path.join(auth_dir, filename)
+ directory = os.path.dirname(full_path)
+
+ if not os.path.exists(directory):
+ print('Failed to write file: directory does not exist')
+ return False
+
+ if os.path.exists(full_path) and not ask_yes_no('Do you want to overwrite the existing file?'):
+ return False
+
+ with open(full_path, 'w') as f:
+ f.write(contents)
+
+ print(f'File written to {full_path}')
+
# Generation functions
def generate_private_key():
@@ -266,7 +284,7 @@ def parse_san_string(san_string):
output.append(value)
return output
-def generate_certificate_request(private_key=None, key_type=None, return_request=False, name=None, install=False, ask_san=True):
+def generate_certificate_request(private_key=None, key_type=None, return_request=False, name=None, install=False, file=False, ask_san=True):
if not private_key:
private_key, key_type = generate_private_key()
@@ -291,14 +309,19 @@ def generate_certificate_request(private_key=None, key_type=None, return_request
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_certificate(cert_req))
print(encode_private_key(private_key, passphrase=passphrase))
return None
- print("Certificate request:")
- print(encode_certificate(cert_req) + "\n")
- install_certificate(name, private_key=private_key, key_type=key_type, key_passphrase=passphrase, is_ca=False)
+ if install:
+ print("Certificate request:")
+ print(encode_certificate(cert_req) + "\n")
+ install_certificate(name, private_key=private_key, key_type=key_type, key_passphrase=passphrase, is_ca=False)
+
+ if file:
+ write_file(f'{name}.csr', encode_certificate(cert_req))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
def generate_certificate(cert_req, ca_cert, ca_private_key, is_ca=False, is_sub_ca=False):
valid_days = ask_input('Enter how many days certificate will be valid:', default='365' if not is_ca else '1825', numeric_only=True)
@@ -307,20 +330,25 @@ def generate_certificate(cert_req, ca_cert, ca_private_key, is_ca=False, is_sub_
cert_type = ask_input('Enter certificate type: (client, server)', default='server', valid_responses=['client', 'server'])
return create_certificate(cert_req, ca_cert, ca_private_key, valid_days, cert_type, is_ca, is_sub_ca)
-def generate_ca_certificate(name, install=False):
+def generate_ca_certificate(name, install=False, file=False):
private_key, key_type = generate_private_key()
cert_req = generate_certificate_request(private_key, key_type, return_request=True, ask_san=False)
cert = generate_certificate(cert_req, cert_req, private_key, is_ca=True)
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_certificate(cert))
print(encode_private_key(private_key, passphrase=passphrase))
return None
- install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=True)
+ if install:
+ install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=True)
+
+ if file:
+ write_file(f'{name}.pem', encode_certificate(cert))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
-def generate_ca_certificate_sign(name, ca_name, install=False):
+def generate_ca_certificate_sign(name, ca_name, install=False, file=False):
ca_dict = get_config_ca_certificate(ca_name)
if not ca_dict:
@@ -374,14 +402,19 @@ def generate_ca_certificate_sign(name, ca_name, install=False):
cert = generate_certificate(cert_req, ca_cert, ca_private_key, is_ca=True, is_sub_ca=True)
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_certificate(cert))
print(encode_private_key(private_key, passphrase=passphrase))
return None
- install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=True)
+ if install:
+ install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=True)
+
+ if file:
+ write_file(f'{name}.pem', encode_certificate(cert))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
-def generate_certificate_sign(name, ca_name, install=False):
+def generate_certificate_sign(name, ca_name, install=False, file=False):
ca_dict = get_config_ca_certificate(ca_name)
if not ca_dict:
@@ -435,27 +468,37 @@ def generate_certificate_sign(name, ca_name, install=False):
cert = generate_certificate(cert_req, ca_cert, ca_private_key, is_ca=False)
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_certificate(cert))
print(encode_private_key(private_key, passphrase=passphrase))
return None
- install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=False)
+ if install:
+ install_certificate(name, cert, private_key, key_type, key_passphrase=passphrase, is_ca=False)
+
+ if file:
+ write_file(f'{name}.pem', encode_certificate(cert))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
-def generate_certificate_selfsign(name, install=False):
+def generate_certificate_selfsign(name, install=False, file=False):
private_key, key_type = generate_private_key()
cert_req = generate_certificate_request(private_key, key_type, return_request=True)
cert = generate_certificate(cert_req, cert_req, private_key, is_ca=False)
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_certificate(cert))
print(encode_private_key(private_key, passphrase=passphrase))
return None
- install_certificate(name, cert, private_key=private_key, key_type=key_type, key_passphrase=passphrase, is_ca=False)
+ if install:
+ install_certificate(name, cert, private_key=private_key, key_type=key_type, key_passphrase=passphrase, is_ca=False)
+
+ if file:
+ write_file(f'{name}.pem', encode_certificate(cert))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
-def generate_certificate_revocation_list(ca_name, install=False):
+def generate_certificate_revocation_list(ca_name, install=False, file=False):
ca_dict = get_config_ca_certificate(ca_name)
if not ca_dict:
@@ -505,26 +548,35 @@ def generate_certificate_revocation_list(ca_name, install=False):
print("Failed to create CRL")
return None
- if not install:
+ if not install and not file:
print(encode_certificate(crl))
return None
- install_crl(ca_name, crl)
+ if install:
+ install_crl(ca_name, crl)
+
+ if file:
+ write_file(f'{name}.crl', encode_certificate(crl))
-def generate_ssh_keypair(name, install=False):
+def generate_ssh_keypair(name, install=False, file=False):
private_key, key_type = generate_private_key()
public_key = private_key.public_key()
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_public_key(public_key, encoding='OpenSSH', key_format='OpenSSH'))
print("")
print(encode_private_key(private_key, encoding='PEM', key_format='OpenSSH', passphrase=passphrase))
return None
- install_ssh_key(name, public_key, private_key, passphrase)
+ if install:
+ install_ssh_key(name, public_key, private_key, passphrase)
+
+ if file:
+ write_file(f'{name}.pem', encode_public_key(public_key, encoding='OpenSSH', key_format='OpenSSH'))
+ write_file(f'{name}.key', encode_private_key(private_key, encoding='PEM', key_format='OpenSSH', passphrase=passphrase))
-def generate_dh_parameters(name, install=False):
+def generate_dh_parameters(name, install=False, file=False):
bits = ask_input('Enter DH parameters key size:', default=2048, numeric_only=True)
print("Generating parameters...")
@@ -534,49 +586,62 @@ def generate_dh_parameters(name, install=False):
print("Failed to create DH parameters")
return None
- if not install:
+ if not install and not file:
print("DH Parameters:")
print(encode_dh_parameters(dh_params))
- install_dh_parameters(name, dh_params)
+ if install:
+ install_dh_parameters(name, dh_params)
+
+ if file:
+ write_file(f'{name}.pem', encode_dh_parameters(dh_params))
-def generate_keypair(name, install=False):
+def generate_keypair(name, install=False, file=False):
private_key, key_type = generate_private_key()
public_key = private_key.public_key()
passphrase = ask_passphrase()
- if not install:
+ if not install and not file:
print(encode_public_key(public_key))
print("")
print(encode_private_key(private_key, passphrase=passphrase))
return None
- install_keypair(name, key_type, private_key, public_key, passphrase)
+ if install:
+ install_keypair(name, key_type, private_key, public_key, passphrase)
+
+ if file:
+ write_file(f'{name}.pem', encode_public_key(public_key))
+ write_file(f'{name}.key', encode_private_key(private_key, passphrase=passphrase))
-def generate_openvpn_key(name, install=False):
+def generate_openvpn_key(name, install=False, file=False):
result = cmd('openvpn --genkey secret /dev/stdout | grep -o "^[^#]*"')
if not result:
print("Failed to generate OpenVPN key")
return None
- if not install:
+ if not install and not file:
print(result)
return None
- key_lines = result.split("\n")
- key_data = "".join(key_lines[1:-1]) # Remove wrapper tags and line endings
- key_version = '1'
+ if install:
+ key_lines = result.split("\n")
+ key_data = "".join(key_lines[1:-1]) # Remove wrapper tags and line endings
+ key_version = '1'
+
+ version_search = re.search(r'BEGIN OpenVPN Static key V(\d+)', result) # Future-proofing (hopefully)
+ if version_search:
+ key_version = version_search[1]
- version_search = re.search(r'BEGIN OpenVPN Static key V(\d+)', result) # Future-proofing (hopefully)
- if version_search:
- key_version = version_search[1]
+ print("Configure mode commands to install OpenVPN key:")
+ print("set pki openvpn shared-secret %s key '%s'" % (name, key_data))
+ print("set pki openvpn shared-secret %s version '%s'" % (name, key_version))
- print("Configure mode commands to install OpenVPN key:")
- print("set pki openvpn shared-secret %s key '%s'" % (name, key_data))
- print("set pki openvpn shared-secret %s version '%s'" % (name, key_version))
+ if file:
+ write_file(f'{name}.key', result)
-def generate_wireguard_key(name, install=False):
+def generate_wireguard_key(name, install=False, file=False):
private_key = cmd('wg genkey')
public_key = cmd('wg pubkey', input=private_key)
@@ -585,17 +650,26 @@ def generate_wireguard_key(name, install=False):
print("Public key: " + public_key)
return None
- install_wireguard_key(name, private_key, public_key)
+ if install:
+ install_wireguard_key(name, private_key, public_key)
-def generate_wireguard_psk(name, install=False):
+ if file:
+ write_file(f'{name}_public.key', public_key)
+ write_file(f'{name}_private.key', private_key)
+
+def generate_wireguard_psk(name, install=False, file=False):
psk = cmd('wg genpsk')
- if not install:
+ if not install and not file:
print("Pre-shared key:")
print(psk)
return None
- install_wireguard_psk(name, psk)
+ if install:
+ install_wireguard_psk(name, psk)
+
+ if file:
+ write_file(f'{name}.key', psk)
# Show functions
@@ -721,6 +795,7 @@ if __name__ == '__main__':
parser.add_argument('--psk', help='Wireguard pre shared key', required=False)
# Global
+ parser.add_argument('--file', help='Write generated keys into specified filename', action='store_true')
parser.add_argument('--install', help='Install generated keys into running-config', action='store_true')
args = parser.parse_args()
@@ -729,31 +804,31 @@ if __name__ == '__main__':
if args.action == 'generate':
if args.ca:
if args.sign:
- generate_ca_certificate_sign(args.ca, args.sign, args.install)
+ generate_ca_certificate_sign(args.ca, args.sign, install=args.install, file=args.file)
else:
- generate_ca_certificate(args.ca, args.install)
+ generate_ca_certificate(args.ca, install=args.install, file=args.file)
elif args.certificate:
if args.sign:
- generate_certificate_sign(args.certificate, args.sign, args.install)
+ generate_certificate_sign(args.certificate, args.sign, install=args.install, file=args.file)
elif args.self_sign:
- generate_certificate_selfsign(args.certificate, args.install)
+ generate_certificate_selfsign(args.certificate, install=args.install, file=args.file)
else:
generate_certificate_request(name=args.certificate, install=args.install)
elif args.crl:
- generate_certificate_revocation_list(args.crl, args.install)
+ generate_certificate_revocation_list(args.crl, install=args.install, file=args.file)
elif args.ssh:
- generate_ssh_keypair(args.ssh, args.install)
+ generate_ssh_keypair(args.ssh, install=args.install, file=args.file)
elif args.dh:
- generate_dh_parameters(args.dh, args.install)
+ generate_dh_parameters(args.dh, install=args.install, file=args.file)
elif args.keypair:
- generate_keypair(args.keypair, args.install)
+ generate_keypair(args.keypair, install=args.install, file=args.file)
elif args.openvpn:
- generate_openvpn_key(args.openvpn, args.install)
+ generate_openvpn_key(args.openvpn, install=args.install, file=args.file)
elif args.wireguard:
if args.key:
- generate_wireguard_key(args.key, args.install)
+ generate_wireguard_key(args.key, install=args.install, file=args.file)
elif args.psk:
- generate_wireguard_psk(args.psk, args.install)
+ generate_wireguard_psk(args.psk, install=args.install, file=args.file)
elif args.action == 'show':
if args.ca:
show_certificate_authority(None if args.ca == 'all' else args.ca)
diff --git a/src/op_mode/show_dhcp.py b/src/op_mode/show_dhcp.py
index ff1e3cc56..4df275e04 100755
--- a/src/op_mode/show_dhcp.py
+++ b/src/op_mode/show_dhcp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2020 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -27,8 +27,7 @@ from datetime import datetime
from isc_dhcp_leases import Lease, IscDhcpLeases
from vyos.config import Config
-from vyos.util import call
-
+from vyos.util import is_systemd_service_running
lease_file = "/config/dhcpd.leases"
pool_key = "shared-networkname"
@@ -217,7 +216,7 @@ if __name__ == '__main__':
exit(0)
# if dhcp server is down, inactive leases may still be shown as active, so warn the user.
- if call('systemctl -q is-active isc-dhcp-server.service') != 0:
+ if not is_systemd_service_running('isc-dhcp-server.service'):
print("WARNING: DHCP server is configured but not started. Data may be stale.")
if args.leases:
diff --git a/src/op_mode/show_dhcpv6.py b/src/op_mode/show_dhcpv6.py
index f70f04298..1f987ff7b 100755
--- a/src/op_mode/show_dhcpv6.py
+++ b/src/op_mode/show_dhcpv6.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2020 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -27,7 +27,7 @@ from datetime import datetime
from isc_dhcp_leases import Lease, IscDhcpLeases
from vyos.config import Config
-from vyos.util import call
+from vyos.util import is_systemd_service_running
lease_file = "/config/dhcpdv6.leases"
pool_key = "shared-networkname"
@@ -202,7 +202,7 @@ if __name__ == '__main__':
exit(0)
# if dhcp server is down, inactive leases may still be shown as active, so warn the user.
- if call('systemctl -q is-active isc-dhcp-server6.service') != 0:
+ if not is_systemd_service_running('isc-dhcp-server6.service'):
print("WARNING: DHCPv6 server is configured but not started. Data may be stale.")
if args.leases:
diff --git a/src/op_mode/show_vrf.py b/src/op_mode/show_vrf.py
index 94358c6e4..3c7a90205 100755
--- a/src/op_mode/show_vrf.py
+++ b/src/op_mode/show_vrf.py
@@ -20,12 +20,11 @@ from json import loads
from vyos.util import cmd
-vrf_out_tmpl = """
-VRF name state mac address flags interfaces
+vrf_out_tmpl = """VRF name state mac address flags interfaces
-------- ----- ----------- ----- ----------
-{% for v in vrf %}
+{%- for v in vrf %}
{{"%-16s"|format(v.ifname)}} {{ "%-8s"|format(v.operstate | lower())}} {{"%-17s"|format(v.address | lower())}} {{ v.flags|join(',')|lower()}} {{v.members|join(',')|lower()}}
-{% endfor %}
+{%- endfor %}
"""
diff --git a/src/op_mode/wireguard.py b/src/op_mode/wireguard.py
deleted file mode 100755
index e08bc983a..000000000
--- a/src/op_mode/wireguard.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018-2020 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/>.
-
-import argparse
-import os
-import sys
-import shutil
-import syslog as sl
-import re
-
-from vyos.config import Config
-from vyos.ifconfig import WireGuardIf
-from vyos.util import cmd
-from vyos.util import run
-from vyos.util import check_kmod
-from vyos import ConfigError
-
-dir = r'/config/auth/wireguard'
-psk = dir + '/preshared.key'
-
-k_mod = 'wireguard'
-
-def generate_keypair(pk, pub):
- """ generates a keypair which is stored in /config/auth/wireguard """
- old_umask = os.umask(0o027)
- if run(f'wg genkey | tee {pk} | wg pubkey > {pub}') != 0:
- raise ConfigError("wireguard key-pair generation failed")
- else:
- sl.syslog(
- sl.LOG_NOTICE, "new keypair wireguard key generated in " + dir)
- os.umask(old_umask)
-
-
-def genkey(location):
- """ helper function to check, regenerate the keypair """
- pk = "{}/private.key".format(location)
- pub = "{}/public.key".format(location)
- old_umask = os.umask(0o027)
- if os.path.exists(pk) and os.path.exists(pub):
- try:
- choice = input(
- "You already have a wireguard key-pair, do you want to re-generate? [y/n] ")
- if choice == 'y' or choice == 'Y':
- generate_keypair(pk, pub)
- except KeyboardInterrupt:
- sys.exit(0)
- else:
- """ if keypair is bing executed from a running iso """
- if not os.path.exists(location):
- run(f'sudo mkdir -p {location}')
- run(f'sudo chgrp vyattacfg {location}')
- run(f'sudo chmod 750 {location}')
- generate_keypair(pk, pub)
- os.umask(old_umask)
-
-
-def showkey(key):
- """ helper function to show privkey or pubkey """
- if os.path.exists(key):
- print (open(key).read().strip())
- else:
- print ("{} not found".format(key))
-
-
-def genpsk():
- """
- generates a preshared key and shows it on stdout,
- it's stored only in the cli config
- """
-
- psk = cmd('wg genpsk')
- print(psk)
-
-def list_key_dirs():
- """ lists all dirs under /config/auth/wireguard """
- if os.path.exists(dir):
- nks = next(os.walk(dir))[1]
- for nk in nks:
- print (nk)
-
-def del_key_dir(kname):
- """ deletes /config/auth/wireguard/<kname> """
- kdir = "{0}/{1}".format(dir,kname)
- if not os.path.isdir(kdir):
- print ("named keypair {} not found".format(kname))
- return 1
- shutil.rmtree(kdir)
-
-
-if __name__ == '__main__':
- check_kmod(k_mod)
- parser = argparse.ArgumentParser(description='wireguard key management')
- parser.add_argument(
- '--genkey', action="store_true", help='generate key-pair')
- parser.add_argument(
- '--showpub', action="store_true", help='shows public key')
- parser.add_argument(
- '--showpriv', action="store_true", help='shows private key')
- parser.add_argument(
- '--genpsk', action="store_true", help='generates preshared-key')
- parser.add_argument(
- '--location', action="store", help='key location within {}'.format(dir))
- parser.add_argument(
- '--listkdir', action="store_true", help='lists named keydirectories')
- parser.add_argument(
- '--delkdir', action="store_true", help='removes named keydirectories')
- parser.add_argument(
- '--showinterface', action="store", help='shows interface details')
- args = parser.parse_args()
-
- try:
- if args.genkey:
- if args.location:
- genkey("{0}/{1}".format(dir, args.location))
- else:
- genkey("{}/default".format(dir))
- if args.showpub:
- if args.location:
- showkey("{0}/{1}/public.key".format(dir, args.location))
- else:
- showkey("{}/default/public.key".format(dir))
- if args.showpriv:
- if args.location:
- showkey("{0}/{1}/private.key".format(dir, args.location))
- else:
- showkey("{}/default/private.key".format(dir))
- if args.genpsk:
- genpsk()
- if args.listkdir:
- list_key_dirs()
- if args.showinterface:
- try:
- intf = WireGuardIf(args.showinterface, create=False, debug=False)
- print(intf.operational.show_interface())
- # the interface does not exists
- except Exception:
- pass
- if args.delkdir:
- if args.location:
- del_key_dir(args.location)
- else:
- del_key_dir("default")
-
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/op_mode/wireguard_client.py b/src/op_mode/wireguard_client.py
index 7a620a01e..7661254da 100755
--- a/src/op_mode/wireguard_client.py
+++ b/src/op_mode/wireguard_client.py
@@ -38,7 +38,7 @@ To enable this configuration on a VyOS router you can use the following commands
{% for addr in address if address is defined %}
set interfaces wireguard {{ interface }} peer {{ name }} allowed-ips '{{ addr }}'
{% endfor %}
-set interfaces wireguard {{ interface }} peer {{ name }} pubkey '{{ pubkey }}'
+set interfaces wireguard {{ interface }} peer {{ name }} public-key '{{ pubkey }}'
"""
client_config = """