diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/pki.py | 129 | 
1 files changed, 115 insertions, 14 deletions
| diff --git a/src/conf_mode/pki.py b/src/conf_mode/pki.py index efa3578b4..29ed7b1b7 100755 --- a/src/conf_mode/pki.py +++ b/src/conf_mode/pki.py @@ -29,12 +29,60 @@ from vyos.pki import load_private_key  from vyos.pki import load_crl  from vyos.pki import load_dh_parameters  from vyos.util import ask_input +from vyos.util import call +from vyos.util import dict_search_args  from vyos.util import dict_search_recursive  from vyos.xml import defaults  from vyos import ConfigError  from vyos import airbag  airbag.enable() +# keys to recursively search for under specified path, script to call if update required +sync_search = [ +    { +        'keys': ['certificate'], +        'path': ['service', 'https'], +        'script': '/usr/libexec/vyos/conf_mode/https.py' +    }, +    { +        'keys': ['certificate', 'ca_certificate'], +        'path': ['interfaces', 'ethernet'], +        'script': '/usr/libexec/vyos/conf_mode/interfaces-ethernet.py' +    }, +    { +        'keys': ['certificate', 'ca_certificate', 'dh_params', 'shared_secret_key', 'auth_key', 'crypt_key'], +        'path': ['interfaces', 'openvpn'], +        'script': '/usr/libexec/vyos/conf_mode/interfaces-openvpn.py' +    }, +    { +        'keys': ['certificate', 'ca_certificate', 'local_key', 'remote_key'], +        'path': ['vpn', 'ipsec'], +        'script': '/usr/libexec/vyos/conf_mode/vpn_ipsec.py' +    }, +    { +        'keys': ['certificate', 'ca_certificate'], +        'path': ['vpn', 'openconnect'], +        'script': '/usr/libexec/vyos/conf_mode/vpn_openconnect.py' +    }, +    { +        'keys': ['certificate', 'ca_certificate'], +        'path': ['vpn', 'sstp'], +        'script': '/usr/libexec/vyos/conf_mode/vpn_sstp.py' +    } +] + +# key from other config nodes -> key in pki['changed'] and pki +sync_translate = { +    'certificate': 'certificate', +    'ca_certificate': 'ca', +    'dh_params': 'dh', +    'local_key': 'key_pair', +    'remote_key': 'key_pair', +    'shared_secret_key': 'openvpn', +    'auth_key': 'openvpn', +    'crypt_key': 'openvpn' +} +  def get_config(config=None):      if config:          conf = config @@ -47,12 +95,21 @@ def get_config(config=None):                                       no_tag_node_value_mangle=True)      pki['changed'] = {} -    tmp = node_changed(conf, base + ['ca'], key_mangling=('-', '_')) +    tmp = node_changed(conf, base + ['ca'], key_mangling=('-', '_'), recursive=True)      if tmp: pki['changed'].update({'ca' : tmp}) -    tmp = node_changed(conf, base + ['certificate'], key_mangling=('-', '_')) +    tmp = node_changed(conf, base + ['certificate'], key_mangling=('-', '_'), recursive=True)      if tmp: pki['changed'].update({'certificate' : tmp}) +    tmp = node_changed(conf, base + ['dh'], key_mangling=('-', '_'), recursive=True) +    if tmp: pki['changed'].update({'dh' : tmp}) + +    tmp = node_changed(conf, base + ['key-pair'], key_mangling=('-', '_'), recursive=True) +    if tmp: pki['changed'].update({'key_pair' : tmp}) + +    tmp = node_changed(conf, base + ['openvpn', 'shared-secret'], key_mangling=('-', '_'), recursive=True) +    if tmp: pki['changed'].update({'openvpn' : tmp}) +      # We only merge on the defaults of there is a configuration at all      if conf.exists(base):          default_values = defaults(base) @@ -164,17 +221,30 @@ def verify(pki):      if 'changed' in pki:          # if the list is getting longer, we can move to a dict() and also embed the          # search key as value from line 173 or 176 -        for cert_type in ['ca', 'certificate']: -            if not cert_type in pki['changed']: -                continue -            for certificate in pki['changed'][cert_type]: -                if cert_type not in pki or certificate not in pki['changed'][cert_type]: -                    if cert_type == 'ca': -                        if certificate in dict_search_recursive(pki['system'], 'ca_certificate'): -                            raise ConfigError(f'CA certificate "{certificate}" is still in use!') -                    elif cert_type == 'certificate': -                        if certificate in dict_search_recursive(pki['system'], 'certificate'): -                            raise ConfigError(f'Certificate "{certificate}" is still in use!') +        for search in sync_search: +            for key in search['keys']: +                changed_key = sync_translate[key] + +                if changed_key not in pki['changed']: +                    continue + +                for item_name in pki['changed'][changed_key]: +                    node_present = False +                    if changed_key == 'openvpn': +                        node_present = dict_search_args(pki, 'openvpn', 'shared_secret', item_name) +                    else: +                        node_present = dict_search_args(pki, changed_key, item_name) + +                    if not node_present: +                        search_dict = dict_search_args(pki['system'], *search['path']) + +                        if not search_dict: +                            continue + +                        for found_name, found_path in dict_search_recursive(search_dict, key): +                            if found_name == item_name: +                                path_str = " ".join(search['path'] + found_path) +                                raise ConfigError(f'PKI object "{item_name}" still in use by "{path_str}"')      return None @@ -188,7 +258,38 @@ def apply(pki):      if not pki:          return None -    # XXX: restart services if the content of a certificate changes +    if 'changed' in pki: +        for search in sync_search: +            for key in search['keys']: +                changed_key = sync_translate[key] + +                if changed_key not in pki['changed']: +                    continue + +                for item_name in pki['changed'][changed_key]: +                    node_present = False +                    if changed_key == 'openvpn': +                        node_present = dict_search_args(pki, 'openvpn', 'shared_secret', item_name) +                    else: +                        node_present = dict_search_args(pki, changed_key, item_name) + +                    if node_present: +                        search_dict = dict_search_args(pki['system'], *search['path']) + +                        if not search_dict: +                            continue + +                        for found_name, found_path in dict_search_recursive(search_dict, key): +                            if found_name == item_name: +                                path_str = ' '.join(search['path'] + found_path) +                                print(f'pki: Updating config: {path_str} {found_name}') + +                                script = search['script'] +                                if found_path[0] == 'interfaces': +                                    ifname = found_path[2] +                                    call(f'VYOS_TAGNODE_VALUE={ifname} {script}') +                                else: +                                    call(script)      return None | 
