diff options
Diffstat (limited to 'src/conf_mode/salt-minion.py')
-rwxr-xr-x | src/conf_mode/salt-minion.py | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/conf_mode/salt-minion.py b/src/conf_mode/salt-minion.py new file mode 100755 index 000000000..303ddae48 --- /dev/null +++ b/src/conf_mode/salt-minion.py @@ -0,0 +1,203 @@ +#!/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 pwd +import socket +import urllib3 + +import jinja2 + +from vyos.config import Config +from vyos import ConfigError + +config_file = r'/etc/salt/minion' + +# Please be careful if you edit the template. +config_tmpl = """ +### Autogenerated by salt-minion.py ### + +##### Primary configuration settings ##### +########################################## + +# The hash_type is the hash to use when discovering the hash of a file on +# the master server. The default is sha256, but md5, sha1, sha224, sha384 and +# sha512 are also supported. +# +# WARNING: While md5 and sha1 are also supported, do not use them due to the +# high chance of possible collisions and thus security breach. +# +# Prior to changing this value, the master should be stopped and all Salt +# caches should be cleared. +hash_type: {{ hash_type }} + +##### Logging settings ##### +########################################## +# The location of the minion log file +# The minion log can be sent to a regular file, local path name, or network +# location. Remote logging works best when configured to use rsyslogd(8) (e.g.: +# ``file:///dev/log``), with rsyslogd(8) configured for network logging. The URI +# format is: <file|udp|tcp>://<host|socketpath>:<port-if-required>/<log-facility> +#log_file: /var/log/salt/minion +#log_file: file:///dev/log +#log_file: udp://loghost:10514 +# +log_file: {{ log_file }} + +# The level of messages to send to the console. +# One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. +# +# The following log levels are considered INSECURE and may log sensitive data: +# ['garbage', 'trace', 'debug'] +# +# Default: 'warning' +log_level: {{ log_level }} + +# Set the location of the salt master server, if the master server cannot be +# resolved, then the minion will fail to start. +master: +{% for host in master -%} +- {{ host }} +{% endfor %} + +# The user to run salt +user: {{ user }} + +# The directory to store the pki information in +pki_dir: /config/salt/pki/minion + +# Explicitly declare the id for this minion to use, if left commented the id +# will be the hostname as returned by the python call: socket.getfqdn() +# Since salt uses detached ids it is possible to run multiple minions on the +# same machine but with different ids, this can be useful for salt compute +# clusters. +id: {{ salt_id }} + + +# The number of minutes between mine updates. +mine_interval: {{ mine_interval }} + +verify_master_pubkey_sign: {{ verify_master_pubkey_sign }} +""" + +default_config_data = { + 'hash_type': 'sha256', + 'log_file': '/var/log/salt/minion', + 'log_level': 'warning', + 'master' : 'salt', + 'user': 'minion', + 'salt_id': socket.gethostname(), + 'mine_interval': '60', + 'verify_master_pubkey_sign': 'false' +} + +def get_config(): + salt = default_config_data + conf = Config() + if not conf.exists('service salt-minion'): + return None + else: + conf.set_level('service salt-minion') + + if conf.exists('hash_type'): + salt['hash_type'] = conf.return_value('hash_type') + + if conf.exists('log_file'): + salt['log_file'] = conf.return_value('log_file') + + if conf.exists('log_level'): + salt['log_level'] = conf.return_value('log_level') + + if conf.exists('master'): + master = conf.return_values('master') + salt['master'] = master + + if conf.exists('id'): + salt['salt_id'] = conf.return_value('id') + + if conf.exists('user'): + salt['user'] = conf.return_value('user') + + if conf.exists('mine_interval'): + salt['mine_interval'] = conf.return_value('mine_interval') + + salt['master-key'] = None + if conf.exists('master-key'): + salt['master-key'] = conf.return_value('master-key') + salt['verify_master_pubkey_sign'] = 'true' + + return salt + +def generate(salt): + paths = ['/etc/salt/','/var/run/salt','/opt/vyatta/etc/config/salt/'] + directory = '/opt/vyatta/etc/config/salt/pki/minion' + uid = pwd.getpwnam(salt['user']).pw_uid + http = urllib3.PoolManager() + + if salt is None: + return None + + if not os.path.exists(directory): + os.makedirs(directory) + + tmpl = jinja2.Template(config_tmpl) + config_text = tmpl.render(salt) + with open(config_file, 'w') as f: + f.write(config_text) + path = "/etc/salt/" + for path in paths: + for root, dirs, files in os.walk(path): + for usgr in dirs: + os.chown(os.path.join(root, usgr), uid, 100) + for usgr in files: + os.chown(os.path.join(root, usgr), uid, 100) + + if not os.path.exists('/opt/vyatta/etc/config/salt/pki/minion/master_sign.pub'): + if not salt['master-key'] is None: + r = http.request('GET', salt['master-key'], preload_content=False) + + with open('/opt/vyatta/etc/config/salt/pki/minion/master_sign.pub', 'wb') as out: + while True: + data = r.read(1024) + if not data: + break + out.write(data) + + r.release_conn() + + return None + +def apply(salt): + if salt is not None: + os.system("sudo systemctl restart salt-minion") + else: + # Salt access is removed in the commit + os.system("sudo systemctl stop salt-minion") + os.unlink(config_file) + + return None + +if __name__ == '__main__': + try: + c = get_config() + generate(c) + apply(c) + except ConfigError as e: + print(e) + sys.exit(1) |