diff --git a/salt/reactor/sominion_setup.sls b/salt/reactor/sominion_setup.sls index 64b3666f4..a72348cc8 100644 --- a/salt/reactor/sominion_setup.sls +++ b/salt/reactor/sominion_setup.sls @@ -6,39 +6,74 @@ # Elastic License 2.0. import logging -from subprocess import call -import yaml +import os +import re +import shlex +import subprocess log = logging.getLogger(__name__) +SO_MINION = '/usr/sbin/so-minion' + +_NODETYPE_RE = re.compile(r'^[A-Z][A-Z0-9_]{0,31}$') +_MINIONID_RE = re.compile(r'^[A-Za-z0-9._-]{1,253}$') +_HOSTPART_RE = re.compile(r'^[A-Za-z0-9._-]{1,253}$') +_IPV4_RE = re.compile( + r'^(?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}' + r'(?:25[0-5]|2[0-4]\d|[01]?\d?\d)$' +) +_HEAP_RE = re.compile(r'^\d{1,6}[kKmMgG]?$') + + +def _check(name, value, pattern): + s = str(value) + if not pattern.match(s): + raise ValueError("sominion_setup_reactor: refusing unsafe %s=%r" % (name, value)) + return s + + def run(): log.info('sominion_setup_reactor: Running') minionid = data['id'] DATA = data['data'] - hv_name = DATA['HYPERVISOR_HOST'] log.info('sominion_setup_reactor: DATA: %s' % DATA) - # Build the base command - cmd = "NODETYPE=" + DATA['NODETYPE'] + " /usr/sbin/so-minion -o=addVM -m=" + minionid + " -n=" + DATA['MNIC'] + " -i=" + DATA['MAINIP'] + " -c=" + str(DATA['CPUCORES']) + " -d='" + DATA['NODE_DESCRIPTION'] + "'" - - # Add optional arguments only if they exist in DATA + nodetype = _check('NODETYPE', DATA['NODETYPE'], _NODETYPE_RE) + + argv = [ + SO_MINION, + '-o=addVM', + '-m=' + _check('minionid', minionid, _MINIONID_RE), + '-n=' + _check('MNIC', DATA['MNIC'], _HOSTPART_RE), + '-i=' + _check('MAINIP', DATA['MAINIP'], _IPV4_RE), + '-c=' + str(int(DATA['CPUCORES'])), + '-d=' + str(DATA['NODE_DESCRIPTION']), + ] + if 'CORECOUNT' in DATA: - cmd += " -C=" + str(DATA['CORECOUNT']) - + argv.append('-C=' + str(int(DATA['CORECOUNT']))) + if 'INTERFACE' in DATA: - cmd += " -a=" + DATA['INTERFACE'] - + argv.append('-a=' + _check('INTERFACE', DATA['INTERFACE'], _HOSTPART_RE)) + if 'ES_HEAP_SIZE' in DATA: - cmd += " -e=" + DATA['ES_HEAP_SIZE'] - + argv.append('-e=' + _check('ES_HEAP_SIZE', DATA['ES_HEAP_SIZE'], _HEAP_RE)) + if 'LS_HEAP_SIZE' in DATA: - cmd += " -l=" + DATA['LS_HEAP_SIZE'] + argv.append('-l=' + _check('LS_HEAP_SIZE', DATA['LS_HEAP_SIZE'], _HEAP_RE)) if 'LSHOSTNAME' in DATA: - cmd += " -L=" + DATA['LSHOSTNAME'] - - log.info('sominion_setup_reactor: Command: %s' % cmd) - rc = call(cmd, shell=True) + argv.append('-L=' + _check('LSHOSTNAME', DATA['LSHOSTNAME'], _HOSTPART_RE)) + + env = os.environ.copy() + env['NODETYPE'] = nodetype + + log.info( + 'sominion_setup_reactor: argv: %s (NODETYPE=%s)', + ' '.join(shlex.quote(a) for a in argv), + shlex.quote(nodetype), + ) + rc = subprocess.call(argv, shell=False, env=env) log.info('sominion_setup_reactor: rc: %s' % rc)