Esempio n. 1
0
def verify(login):
    cur_user = os.environ['SUDO_USER']
    if cur_user in login['del_users']:
        raise ConfigError(
            'Attempting to delete current user: {}'.format(cur_user))

    for user in login['add_users']:
        for key in user['public_keys']:
            if not key['type']:
                raise ConfigError(
                    'SSH public key type missing for "{}"!'.format(
                        key['name']))

            if not key['key']:
                raise ConfigError('SSH public key for id "{}" missing!'.format(
                    key['name']))

    # At lease one RADIUS server must not be disabled
    if len(login['radius_server']) > 0:
        fail = True
        for server in login['radius_server']:
            if not server['disabled']:
                fail = False
        if fail:
            raise ConfigError('At least one RADIUS server must be active.')

    return None
Esempio n. 2
0
def verify(igmp_proxy):
    # bail out early - looks like removal from running config
    if igmp_proxy is None:
        return None

    # bail out early - service is disabled
    if igmp_proxy['disable']:
        return None

    # at least two interfaces are required, one upstream and one downstream
    if len(igmp_proxy['interfaces']) < 2:
        raise ConfigError(
            'Must define an upstream and at least 1 downstream interface!')

    upstream = 0
    for interface in igmp_proxy['interfaces']:
        if interface['name'] not in interfaces():
            raise ConfigError('Interface "{}" does not exist'.format(
                interface['name']))
        if "upstream" == interface['role']:
            upstream += 1

    if upstream == 0:
        raise ConfigError('At least 1 upstream interface is required!')
    elif upstream > 1:
        raise ConfigError('Only 1 upstream interface allowed!')

    return None
def verify(pppoe):
    if not pppoe:
        return None

    # vertify auth settings
    if pppoe['auth_mode'] == 'local':
        if not pppoe['local_users']:
            raise ConfigError(
                'PPPoE local auth mode requires local users to be configured!')

        for user in pppoe['local_users']:
            username = user['name']
            if not user['password']:
                raise ConfigError(
                    f'Password required for local user "{username}"')

            # if up/download is set, check that both have a value
            if user['upload'] and not user['download']:
                raise ConfigError(
                    f'Download speed value required for local user "{username}"'
                )

            if user['download'] and not user['upload']:
                raise ConfigError(
                    f'Upload speed value required for local user "{username}"')

    elif pppoe['auth_mode'] == 'radius':
        if len(pppoe['radius_server']) == 0:
            raise ConfigError(
                'RADIUS authentication requires at least one server')

        for radius in pppoe['radius_server']:
            if not radius['key']:
                server = radius['server']
                raise ConfigError(
                    f'Missing RADIUS secret key for server "{ server }"')

    if len(pppoe['wins']) > 2:
        raise ConfigError(
            'Not more then two IPv4 WINS name-servers can be configured')

    if len(pppoe['dnsv4']) > 2:
        raise ConfigError(
            'Not more then two IPv4 DNS name-servers can be configured')

    if len(pppoe['dnsv6']) > 3:
        raise ConfigError(
            'Not more then three IPv6 DNS name-servers can be configured')

    # local ippool and gateway settings config checks
    if pppoe['client_ip_subnets'] or pppoe['client_ip_pool']:
        if not pppoe['ppp_gw']:
            raise ConfigError(
                'PPPoE server requires local IP to be configured')

    if pppoe['ppp_gw'] and not pppoe['client_ip_subnets'] and not pppoe[
            'client_ip_pool']:
        print("Warning: No PPPoE client pool defined")

    return None
Esempio n. 4
0
def verify(pim):
    if pim is None:
        return None

    if pim['pim_conf']:
        # Check interfaces
        if not pim['pim']['ifaces']:
            raise ConfigError(f"PIM require defined interfaces!")

        if not pim['pim']['rp']:
            raise ConfigError(f"RP address required")

        # Check unique multicast groups
        uniq_groups = []
        for rp_addr in pim['pim']['rp']:
            if not pim['pim']['rp'][rp_addr]:
                raise ConfigError(f"Group should be specified for RP " +
                                  rp_addr)
            for group in pim['pim']['rp'][rp_addr]:
                if (group in uniq_groups):
                    raise ConfigError(f"Group range " + group +
                                      " specified cannot exact match another")

                # Check, is this multicast group
                gr_addr = group.split('/')
                if IPv4Address(gr_addr[0]) < IPv4Address('224.0.0.0'):
                    raise ConfigError(group + " not a multicast group")

            uniq_groups.extend(pim['pim']['rp'][rp_addr])
Esempio n. 5
0
def verify(vrf_config):
    # ensure VRF is not assigned to any interface
    for vrf in vrf_config['vrf_remove']:
        if len(vrf['interfaces']) > 0:
            raise ConfigError(
                f"VRF {vrf['name']} can not be deleted. It has active member interfaces!"
            )

        if len(vrf['routes']) > 0:
            raise ConfigError(
                f"VRF {vrf['name']} can not be deleted. It has active routing protocols!"
            )

    table_ids = []
    for vrf in vrf_config['vrf_add']:
        # table id is mandatory
        if not vrf['table']:
            raise ConfigError(f"VRF {vrf['name']} table id is mandatory!")

        # routing table id can't be changed - OS restriction
        if vrf['table_mod']:
            raise ConfigError(
                f"VRF {vrf['name']} table id modification is not possible!")

        # VRf routing table ID must be unique on the system
        if vrf['table'] in table_ids:
            raise ConfigError(
                f"VRF {vrf['name']} table id {vrf['table']} is not unique!")

        table_ids.append(vrf['table'])

    return None
Esempio n. 6
0
def verify(dummy):
    if dummy['deleted']:
        if dummy['is_bridge_member']:
            raise ConfigError(
                (f'Interface "{dummy["intf"]}" cannot be deleted as it is a '
                 f'member of bridge "{dummy["is_bridge_member"]}"!'))

        return None

    if dummy['vrf']:
        if dummy['vrf'] not in interfaces():
            raise ConfigError(f'VRF "{dummy["vrf"]}" does not exist')

        if dummy['is_bridge_member']:
            raise ConfigError(
                (f'Interface "{dummy["intf"]}" cannot be member of VRF '
                 f'"{dummy["vrf"]}" and bridge "{dummy["is_bridge_member"]}" '
                 f'at the same time!'))

    if dummy['is_bridge_member'] and dummy['address']:
        raise ConfigError(
            (f'Cannot assign address to interface "{dummy["intf"]}" '
             f'as it is a member of bridge "{dummy["is_bridge_member"]}"!'))

    return None
Esempio n. 7
0
def verify(relay):
    if relay is None:
        return None

    if relay['disabled']:
        return None

    for r in relay['instances']:
        # we don't have to check this instance when it's disabled
        if r['disabled']:
            continue

        # we certainly require a UDP port to listen to
        if not r['port']:
            raise ConfigError(
                'UDP broadcast relay "{0}" requires a port number'.format(
                    r['id']))

        # Relaying data without two interface is kinda senseless ...
        if len(r['interfaces']) < 2:
            raise ConfigError(
                'UDP broadcast relay "id {0}" requires at least 2 interfaces'.
                format(r['id']))

    return None
Esempio n. 8
0
def verify(c):
    if not c:
        return None
    if not c['url'] or not c['port']:
        raise ConfigError("proxy url and port requires a value")
    elif c['usr'] and not c['passwd']:
        raise ConfigError("proxy password requires a value")
    elif not c['usr'] and c['passwd']:
        raise ConfigError("proxy username requires a value")
Esempio n. 9
0
def verify(cert):
    if cert is None:
        return None

    if 'domains' not in cert:
        raise ConfigError("At least one domain name is required to"
                          " request a letsencrypt certificate.")

    if 'email' not in cert:
        raise ConfigError("An email address is required to request"
                          " a letsencrypt certificate.")
Esempio n. 10
0
def check_cert_file_store(cert_name, file_path, dts_path):
    if not re.search('^\/config\/.+', file_path):
        print("Warning: \"" + file_path + "\" lies outside of /config/auth directory. It will not get preserved during image upgrade.")
    #Checking file existence
    if not os.path.isfile(file_path):
      raise ConfigError("L2TP VPN configuration error: Invalid "+cert_name+" \""+file_path+"\"")
    else:
      ### Cpy file to /etc/ipsec.d/certs/ /etc/ipsec.d/cacerts/
      # todo make check
      ret = call('cp -f '+file_path+' '+dts_path)
      if ret:
         raise ConfigError("L2TP VPN configuration error: Cannot copy "+file_path)
Esempio n. 11
0
def verify(l2tp):
    if not l2tp:
        return None

    if l2tp['auth_mode'] == 'local':
        if not l2tp['local_users']:
            raise ConfigError(
                'L2TP local auth mode requires local users to be configured!')

        for user in l2tp['local_users']:
            if not user['password']:
                raise ConfigError(f"Password required for user {user['name']}")

    elif l2tp['auth_mode'] == 'radius':
        if len(l2tp['radius_server']) == 0:
            raise ConfigError(
                "RADIUS authentication requires at least one server")

        for radius in l2tp['radius_server']:
            if not radius['key']:
                raise ConfigError(
                    f"Missing RADIUS secret for server { radius['key'] }")

    # check for the existence of a client ip pool
    if not (l2tp['client_ip_pool'] or l2tp['client_ip_subnets']):
        raise ConfigError(
            "set vpn l2tp remote-access client-ip-pool requires subnet or start/stop IP pool"
        )

    # check ipv6
    if l2tp['client_ipv6_delegate_prefix'] and not l2tp['client_ipv6_pool']:
        raise ConfigError(
            'IPv6 prefix delegation requires client-ipv6-pool prefix')

    for prefix in l2tp['client_ipv6_delegate_prefix']:
        if not prefix['mask']:
            raise ConfigError(
                'Delegation-prefix required for individual delegated networks')

    if len(l2tp['wins']) > 2:
        raise ConfigError(
            'Not more then two IPv4 WINS name-servers can be configured')

    if len(l2tp['dnsv4']) > 2:
        raise ConfigError(
            'Not more then two IPv4 DNS name-servers can be configured')

    if len(l2tp['dnsv6']) > 3:
        raise ConfigError(
            'Not more then three IPv6 DNS name-servers can be configured')

    return None
Esempio n. 12
0
def verify(relay):
    # bail out early - looks like removal from running config
    if relay is None:
        return None

    if 'lo' in relay['interface']:
        raise ConfigError('DHCP relay does not support the loopback interface.')

    if len(relay['server']) == 0:
        raise ConfigError('No DHCP relay server(s) configured.\n' \
                          'At least one DHCP relay server required.')

    return None
Esempio n. 13
0
def verify(igmp):
    if igmp is None:
        return None

    if igmp['igmp_conf']:
        # Check interfaces
        if not igmp['ifaces']:
            raise ConfigError(f"IGMP require defined interfaces!")
        # Check, is this multicast group
        for intfc in igmp['ifaces']:
            for gr_addr in igmp['ifaces'][intfc]['gr_join']:
                if IPv4Address(gr_addr) < IPv4Address('224.0.0.0'):
                    raise ConfigError(gr_addr + " not a multicast group")
Esempio n. 14
0
def verify(config):
    """Verify configuration"""
    # check for invalid host

    # pattern $VAR(@) "^[[:alnum:]][-.[:alnum:]]*[[:alnum:]]$" ; "invalid host name $VAR(@)"
    if not hostname_regex.match(config["hostname"]):
        raise ConfigError('Invalid host name ' + config["hostname"])

    # pattern $VAR(@) "^.{1,63}$" ; "invalid host-name length"
    length = len(config["hostname"])
    if length < 1 or length > 63:
        raise ConfigError(
            'Invalid host-name length, must be less than 63 characters')

    return None
Esempio n. 15
0
def verify(nat):
    if nat['deleted']:
        # no need to verify the CLI as NAT is going to be deactivated
        return None

    if nat['helper_functions']:
        if not (nat['pre_ct_ignore'] or nat['pre_ct_conntrack']
                or nat['out_ct_ignore'] or nat['out_ct_conntrack']):
            raise Exception('could not determine nftable ruleset handlers')

    for rule in nat['source']:
        interface = rule['interface_out']
        err_msg = f"Source NAT configuration error in rule {rule['number']}:"

        if interface and interface not in interfaces():
            print(
                f'NAT configuration warning: interface {interface} does not exist on this system'
            )

        if not rule['interface_out']:
            raise ConfigError(f'{err_msg} outbound-interface not specified')

        if rule['translation_address']:
            addr = rule['translation_address']
            if addr != 'masquerade' and not is_addr_assigned(addr):
                print(
                    f'Warning: IP address {addr} does not exist on the system!'
                )

        # common rule verification
        verify_rule(rule, err_msg)

    for rule in nat['destination']:
        interface = rule['interface_in']
        err_msg = f"Destination NAT configuration error in rule {rule['number']}:"

        if interface and interface not in interfaces():
            print(
                f'NAT configuration warning: interface {interface} does not exist on this system'
            )

        if not rule['interface_in']:
            raise ConfigError(f'{err_msg} inbound-interface not specified')

        # common rule verification
        verify_rule(rule, err_msg)

    return None
Esempio n. 16
0
def check_kmod():
    """ check if kmod is loaded, if not load it """
    if not os.path.exists('/sys/module/wireguard'):
        sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod")
        if run('sudo modprobe wireguard') != 0:
            sl.syslog(sl.LOG_ERR, "modprobe wireguard failed")
            raise ConfigError("modprobe wireguard failed")
Esempio n. 17
0
def verify(dummy):
    if dummy['deleted']:
        interface = dummy['intf']
        is_member, bridge = is_bridge_member(interface)
        if is_member:
            # can not use a f'' formatted-string here as bridge would not get
            # expanded in the print statement
            raise ConfigError('Can not delete interface "{0}" as it ' \
                              'is a member of bridge "{1}"!'.format(interface, bridge))
        return None

    vrf_name = dummy['vrf']
    if vrf_name and vrf_name not in interfaces():
        raise ConfigError(f'VRF "{vrf_name}" does not exist')

    return None
Esempio n. 18
0
def get_config():
    loopback = deepcopy(default_config_data)
    conf = Config()

    # determine tagNode instance
    if 'VYOS_TAGNODE_VALUE' not in os.environ:
        raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified')

    loopback['intf'] = os.environ['VYOS_TAGNODE_VALUE']

    # Check if interface has been removed
    if not conf.exists('interfaces loopback ' + loopback['intf']):
        loopback['deleted'] = True

    # set new configuration level
    conf.set_level('interfaces loopback ' + loopback['intf'])

    # retrieve configured interface addresses
    if conf.exists('address'):
        loopback['address'] = conf.return_values('address')

    # retrieve interface description
    if conf.exists('description'):
        loopback['description'] = conf.return_value('description')

    # Determine interface addresses (currently effective) - to determine which
    # address is no longer valid and needs to be removed from the interface
    eff_addr = conf.return_effective_values('address')
    act_addr = conf.return_values('address')
    loopback['address_remove'] = list_diff(eff_addr, act_addr)

    return loopback
Esempio n. 19
0
def _check_kmod():
    """ load required Kernel modules """
    modules = ['nft_nat', 'nft_chain_nat_ipv4']
    for module in modules:
        if not os.path.exists(f'/sys/module/{module}'):
            if call(f'modprobe {module}') != 0:
                raise ConfigError(f'Loading Kernel module {module} failed')
Esempio n. 20
0
def get_ethertype(ethertype_val):
    if ethertype_val == '0x88A8':
        return '802.1ad'
    elif ethertype_val == '0x8100':
        return '802.1q'
    else:
        raise ConfigError('invalid ethertype "{}"'.format(ethertype_val))
Esempio n. 21
0
    def _create(self):
        cmdline = set()
        if self.config['remote']:
            cmdline = ('ifname', 'type', 'remote', 'src_interface', 'vni',
                       'port')

        elif self.config['src_address']:
            cmdline = ('ifname', 'type', 'src_address', 'vni', 'port')

        elif self.config['group'] and self.config['src_interface']:
            cmdline = ('ifname', 'type', 'group', 'src_interface', 'vni',
                       'port')

        else:
            ifname = self.config['ifname']
            raise ConfigError(
                f'VXLAN "{ifname}" is missing mandatory underlay interface for a multicast network.'
            )

        cmd = 'ip link'
        for key in cmdline:
            value = self.config.get(key, '')
            if not value:
                continue
            cmd += ' {} {}'.format(self.mapping.get(key, key), value)

        self._cmd(cmd)
Esempio n. 22
0
def apply(data):
    vrrp_groups, sync_groups = data
    if vrrp_groups:
        # safely rename a temporary file with configuration dict
        try:
            dict_file = Path("{}.temp".format(VRRP.location['vyos']))
            dict_file.rename(Path(VRRP.location['vyos']))
        except Exception as err:
            print("Unable to rename the file with keepalived config for FIFO pipe: {}".format(err))

        if not VRRP.is_running():
            print("Starting the VRRP process")
            ret = call("systemctl restart keepalived.service")
        else:
            print("Reloading the VRRP process")
            ret = call("systemctl reload keepalived.service")

        if ret != 0:
            raise ConfigError("keepalived failed to start")
    else:
        # VRRP is removed in the commit
        print("Stopping the VRRP process")
        call("systemctl stop keepalived.service")
        os.unlink(VRRP.location['daemon'])

    return None
Esempio n. 23
0
def verify(mpls):
    if mpls is None:
        return None

    if mpls['mpls_ldp']:
        # Requre router-id
        if not mpls['router_id']:
            raise ConfigError(f"MPLS ldp router-id is mandatory!")

        # Requre discovery transport-address
        if not mpls['ldp']['d_transp_ipv4'] and not mpls['ldp']['d_transp_ipv6']:
            raise ConfigError(f"MPLS ldp discovery transport address is mandatory!")

        # Requre interface
        if not mpls['ldp']['interfaces']:
            raise ConfigError(f"MPLS ldp interface is mandatory!")
Esempio n. 24
0
def verify(tftpd):
    # bail out early - looks like removal from running config
    if tftpd is None:
        return None

    # Configuring allowed clients without a server makes no sense
    if not tftpd['directory']:
        raise ConfigError('TFTP root directory must be configured!')

    if not tftpd['listen']:
        raise ConfigError('TFTP server listen address must be configured!')

    for addr in tftpd['listen']:
        if not is_addr_assigned(addr):
            print('WARNING: TFTP server listen address {0} not assigned to any interface!'.format(addr))

    return None
def verify(mroute):
    if mroute is None:
        return None

    for route in mroute['mroute']:
        route = route.split('/')
        if IPv4Address(route[0]) < IPv4Address('224.0.0.0'):
            raise ConfigError(route + " not a multicast network")
Esempio n. 26
0
def verify(mdns):
    # '0' interfaces are possible, think of service deletion. Only '1' is not supported!
    if len(mdns) == 1:
        raise ConfigError(
            'At least 2 interfaces must be specified but %d given!' %
            len(mdns))

    # For mdns-repeater to work it is essential that the interfaces
    # have an IP address assigned
    for intf in mdns:
        try:
            netifaces.ifaddresses(intf)[netifaces.AF_INET]
        except KeyError as e:
            raise ConfigError('No IP address configured for interface "%s"!' %
                              intf)

    return None
Esempio n. 27
0
def verify_rule(rule, err_msg):
    """ Common verify steps used for both source and destination NAT """
    if rule['translation_port'] or rule['dest_port'] or rule['source_port']:
        if rule['protocol'] not in ['tcp', 'udp', 'tcp_udp']:
            proto = rule['protocol']
            raise ConfigError(
                f'{err_msg} ports can only be specified when protocol is "tcp", "udp" or "tcp_udp" (currently "{proto}")'
            )

        if '/' in rule['translation_address']:
            raise ConfigError(f'{err_msg}\n' \
                             'Cannot use ports with an IPv4net type translation address as it\n' \
                             'statically maps a whole network of addresses onto another\n' \
                             'network of addresses')

    if not rule['translation_address']:
        raise ConfigError(f'{err_msg} translation address not specified')
Esempio n. 28
0
def verify(regdom):
    if regdom['deleted']:
        return None

    if not regdom['regdom']:
        raise ConfigError("Wireless regulatory domain is mandatory.")

    return None
Esempio n. 29
0
def verify(ntp):
    # bail out early - looks like removal from running config
    if ntp is None:
        return None

    # Configuring allowed clients without a server makes no sense
    if len(ntp['allowed_networks']) and not len(ntp['servers']):
        raise ConfigError('NTP server not configured')

    for n in ntp['allowed_networks']:
        try:
            addr = ip_network( n['network'] )
            break
        except ValueError:
            raise ConfigError("{0} does not appear to be a valid IPv4 or IPv6 network, check host bits!".format(n['network']))

    return None
Esempio n. 30
0
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)