summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/config/cc_vyos.py62
1 files changed, 39 insertions, 23 deletions
diff --git a/cloudinit/config/cc_vyos.py b/cloudinit/config/cc_vyos.py
index e51ed7f2..6a1991d5 100644
--- a/cloudinit/config/cc_vyos.py
+++ b/cloudinit/config/cc_vyos.py
@@ -22,8 +22,6 @@
import os
import re
-import sys
-import ast
import ipaddress
from cloudinit import stages
@@ -31,7 +29,6 @@ from cloudinit import util
from cloudinit.distros import ug_util
from cloudinit.settings import PER_INSTANCE
-from cloudinit import handlers
from cloudinit import log as logging
from vyos.configtree import ConfigTree
@@ -42,12 +39,14 @@ logger.setLevel(logging.DEBUG)
frequency = PER_INSTANCE
+
class VyosError(Exception):
"""Raised when the distro runs into an exception when setting vyos config.
This may happen when the ssh pub key format is wrong.
"""
pass
+
# configure user account with password
def set_pass_login(config, user, password, encrypted_pass):
if encrypted_pass:
@@ -57,13 +56,14 @@ def set_pass_login(config, user, password, encrypted_pass):
config.set_tag(['system', 'login', 'user'])
+
# configure user account with ssh key
def set_ssh_login(config, user, key_string, key_x):
key_type = None
key_data = None
key_name = None
- if key_string == '':
+ if key_string == '':
logger.error("No keys found.")
return
@@ -74,7 +74,7 @@ def set_ssh_login(config, user, key_string, key_x):
key_type = key
if key.startswith('AAAAB3NzaC1yc2E') or key.startswith('AAAAB3NzaC1kc3M'):
- key_data = key
+ key_data = key
if not key_type:
logger.error("Key type not defined, wrong ssh key format.")
@@ -92,15 +92,31 @@ def set_ssh_login(config, user, key_string, key_x):
else:
key_name = "cloud-init-%s" % key_x
- config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name , 'key'], value=key_data, replace=True)
- config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name , 'type'], value=key_type, replace=True)
+ config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name, 'key'], value=key_data, replace=True)
+ config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name, 'type'], value=key_type, replace=True)
config.set_tag(['system', 'login', 'user'])
config.set_tag(['system', 'login', 'user', user, 'authentication', 'public-keys'])
+# filter hostname to be sure that it can be applied
+# NOTE: here we cannot attempt to deny anything prohibited, as it is too late.
+# Therefore, we need only pass what is allowed, cutting everything else
+def hostname_filter(hostname):
+ # define regex for alloweed characters and resulted hostname
+ regex_characters = re.compile(r'[a-z0-9.-]', re.IGNORECASE)
+ regex_hostname = re.compile(r'[a-z0-9](([a-z0-9-]\.|[a-z0-9-])*[a-z0-9])?', re.IGNORECASE)
+ # filter characters
+ filtered_characters = ''.join(regex_characters.findall(hostname))
+ # check that hostname start and end by allowed characters and cut unsupported ones, limit to 64 characters total
+ filtered_hostname = regex_hostname.search(filtered_characters).group()[:64]
+
+ # return safe to apply host-name value
+ return filtered_hostname
+
+
# configure system parameters from OVF template
def set_config_ovf(config, hostname, metadata):
- ip_0 = metadata['ip0']
+ ip_0 = metadata['ip0']
mask_0 = metadata['netmask0']
gateway = metadata['gateway']
DNS = list(metadata['DNS'].replace(' ', '').split(','))
@@ -109,8 +125,8 @@ def set_config_ovf(config, hostname, metadata):
APIPORT = metadata['APIPORT']
APIDEBUG = metadata['APIDEBUG']
- if ip_0 and ip_0 != 'null' and mask_0 and mask_0 != 'null' and gateway and gateway != 'null':
- cidr = str(ipaddress.IPv4Network('0.0.0.0/' + mask_0).prefixlen)
+ if ip_0 and ip_0 != 'null' and mask_0 and mask_0 != 'null' and gateway and gateway != 'null':
+ cidr = str(ipaddress.IPv4Network('0.0.0.0/' + mask_0).prefixlen)
ipcidr = ip_0 + '/' + cidr
config.set(['interfaces', 'ethernet', 'eth0', 'address'], value=ipcidr, replace=True)
@@ -146,9 +162,9 @@ def set_config_ovf(config, hostname, metadata):
config.set(['service', 'ssh'], replace=True)
config.set(['service', 'ssh', 'port'], value='22', replace=True)
-
+
if hostname and hostname != 'null':
- config.set(['system', 'host-name'], value=hostname, replace=True)
+ config.set(['system', 'host-name'], value=hostname_filter(hostname), replace=True)
else:
config.set(['system', 'host-name'], value='vyos', replace=True)
@@ -157,11 +173,11 @@ def set_config_ovf(config, hostname, metadata):
def set_config_interfaces(config, iface_name, iface_config):
# configure DHCP client
if 'dhcp4' in iface_config:
- if iface_config['dhcp4'] == True:
+ if iface_config['dhcp4'] is True:
config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp', replace=True)
config.set_tag(['interfaces', 'ethernet'])
if 'dhcp6' in iface_config:
- if iface_config['dhcp6'] == True:
+ if iface_config['dhcp6'] is True:
config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp6', replace=True)
config.set_tag(['interfaces', 'ethernet'])
@@ -226,7 +242,7 @@ def set_config_ssh(config):
# configure hostname
def set_config_hostname(config, hostname):
- config.set(['system', 'host-name'], value=hostname, replace=True)
+ config.set(['system', 'host-name'], value=hostname_filter(hostname), replace=True)
# configure SSH, eth0 interface and hostname
@@ -236,7 +252,7 @@ def set_config_cloud(config, hostname):
config.set(['service', 'ssh', 'client-keepalive-interval'], value='180', replace=True)
config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True)
config.set_tag(['interfaces', 'ethernet'])
- config.set(['system', 'host-name'], value=hostname, replace=True)
+ config.set(['system', 'host-name'], value=hostname_filter(hostname), replace=True)
# main config handler
@@ -253,7 +269,7 @@ def handle(name, cfg, cloud, log, _args):
key_y = 0
# look at data that can be used for configuration
- #print(dir(dc))
+ # print(dir(dc))
if not os.path.exists(cfg_file_name):
file_name = bak_file_name
@@ -264,7 +280,7 @@ def handle(name, cfg, cloud, log, _args):
config_file = f.read()
config = ConfigTree(config_file)
- if 'Azure' in dc.dsname:
+ if 'Azure' in dc.dsname:
encrypted_pass = True
for key, val in users.items():
user = key
@@ -287,14 +303,14 @@ def handle(name, cfg, cloud, log, _args):
password = util.get_cfg_option_str(cfg, 'password', None)
if password and password != '':
- hash = re.match("(^\$.\$)", password)
+ hash = re.match(r"(^\$.\$)", password)
hash_count = password.count('$')
if hash and hash_count >= 3:
base64 = password.split('$')[3]
base_64_len = len(base64)
if ((hash.group(1) == '$1$' and base_64_len == 22) or
- (hash.group(1) == '$5$' and base_64_len == 43) or
- (hash.group(1) == '$6$' and base_64_len == 86)):
+ (hash.group(1) == '$5$' and base_64_len == 43) or
+ (hash.group(1) == '$6$' and base_64_len == 86)):
encrypted_pass = True
set_pass_login(config, user, password, encrypted_pass)
@@ -319,7 +335,7 @@ def handle(name, cfg, cloud, log, _args):
set_config_ssh(config)
set_config_hostname(config, hostname)
else:
- set_config_dhcp(config)
+ set_config_dhcp(config)
set_config_ssh(config)
set_config_hostname(config, hostname)
@@ -330,4 +346,4 @@ def handle(name, cfg, cloud, log, _args):
with open(cfg_file_name, 'w') as f:
f.write(config.to_string())
except Exception as e:
- logger.error("Failed to write configs into file %s error %s", file_name, e)
+ logger.error("Failed to write configs into file {}: {}".format(cfg_file_name, e))