From cf1f11c5336801784cc5f3ce7112318bcf60d4e5 Mon Sep 17 00:00:00 2001
From: Viacheslav Hletenko <v.gletenko@vyos.io>
Date: Tue, 2 Jul 2024 05:22:59 +0000
Subject: T6486: T6379: Rewrite generate openvpn client-config

This command helps to generate users `.ovpn` files
Rewrite `generate openvpn client-config` to use Config()
It needs to get the default values as `ConfigTreeQuery` is
not supporting default values.

Fixed "ignores configured protocol type" if TCP is used
Fixed lzo, was used even if lzo not configured
Fixed encryption is not parse the dict

(cherry picked from commit fe50f1a9292b34e168b35453f2cfc2aee2ca4843)
---
 src/op_mode/generate_ovpn_client_file.py | 113 +++++++++++++++++--------------
 1 file changed, 64 insertions(+), 49 deletions(-)

(limited to 'src')

diff --git a/src/op_mode/generate_ovpn_client_file.py b/src/op_mode/generate_ovpn_client_file.py
index 2d96fe217..974f7d9b6 100755
--- a/src/op_mode/generate_ovpn_client_file.py
+++ b/src/op_mode/generate_ovpn_client_file.py
@@ -19,42 +19,53 @@ import argparse
 from jinja2 import Template
 from textwrap import fill
 
-from vyos.configquery import ConfigTreeQuery
+from vyos.config import Config
 from vyos.ifconfig import Section
 
 client_config = """
 
 client
 nobind
-remote {{ remote_host }} {{ port }}
+remote {{ local_host if local_host else 'x.x.x.x' }} {{ port }}
 remote-cert-tls server
-proto {{ 'tcp-client' if protocol == 'tcp-active' else 'udp' }}
-dev {{ device }}
-dev-type {{ device }}
+proto {{ 'tcp-client' if protocol == 'tcp-passive' else 'udp' }}
+dev {{ device_type }}
+dev-type {{ device_type }}
 persist-key
 persist-tun
 verb 3
 
 # Encryption options
+{# Define the encryption map #}
+{% set encryption_map = {
+    'des': 'DES-CBC',
+    '3des': 'DES-EDE3-CBC',
+    'bf128': 'BF-CBC',
+    'bf256': 'BF-CBC',
+    'aes128gcm': 'AES-128-GCM',
+    'aes128': 'AES-128-CBC',
+    'aes192gcm': 'AES-192-GCM',
+    'aes192': 'AES-192-CBC',
+    'aes256gcm': 'AES-256-GCM',
+    'aes256': 'AES-256-CBC'
+} %}
+
 {% if encryption is defined and encryption is not none %}
-{%   if encryption.cipher is defined and encryption.cipher is not none %}
-cipher {{ encryption.cipher }}
-{%     if encryption.cipher == 'bf128' %}
-keysize 128
-{%     elif encryption.cipher == 'bf256' %}
-keysize 256
+{%     if encryption.ncp_ciphers is defined and encryption.ncp_ciphers is not none %}
+cipher {% for algo in encryption.ncp_ciphers %}
+{{ encryption_map[algo] if algo in encryption_map.keys() else algo }}{% if not loop.last %}:{% endif %}
+{%      endfor %}
+
+data-ciphers {% for algo in encryption.ncp_ciphers %}
+{{ encryption_map[algo] if algo in encryption_map.keys() else algo }}{% if not loop.last %}:{% endif %}
+{%      endfor %}
 {%     endif %}
-{%   endif %}
-{%   if encryption.ncp_ciphers is defined and encryption.ncp_ciphers is not none %}
-data-ciphers {{ encryption.ncp_ciphers }}
-{%   endif %}
 {% endif %}
 
 {% if hash is defined and hash is not none %}
 auth {{ hash }}
 {% endif %}
-keysize 256
-comp-lzo {{ '' if use_lzo_compression is defined else 'no' }}
+{{ 'comp-lzo' if use_lzo_compression is defined else '' }}
 
 <ca>
 -----BEGIN CERTIFICATE-----
@@ -79,7 +90,7 @@ comp-lzo {{ '' if use_lzo_compression is defined else 'no' }}
 
 """
 
-config = ConfigTreeQuery()
+config = Config()
 base = ['interfaces', 'openvpn']
 
 if not config.exists(base):
@@ -89,10 +100,22 @@ if not config.exists(base):
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser()
-    parser.add_argument("-i", "--interface", type=str, help='OpenVPN interface the client is connecting to', required=True)
-    parser.add_argument("-a", "--ca", type=str, help='OpenVPN CA cerificate', required=True)
-    parser.add_argument("-c", "--cert", type=str, help='OpenVPN client cerificate', required=True)
-    parser.add_argument("-k", "--key", type=str, help='OpenVPN client cerificate key', action="store")
+    parser.add_argument(
+        "-i",
+        "--interface",
+        type=str,
+        help='OpenVPN interface the client is connecting to',
+        required=True,
+    )
+    parser.add_argument(
+        "-a", "--ca", type=str, help='OpenVPN CA cerificate', required=True
+    )
+    parser.add_argument(
+        "-c", "--cert", type=str, help='OpenVPN client cerificate', required=True
+    )
+    parser.add_argument(
+        "-k", "--key", type=str, help='OpenVPN client cerificate key', action="store"
+    )
     args = parser.parse_args()
 
     interface = args.interface
@@ -114,33 +137,25 @@ if __name__ == '__main__':
     if not config.exists(['pki', 'certificate', cert, 'private', 'key']):
         exit(f'OpenVPN certificate key "{key}" does not exist!')
 
-    ca = config.value(['pki', 'ca', ca, 'certificate'])
+    config = config.get_config_dict(
+        base + [interface],
+        key_mangling=('-', '_'),
+        get_first_key=True,
+        with_recursive_defaults=True,
+        with_pki=True,
+    )
+
+    ca = config['pki']['ca'][ca]['certificate']
     ca = fill(ca, width=64)
-    cert = config.value(['pki', 'certificate', cert, 'certificate'])
+    cert = config['pki']['certificate'][cert]['certificate']
     cert = fill(cert, width=64)
-    key = config.value(['pki', 'certificate', key, 'private', 'key'])
+    key = config['pki']['certificate'][key]['private']['key']
     key = fill(key, width=64)
-    remote_host = config.value(base + [interface, 'local-host'])
-
-    ovpn_conf = config.get_config_dict(base + [interface], key_mangling=('-', '_'), get_first_key=True)
-
-    port = '1194' if 'local_port' not in ovpn_conf else ovpn_conf['local_port']
-    proto = 'udp' if 'protocol' not in ovpn_conf else ovpn_conf['protocol']
-    device = 'tun' if 'device_type' not in ovpn_conf else ovpn_conf['device_type']
-
-    config = {
-        'interface'   : interface,
-        'ca'          : ca,
-        'cert'        : cert,
-        'key'         : key,
-        'device'      : device,
-        'port'        : port,
-        'proto'       : proto,
-        'remote_host' : remote_host,
-        'address'     : [],
-    }
-
-# Clear out terminal first
-print('\x1b[2J\x1b[H')
-client = Template(client_config, trim_blocks=True).render(config)
-print(client)
+
+    config['ca'] = ca
+    config['cert'] = cert
+    config['key'] = key
+    config['port'] = '1194' if 'local_port' not in config else config['local_port']
+
+    client = Template(client_config, trim_blocks=True).render(config)
+    print(client)
-- 
cgit v1.2.3