summaryrefslogtreecommitdiff
path: root/src/conf-mode
diff options
context:
space:
mode:
authorYuya Kusakabe <yuya.kusakabe@gmail.com>2018-05-16 21:35:22 +0900
committerYuya Kusakabe <yuya.kusakabe@gmail.com>2018-05-16 21:35:22 +0900
commitbe6f809581ccbcd6411713128a63711eaa2ce6b7 (patch)
treec62377a36c274d878224dc102562fdfbc10e17be /src/conf-mode
parent99a3049c67005bf5e0ba45db264d56d3b57cb792 (diff)
downloadvyos-1x-be6f809581ccbcd6411713128a63711eaa2ce6b7.tar.gz
vyos-1x-be6f809581ccbcd6411713128a63711eaa2ce6b7.zip
Use '_' instead of '-' for python scripts for test
Diffstat (limited to 'src/conf-mode')
-rwxr-xr-xsrc/conf-mode/vyos-config-bcast-relay.py124
-rwxr-xr-xsrc/conf-mode/vyos-config-dns-forwarding.py213
-rwxr-xr-xsrc/conf-mode/vyos-config-host-name.py96
-rw-r--r--src/conf-mode/vyos-config-lldp.py218
-rwxr-xr-xsrc/conf-mode/vyos-config-mdns-repeater.py93
-rwxr-xr-xsrc/conf-mode/vyos-config-ntp.py161
-rwxr-xr-xsrc/conf-mode/vyos-config-ssh.py249
-rwxr-xr-xsrc/conf-mode/vyos-update-crontab.py148
8 files changed, 0 insertions, 1302 deletions
diff --git a/src/conf-mode/vyos-config-bcast-relay.py b/src/conf-mode/vyos-config-bcast-relay.py
deleted file mode 100755
index 785690d9c..000000000
--- a/src/conf-mode/vyos-config-bcast-relay.py
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2017 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 sys
-import os
-import fnmatch
-import time
-import subprocess
-
-from vyos.config import Config
-from vyos import ConfigError
-
-config_file = r'/etc/default/udp-broadcast-relay'
-
-def get_config():
- conf = Config()
- conf.set_level("service broadcast-relay id")
- relay_id = conf.list_nodes("")
- relays = []
-
- for id in relay_id:
- interface_list = []
- address = conf.return_value("{0} address".format(id))
- description = conf.return_value("{0} description".format(id))
- port = conf.return_value("{0} port".format(id))
-
- # split the interface name listing and form a list
- if conf.exists("{0} interface".format(id)):
- intfs_names = []
- intfs_names = conf.return_values("{0} interface".format(id))
-
- for name in intfs_names:
- interface_list.append(name)
-
- relay = {
- "id": id,
- "address": address,
- "description": description,
- "interfaces" : interface_list,
- "port": port
- }
- relays.append(relay)
-
- return relays
-
-def verify(relays):
- for relay in relays:
- if not relay["port"]:
- raise ConfigError("UDP broadcast relay 'id {0}' requires a port number".format(relay["id"]))
-
- if len(relay["interfaces"]) < 2:
- raise ConfigError("UDP broadcast relay 'id {0}' requires at least 2 interfaces".format(relay["id"]))
-
- return None
-
-def generate(relays):
- config_header = '### Autogenerated by {0} on {tm} ###\n'.format(os.path.basename(__file__),
- tm=time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()))
-
- config_dir = os.path.dirname(config_file)
- config_filename = os.path.basename(config_file)
- active_configs = []
-
- for config in fnmatch.filter(os.listdir(config_dir), config_filename + '*'):
- # determine prefix length to identify service instance
- prefix_len = len(config_filename)
- active_configs.append(config[prefix_len:])
-
- # sort our list
- active_configs.sort()
-
- for id in active_configs[:]:
- os.unlink(config_file + id)
-
- for relay in relays:
- file = config_file + str(relay["id"])
- interfaces = ' '.join(str(intf) for intf in relay["interfaces"])
- config_args = 'DAEMON_ARGS="{0} {1}"\n'.format(relay["port"], interfaces)
-
- f = open(file, 'w')
- f.write(config_header)
- if relay["description"]:
- f.write('# ' + relay["description"] + '\n')
- f.write(config_args)
- f.close()
-
- return None
-
-def apply(relays):
- # first stop all running services
- cmd = "sudo systemctl stop udp-broadcast-relay@{1..99}"
- os.system(cmd)
-
- # start only required service instances
- for relay in relays:
- cmd = "sudo systemctl start udp-broadcast-relay@{0}".format(relay["id"])
- os.system(cmd)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-config-dns-forwarding.py b/src/conf-mode/vyos-config-dns-forwarding.py
deleted file mode 100755
index be48cde60..000000000
--- a/src/conf-mode/vyos-config-dns-forwarding.py
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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 sys
-import os
-
-import netifaces
-import jinja2
-
-from vyos.config import Config
-from vyos import ConfigError
-
-config_file = r'/etc/powerdns/recursor.conf'
-
-# XXX: pdns recursor doesn't like whitespace near entry separators,
-# especially in the semicolon-separated lists of name servers.
-# Please be careful if you edit the template.
-config_tmpl = """
-### Autogenerated by vyos-config-dns-forwarding.py ###
-
-# Non-configurable defaults
-daemon=yes
-threads=1
-allow-from=0.0.0.0/0
-log-common-errors=yes
-
-# cache-size
-max-cache-entries={{ cache_size }}
-
-# ignore-hosts-file
-export-etc-hosts={{ export_hosts_file }}
-
-# listen-on
-local-address={{ listen_on | join(',') }}
-
-# domain ... server ...
-{% if domains -%}
-
-forward-zones={% for d in domains %}
-{{ d.name }}={{ d.servers | join(";") }}
-{%- if loop.first %}, {% endif %}
-{% endfor %}
-
-{% endif %}
-
-# name-server
-forward-zones-recurse=.={{ name_servers | join(';') }}
-
-"""
-
-default_config_data = {
- 'cache_size' : 10000,
- 'export_hosts_file': 'yes',
- 'listen_on': [],
- 'interfaces': [],
- 'name_servers': [],
- 'domains': []
-}
-
-
-# borrowed from: https://github.com/donjajo/py-world/blob/master/resolvconfReader.py, THX!
-def get_resolvers(file):
- resolvers = []
- try:
- with open(file, 'r') as resolvconf:
- for line in resolvconf.readlines():
- line = line.split('#',1)[0];
- line = line.rstrip();
- if 'nameserver' in line:
- resolvers.append(line.split()[1])
- return resolvers
- except IOError:
- return []
-
-def get_config():
- dns = default_config_data
- conf = Config()
- if not conf.exists('service dns forwarding'):
- return None
- else:
- conf.set_level('service dns forwarding')
-
- if conf.exists('cache-size'):
- cache_size = conf.return_value('cache-size')
- dns['cache_size'] = cache_size
-
- if conf.exists('domain'):
- for node in conf.list_nodes('domain'):
- server = conf.return_values("domain {0} server".format(node))
- domain = {
- "name": node,
- "servers": server
- }
- dns['domains'].append(domain)
-
- if conf.exists('ignore-hosts-file'):
- dns.setdefault('export_hosts_file', "no")
-
- if conf.exists('name-server'):
- name_servers = conf.return_values('name-server')
- dns['name_servers'] = dns['name_servers'] + name_servers
-
- if conf.exists('system'):
- conf.set_level('system')
- system_name_servers = []
- system_name_servers = conf.return_values('name-server')
- if not system_name_servers:
- print("DNS forwarding warning: No name-servers set under 'system name-server'\n")
- else:
- dns['name_servers'] = dns['name_servers'] + system_name_servers
- conf.set_level('service dns forwarding')
-
- ## Hacks and tricks
-
- # The old VyOS syntax that comes from dnsmasq was "listen-on $interface".
- # pdns wants addresses instead, so we emulate it by looking up all addresses
- # of a given interface and writing them to the config
- if conf.exists('listen-on'):
- interfaces = conf.return_values('listen-on')
-
- listen4 = []
- listen6 = []
- for interface in interfaces:
- addrs = netifaces.ifaddresses(interface)
- for ip4 in addrs[netifaces.AF_INET]:
- listen4.append(ip4['addr'])
-
- for ip6 in addrs[netifaces.AF_INET6]:
- listen6.append(ip6['addr'])
-
- dns['listen_on'] = listen4 + listen6
-
- # Save interfaces in the dict for the reference
- dns['interfaces'] = interfaces
-
- # Add name servers received from DHCP
- if conf.exists('dhcp'):
- interfaces = []
- interfaces = conf.return_values('dhcp')
- for interface in interfaces:
- dhcp_resolvers = get_resolvers("/etc/resolv.conf.dhclient-new-{0}".format(interface))
- if dhcp_resolvers:
- dns['name_servers'] = dns['name_servers'] + dhcp_resolvers
-
- return dns
-
-def verify(dns):
- # bail out early - looks like removal from running config
- if dns is None:
- return None
-
- if not dns['interfaces']:
- raise ConfigError('Error: DNS forwarding requires a configured listen interface!')
-
- for interface in dns['interfaces']:
- try:
- netifaces.ifaddresses(interface)[netifaces.AF_INET]
- except KeyError as e:
- raise ConfigError('Error: Interface {0} has no IP address assigned'.format(interface))
-
- if dns['domains']:
- for domain in dns['domains']:
- if not domain['servers']:
- raise ConfigError('Error: No server configured for domain {0}'.format(domain['name']))
-
- return None
-
-def generate(dns):
- # bail out early - looks like removal from running config
- if dns is None:
- return None
-
- tmpl = jinja2.Template(config_tmpl, trim_blocks=True)
-
- config_text = tmpl.render(dns)
- with open(config_file, 'w') as f:
- f.write(config_text)
- return None
-
-def apply(dns):
- if dns is not None:
- os.system("systemctl restart pdns-recursor")
- else:
- # DNS forwarding is removed in the commit
- os.system("systemctl stop pdns-recursor")
- os.unlink(config_file)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-config-host-name.py b/src/conf-mode/vyos-config-host-name.py
deleted file mode 100755
index 2a245b211..000000000
--- a/src/conf-mode/vyos-config-host-name.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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 os
-import re
-import sys
-import subprocess
-
-from vyos.config import Config
-from vyos.util import ConfigError
-
-hostname_regex = re.compile("^[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]$")
-
-def get_config():
- conf = Config()
-
- hostname = conf.return_value("system host-name")
- domain = conf.return_value("system domain-name")
-
- # No one likes fixups, but we really don't want VyOS fail to boot
- # if hostname is not in the config
- if not hostname:
- hostname = "vyos"
-
- if domain:
- fqdn = "{0}.{1}".format(hostname, domain)
- else:
- fqdn = hostname
-
- return {"hostname": hostname, "domain": domain, "fqdn": fqdn}
-
-def verify(config):
- # 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
-
-
-def generate(config):
- # read the hosts file
- with open('/etc/hosts', 'r') as f:
- hosts = f.read()
-
- # get the current hostname
- old_hostname = subprocess.check_output(['hostname']).decode().strip()
-
- # replace the local host line
- hosts = re.sub(r"(127.0.1.1\s+{0}.*)".format(old_hostname), r"127.0.1.1\t{0} # VyOS entry\n".format(config["fqdn"]), hosts)
-
- with open('/etc/hosts', 'w') as f:
- f.write(hosts)
-
- return None
-
-
-def apply(config):
- os.system("hostnamectl set-hostname {0}".format(config["fqdn"]))
-
- # restart services that use the hostname
- os.system("systemctl restart rsyslog.service")
-
- return None
-
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-config-lldp.py b/src/conf-mode/vyos-config-lldp.py
deleted file mode 100644
index ba7e9cb13..000000000
--- a/src/conf-mode/vyos-config-lldp.py
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2017 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 re
-import sys
-
-from vyos.config import Config
-from vyos.util import ConfigError
-
-
-
-def get_options(config):
- options ={}
- config.set_level('service lldp')
- options['listen_vlan'] = config.exists('listen-vlan')
-
- options["addr"] = config.return_value('management-address')
-
- snmp = config.exists('snmp enable')
- options["snmp"] = snmp
- if snmp:
- config.set_level('')
- options["sys_snmp"] = config.exists('service snmp')
- config.set_level('service lldp')
-
- config.set_level('service lldp legacy-protocols')
- options["cdp"] = config.exists("cdp")
- options["edp"] = config.exists("edp")
- options["fdp"] = config.exists("fdp")
- options["sonmp"] = config.exists("sonmp")
- return options
-
-
-def get_interface_list(config):
- config.set_level('service lldp')
- intfs_names = config.list_nodes('interface')
- if len(intfs_names) < 0:
- return 0
- interface_list = []
- for name in intfs_names:
- config.set_level("service lldp interface {0}".format(name))
- disable = config.exists('disable')
- intf = {
- "name": name,
- "disable": disable
- }
- interface_list.append(intf)
- return interface_list
-
-
-def get_location_intf(config, name):
- path = "service lldp interface {0}".format(name)
- config.set_level(path)
- if config.exists("location"):
- return 0
- config.set_level("{} location".format(path))
- civic_based = {}
- elin = None
- coordinate_based = {}
-
- if config.exists('civic-based'):
- config.set_level("{} location civic-based".format(path))
- cc = config.return_value("country-code")
- civic_based["country_code"] = cc
- civic_based["ca_type"] = []
- ca_types_names = config.list_nodes('ca-type')
- if ca_types_names:
- for ca_types_name in ca_types_names:
- config.set_level("{0} location civic-based ca-type {1}".format(path, ca_types_name))
- ca_val = config.return_value('ca-value')
- ca_type = {
- "name": ca_types_name,
- "ca_val": ca_val
- }
- civic_based["ca_type"].append(ca_type)
-
- elif config.exists("elin"):
- elin = config.return_value("elin")
-
- elif config.exists("coordinate-based"):
- config.set_level("{} location coordinate-based".format(path))
- alt = config.return_value("altitude")
- lat = config.return_value("latitude")
- long = config.return_value("longitude")
- datum = config.return_value("datum")
- coordinate_based["altitude"] = alt
- coordinate_based["latitude"] = lat
- coordinate_based["longitude"] = long
- coordinate_based["datum"] = datum
-
- intf = {
- "name": name,
- "civic_based": civic_based,
- "elin": elin,
- "coordinate_based": coordinate_based
-
- }
- return intf
-
-
-def get_location(config):
- config.set_level('service lldp')
- intfs_names = config.list_nodes('interface')
- if len(intfs_names) < 0:
- return 0
- if config.exists("disable"):
- return 0
- intfs_location = []
- for name in intfs_names:
- intf = get_location_intf(config, name)
- intfs_location.append(intf)
- return intfs_location
-
-
-def get_config():
- conf = Config()
- options = get_options(conf)
- interface_list = get_interface_list(conf)
- location = get_location(conf)
- lldp = {"options": options, "interface_list": interface_list, "location": location}
- return lldp
-
-
-def verify(lldp):
-
- # check location
- for location in lldp["location"]:
-
- # check civic-based
- if len(location["civic_based"]) > 0:
- if len(location["coordinate_based"]) > 0 or location["elin"]:
- raise ConfigError("Can only configure 1 location type for interface {0}".format(location["name"]))
-
- # check country-code
- if not location["civic_based"]["country_code"]:
- raise ConfigError("Invalid location for interface {0}: must configure the country code".format(location["name"]))
-
- if not re.match(r"^[a-zA-Z]{2}$", location["civic_based"]["country_code"]):
- raise ConfigError("Invalid location for interface {0}: country-code must be 2 characters".format(location["name"]))
- # check ca-type
- if len(location["civic_based"]["ca_type"]) < 0:
- raise ConfigError("Invalid location for interface {0}: must define at least 1 ca-type".format(location["name"]))
-
- for ca_type in location["civic_based"]["ca_type"]:
- if not int(ca_type["name"]) in range(0, 129):
- raise ConfigError("Invalid location for interface {0}: ca-type must between 0-128".format(location["name"]))
-
- if not ca_type["ca_val"]:
- raise ConfigError("Invalid location for interface {0}: must configure the ca-value for ca-type {1}".format(location["name"],ca_type["name"]))
-
- # check coordinate-based
- elif len(location["coordinate_based"]) > 0:
- # check longitude and latitude
- if not location["coordinate_based"]["longitude"]:
- raise ConfigError("Must define longitude for interface {0}".format(location["name"]))
-
- if not location["coordinate_based"]["latitude"]:
- raise ConfigError("Must define latitude for interface {0}".format(location["name"]))
-
- if not re.match(r"^(\d+)(\.\d+)?[nNsS]$", location["coordinate_based"]["latitude"]):
- raise ConfigError("Invalid location for interface {0}: latitude should be a number followed by S or N".format(location["name"]))
-
- if not re.match(r"^(\d+)(\.\d+)?[eEwW]$", location["coordinate_based"]["longitude"]):
- raise ConfigError("Invalid location for interface {0}: longitude should be a number followed by E or W".format(location["name"]))
-
- # check altitude and datum if exist
- if location["coordinate_based"]["altitude"]:
- if not re.match(r"^[-+0-9\.]+$", location["coordinate_based"]["altitude"]):
- raise ConfigError("Invalid location for interface {0}: altitude should be a positive or negative number".format(location["name"]))
-
- if location["coordinate_based"]["datum"]:
- if not re.match(r"^(WGS84|NAD83|MLLW)$", location["coordinate_based"]["datum"]):
- raise ConfigError("Invalid location for interface {0}: datum should be WGS84, NAD83, or MLLW".format(location["name"]))
-
- # check elin
- elif len(location["elin"]) > 0:
- if not re.match(r"^[0-9]{10,25}$", location["elin"]):
- raise ConfigError("Invalid location for interface {0}: ELIN number must be between 10-25 numbers".format(location["name"]))
-
- # check options
- if lldp["options"]["snmp"]:
- if not lldp["options"]["sys_snmp"]:
- raise ConfigError("SNMP must be configured to enable LLDP SNMP")
-
-
-def generate(config):
- pass
-
-
-def apply(config):
- pass
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
-
diff --git a/src/conf-mode/vyos-config-mdns-repeater.py b/src/conf-mode/vyos-config-mdns-repeater.py
deleted file mode 100755
index e648fd64f..000000000
--- a/src/conf-mode/vyos-config-mdns-repeater.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2017 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 sys
-import os
-import netifaces
-import time
-
-from vyos.config import Config
-from vyos import ConfigError
-
-config_file = r'/etc/default/mdns-repeater'
-
-def get_config():
- interface_list = []
-
- conf = Config()
- conf.set_level('service mdns repeater')
- if not conf.exists(''):
- return interface_list
-
- if conf.exists('interface'):
- intfs_names = []
- intfs_names = conf.return_values('interface')
-
- for name in intfs_names:
- interface_list.append(name)
-
- return interface_list
-
-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
-
-def generate(mdns):
- config_header = '### Autogenerated by vyos-update-mdns-repeater.py on {tm} ###\n'.format(tm=time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()))
- if len(mdns) > 0:
- config_args = 'DAEMON_ARGS="' + ' '.join(str(e) for e in mdns) + '"\n'
- else:
- config_args = 'DAEMON_ARGS=""\n'
-
- # write new configuration file
- f = open(config_file, 'w')
- f.write(config_header)
- f.write(config_args)
- f.close()
-
- return None
-
-def apply(mdns):
- if len(mdns) == 0:
- cmd = "sudo systemctl stop mdns-repeater"
- else:
- cmd = "sudo systemctl restart mdns-repeater"
-
- os.system(cmd)
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-config-ntp.py b/src/conf-mode/vyos-config-ntp.py
deleted file mode 100755
index 8be12e44e..000000000
--- a/src/conf-mode/vyos-config-ntp.py
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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 sys
-import os
-
-import jinja2
-import ipaddress
-
-from vyos.config import Config
-from vyos import ConfigError
-
-config_file = r'/etc/ntp.conf'
-
-# Please be careful if you edit the template.
-config_tmpl = """
-### Autogenerated by vyos-config-ntp.py ###
-
-#
-# Non-configurable defaults
-#
-driftfile /var/lib/ntp/ntp.drift
-# By default, only allow ntpd to query time sources, ignore any incoming requests
-restrict default ignore
-# Local users have unrestricted access, allowing reconfiguration via ntpdc
-restrict 127.0.0.1
-restrict -6 ::1
-
-
-#
-# Configurable section
-#
-
-{% if servers -%}
-{% for s in servers -%}
-# Server configuration for: {{ s.name }}
-server {{ s.name }} iburst {{ s.options | join(" ") }}
-
-{% endfor -%}
-{% endif %}
-
-{% if allowed_networks -%}
-{% for n in allowed_networks -%}
-# Client configuration for network: {{ n.network }}
-restrict {{ n.address }} mask {{ n.netmask }} nomodify notrap nopeer
-
-{% endfor -%}
-{% endif %}
-
-"""
-
-default_config_data = {
- 'servers': [],
- 'allowed_networks': []
-}
-
-def get_config():
- ntp = default_config_data
- conf = Config()
- if not conf.exists('system ntp'):
- return None
- else:
- conf.set_level('system ntp')
-
- if conf.exists('allow-clients address'):
- networks = conf.return_values('allow-clients address')
- for n in networks:
- addr = ipaddress.ip_network(n)
- net = {
- "network" : n,
- "address" : addr.network_address,
- "netmask" : addr.netmask
- }
-
- ntp['allowed_networks'].append(net)
-
- if conf.exists('server'):
- for node in conf.list_nodes('server'):
- options = []
- server = {
- "name": node,
- "options": []
- }
- if conf.exists('server {0} dynamic'.format(node)):
- options.append('dynamic')
- if conf.exists('server {0} noselect'.format(node)):
- options.append('noselect')
- if conf.exists('server {0} preempt'.format(node)):
- options.append('preempt')
- if conf.exists('server {0} prefer'.format(node)):
- options.append('prefer')
-
- server['options'] = options
- ntp['servers'].append(server)
-
- return ntp
-
-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 = ipaddress.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
-
-def generate(ntp):
- # bail out early - looks like removal from running config
- if ntp is None:
- return None
-
- tmpl = jinja2.Template(config_tmpl)
- config_text = tmpl.render(ntp)
- with open(config_file, 'w') as f:
- f.write(config_text)
-
- return None
-
-def apply(ntp):
- if ntp is not None:
- os.system('sudo /usr/sbin/invoke-rc.d ntp force-reload')
- else:
- # NTP suuport is removed in the commit
- os.system('sudo /usr/sbin/invoke-rc.d ntp stop')
- os.unlink(config_file)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-config-ssh.py b/src/conf-mode/vyos-config-ssh.py
deleted file mode 100755
index a4857bba9..000000000
--- a/src/conf-mode/vyos-config-ssh.py
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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 sys
-import os
-
-import jinja2
-
-from vyos.config import Config
-from vyos import ConfigError
-
-config_file = r'/etc/ssh/sshd_config'
-
-# Please be careful if you edit the template.
-config_tmpl = """
-
-### Autogenerated by vyos-config-ssh.py ###
-
-# Non-configurable defaults
-Protocol 2
-HostKey /etc/ssh/ssh_host_rsa_key
-HostKey /etc/ssh/ssh_host_dsa_key
-HostKey /etc/ssh/ssh_host_ecdsa_key
-HostKey /etc/ssh/ssh_host_ed25519_key
-UsePrivilegeSeparation yes
-KeyRegenerationInterval 3600
-ServerKeyBits 1024
-SyslogFacility AUTH
-LoginGraceTime 120
-StrictModes yes
-RSAAuthentication yes
-PubkeyAuthentication yes
-IgnoreRhosts yes
-RhostsRSAAuthentication no
-HostbasedAuthentication no
-PermitEmptyPasswords no
-ChallengeResponseAuthentication no
-X11Forwarding yes
-X11DisplayOffset 10
-PrintMotd no
-PrintLastLog yes
-TCPKeepAlive yes
-Banner /etc/issue.net
-Subsystem sftp /usr/lib/openssh/sftp-server
-UsePAM yes
-HostKey /etc/ssh/ssh_host_key
-PermitRootLogin no
-
-# Specifies whether sshd should look up the remote host name,
-# and to check that the resolved host name for the remote IP
-# address maps back to the very same IP address.
-UseDNS {{ host_validation }}
-
-# Specifies the port number that sshd listens on. The default is 22.
-# Multiple options of this type are permitted.
-Port {{ port }}
-
-# Gives the verbosity level that is used when logging messages from sshd
-LogLevel {{ log_level }}
-
-# Specifies whether password authentication is allowed
-PasswordAuthentication {{ password_authentication }}
-
-{% if listen_on -%}
-# Specifies the local addresses sshd should listen on
-{% for a in listen_on -%}
-ListenAddress {{ a }}
-{% endfor -%}
-{% endif %}
-
-{% if ciphers -%}
-# Specifies the ciphers allowed. Multiple ciphers must be comma-separated.
-#
-# NOTE: As of now, there is no 'multi' node for 'ciphers', thus we have only one :/
-Ciphers {{ ciphers | join(",") }}
-{% endif %}
-
-{% if mac -%}
-# Specifies the available MAC (message authentication code) algorithms. The MAC
-# algorithm is used for data integrity protection. Multiple algorithms must be
-# comma-separated.
-#
-# NOTE: As of now, there is no 'multi' node for 'mac', thus we have only one :/
-MACs {{ mac | join(",") }}
-{% endif %}
-
-{% if key_exchange -%}
-# Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must
-# be comma-separated.
-#
-# NOTE: As of now, there is no 'multi' node for 'key-exchange', thus we have only one :/
-KexAlgorithms {{ key_exchange | join(",") }}
-{% endif %}
-
-{% if allow_users -%}
-# This keyword can be followed by a list of user name patterns, separated by spaces.
-# If specified, login is allowed only for user names that match one of the patterns.
-# Only user names are valid, a numerical user ID is not recognized.
-AllowUsers {{ allow_users | join(" ") }}
-{% endif %}
-
-{% if allow_groups -%}
-# This keyword can be followed by a list of group name patterns, separated by spaces.
-# If specified, login is allowed only for users whose primary group or supplementary
-# group list matches one of the patterns. Only group names are valid, a numerical group
-# ID is not recognized.
-AllowGroups {{ allow_groups | join(" ") }}
-{% endif %}
-
-{% if deny_users -%}
-# This keyword can be followed by a list of user name patterns, separated by spaces.
-# Login is disallowed for user names that match one of the patterns. Only user names
-# are valid, a numerical user ID is not recognized.
-DenyUsers {{ deny_users | join(" ") }}
-{% endif %}
-
-{% if deny_groups -%}
-# This keyword can be followed by a list of group name patterns, separated by spaces.
-# Login is disallowed for users whose primary group or supplementary group list matches
-# one of the patterns. Only group names are valid, a numerical group ID is not recognized.
-DenyGroups {{ deny_groups | join(" ") }}
-{% endif %}
-"""
-
-default_config_data = {
- 'port' : '22',
- 'log_level': 'INFO',
- 'password_authentication': 'yes',
- 'host_validation': 'yes'
-}
-
-def get_config():
- ssh = default_config_data
- conf = Config()
- if not conf.exists('service ssh'):
- return None
- else:
- conf.set_level('service ssh')
-
- if conf.exists('access-control allow user'):
- allow_users = conf.return_values('access-control allow user')
- ssh.setdefault('allow_users', allow_users)
-
- if conf.exists('access-control allow group'):
- allow_groups = conf.return_values('access-control allow group')
- ssh.setdefault('allow_groups', allow_groups)
-
- if conf.exists('access-control deny user'):
- deny_users = conf.return_values('access-control deny user')
- ssh.setdefault('deny_users', deny_users)
-
- if conf.exists('access-control deny group'):
- deny_groups = conf.return_values('access-control deny group')
- ssh.setdefault('deny_groups', deny_groups)
-
- if conf.exists('ciphers'):
- ciphers = conf.return_values('ciphers')
- ssh.setdefault('ciphers', ciphers)
-
- if conf.exists('disable-host-validation'):
- ssh['host_validation'] = 'no'
-
- if conf.exists('disable-password-authentication'):
- ssh['password_authentication'] = 'no'
-
- if conf.exists('key-exchange'):
- kex = conf.return_values('key-exchange')
- ssh.setdefault('key_exchange', kex)
-
- if conf.exists('listen-address'):
- # We can listen on both IPv4 and IPv6 addresses
- # Maybe there could be a check in the future if the configured IP address
- # is configured on this system at all?
- addresses = conf.return_values('listen-address')
- listen = []
-
- for addr in addresses:
- listen.append(addr)
-
- ssh.setdefault('listen_on', listen)
-
- if conf.exists('loglevel'):
- ssh['log_level'] = conf.return_value('loglevel')
-
- if conf.exists('mac'):
- mac = conf.return_values('mac')
- ssh.setdefault('mac', mac)
-
- if conf.exists('port'):
- port = conf.return_value('port')
- ssh.setdefault('port', port)
-
- return ssh
-
-def verify(ssh):
- if ssh is None:
- return None
-
- if 'loglevel' in ssh.keys():
- allowed_loglevel = 'QUIET, FATAL, ERROR, INFO, VERBOSE'
- if not ssh['loglevel'] in allowed_loglevel:
- raise ConfigError('loglevel must be one of "{0}"\n'.format(allowed_loglevel))
-
- return None
-
-def generate(ssh):
- if ssh is None:
- return None
-
- tmpl = jinja2.Template(config_tmpl)
- config_text = tmpl.render(ssh)
- with open(config_file, 'w') as f:
- f.write(config_text)
- return None
-
-def apply(ssh):
- if ssh is not None and 'port' in ssh.keys():
- os.system("sudo systemctl restart ssh")
- else:
- # SSH access is removed in the commit
- os.system("sudo systemctl stop ssh")
- os.unlink(config_file)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf-mode/vyos-update-crontab.py b/src/conf-mode/vyos-update-crontab.py
deleted file mode 100755
index c19b88007..000000000
--- a/src/conf-mode/vyos-update-crontab.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2017 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 os
-import re
-import sys
-
-from vyos.config import Config
-from vyos import ConfigError
-
-
-crontab_file = "/etc/cron.d/vyos-crontab"
-
-
-def format_task(minute="*", hour="*", day="*", dayofweek="*", month="*", user="root", rawspec=None, command=""):
- fmt_full = "{minute} {hour} {day} {month} {dayofweek} {user} {command}\n"
- fmt_raw = "{spec} {user} {command}\n"
-
- if rawspec is None:
- s = fmt_full.format(minute=minute, hour=hour, day=day,
- dayofweek=dayofweek, month=month, command=command, user=user)
- else:
- s = fmt_raw.format(spec=rawspec, user=user, command=command)
-
- return s
-
-def split_interval(s):
- result = re.search(r"(\d+)([mdh]?)", s)
- value = int(result.group(1))
- suffix = result.group(2)
- return( (value, suffix) )
-
-def make_command(executable, arguments):
- if arguments:
- return("{0} {1}".format(executable, arguments))
- else:
- return(executable)
-
-def get_config():
- conf = Config()
- conf.set_level("system task-scheduler task")
- task_names = conf.list_nodes("")
- tasks = []
-
- for name in task_names:
- interval = conf.return_value("{0} interval".format(name))
- spec = conf.return_value("{0} crontab-spec".format(name))
- executable = conf.return_value("{0} executable path".format(name))
- args = conf.return_value("{0} executable arguments".format(name))
- task = {
- "name": name,
- "interval": interval,
- "spec": spec,
- "executable": executable,
- "args": args
- }
- tasks.append(task)
-
- return tasks
-
-def verify(tasks):
- for task in tasks:
- if not task["interval"] and not task["spec"]:
- raise ConfigError("Invalid task {0}: must define either interval or crontab-spec".format(task["name"]))
-
- if task["interval"]:
- if task["spec"]:
- raise ConfigError("Invalid task {0}: cannot use interval and crontab-spec at the same time".format(task["name"]))
-
- if not re.match(r"^\d+[mdh]?$", task["interval"]):
- raise(ConfigError("Invalid interval {0} in task {1}: interval should be a number optionally followed by m, h, or d".format(task["name"], task["interval"])))
- else:
- # Check if values are within allowed range
- value, suffix = split_interval(task["interval"])
-
- if not suffix or suffix == "m":
- if value > 60:
- raise ConfigError("Invalid task {0}: interval in minutes must not exceed 60".format(task["name"]))
- elif suffix == "h":
- if value > 24:
- raise ConfigError("Invalid task {0}: interval in hours must not exceed 24".format(task["name"]))
- elif suffix == "d":
- if value > 31:
- raise ConfigError("Invalid task {0}: interval in days must not exceed 31".format(task["name"]))
-
- if not task["executable"]:
- raise ConfigError("Invalid task {0}: executable is not defined".format(task["name"]))
- else:
- # Check if executable exists and is executable
- if not (os.path.isfile(task["executable"]) and os.access(task["executable"], os.X_OK)):
- raise ConfigError("Invalid task {0}: file {1} does not exist or is not executable".format(task["name"], task["executable"]))
-
-def generate(tasks):
- crontab_header = "### Generated by vyos-update-crontab.py ###\n"
- if len(tasks) == 0:
- if os.path.exists(crontab_file):
- os.remove(crontab_file)
- else:
- pass
- else:
- crontab_lines = []
- for task in tasks:
- command = make_command(task["executable"], task["args"])
- if task["spec"]:
- line = format_task(command=command, rawspec=task["spec"])
- else:
- value, suffix = split_interval(task["interval"])
- if not suffix or suffix == "m":
- line = format_task(command=command, minute="*/{0}".format(value))
- elif suffix == "h":
- line = format_task(command=command, minute="0", hour="*/{0}".format(value))
- elif suffix == "d":
- line = format_task(command=command, minute="0", hour="0", day="*/{0}".format(value))
- crontab_lines.append(line)
-
- with open(crontab_file, 'w') as f:
- f.write(crontab_header)
- f.writelines(crontab_lines)
-
-def apply(config):
- # No daemon restarts etc. needed for cron
- pass
-
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)