diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/authutils.py | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 4 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireguard.py | 1 | ||||
-rw-r--r-- | python/vyos/remote.py | 29 | ||||
-rw-r--r-- | python/vyos/util.py | 72 |
5 files changed, 66 insertions, 48 deletions
diff --git a/python/vyos/authutils.py b/python/vyos/authutils.py index 234294649..90a46ffb4 100644 --- a/python/vyos/authutils.py +++ b/python/vyos/authutils.py @@ -15,16 +15,14 @@ import re -from subprocess import Popen, PIPE, STDOUT +from vyos.util import cmd def make_password_hash(password): """ Makes a password hash for /etc/shadow using mkpasswd """ - mkpasswd = Popen(['mkpasswd', '--method=sha-512', '--stdin'], stdout=PIPE, stdin=PIPE, stderr=PIPE) - hash = mkpasswd.communicate(input=password.encode(), timeout=5)[0].decode().strip() - - return hash + mkpassword = 'mkpasswd --method=sha-512 --stdin' + return cmd(mkpassword, input=password.encode(), timeout=5) def split_ssh_public_key(key_string, defaultname=""): """ Splits an SSH public key into its components """ diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index c18d2e72f..291b326bf 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -18,7 +18,7 @@ import re from vyos.ifconfig.interface import Interface from vyos.ifconfig.vlan import VLAN -from vyos.util import popen +from vyos.util import run from vyos.validate import * @@ -45,7 +45,7 @@ class EthernetIf(Interface): @staticmethod def feature(ifname, option, value): - out, code = popen(f'/sbin/ethtool -K {ifname} {option} {value}','ifconfig') + run(f'/sbin/ethtool -K {ifname} {option} {value}','ifconfig') return False _command_set = {**Interface._command_set, **{ diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index def5ab7c5..e2b8a5924 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -16,7 +16,6 @@ import os import time -import subprocess from datetime import timedelta from vyos.config import Config diff --git a/python/vyos/remote.py b/python/vyos/remote.py index f8a21f068..f0bf41cd4 100644 --- a/python/vyos/remote.py +++ b/python/vyos/remote.py @@ -17,7 +17,8 @@ import sys import os import re import fileinput -import subprocess + +from vyos.util import cmd, DEVNULL def check_and_add_host_key(host_name): @@ -33,10 +34,8 @@ def check_and_add_host_key(host_name): keyscan_cmd = 'ssh-keyscan -t rsa {} 2>/dev/null'.format(host_name) try: - host_key = subprocess.check_output(keyscan_cmd, shell=True, - stderr=subprocess.DEVNULL, - universal_newlines=True) - except subprocess.CalledProcessError as err: + host_key = cmd(keyscan_cmd, stderr=DEVNULL, universal_newlines=True) + except OSError: sys.exit("Can not get RSA host key") # libssh2 (jessie; stretch) does not recognize ec host keys, and curl @@ -64,10 +63,8 @@ def check_and_add_host_key(host_name): fingerprint_cmd = 'ssh-keygen -lf /dev/stdin <<< "{}"'.format(host_key) try: - fingerprint = subprocess.check_output(fingerprint_cmd, shell=True, - stderr=subprocess.DEVNULL, - universal_newlines=True) - except subprocess.CalledProcessError as err: + fingerprint = cmd(fingerprint_cmd, stderr=DEVNULL, universal_newlines=True) + except OSError: sys.exit("Can not get RSA host key fingerprint.") print("RSA host key fingerprint is {}".format(fingerprint.split()[1])) @@ -128,9 +125,8 @@ def get_remote_config(remote_file): # Try header first, and look for 'OK' or 'Moved' codes: curl_cmd = 'curl {0} -q -I {1}'.format(redirect_opt, remote_file) try: - curl_output = subprocess.check_output(curl_cmd, shell=True, - universal_newlines=True) - except subprocess.CalledProcessError: + curl_output = cmd(curl_cmd, shell=True, universal_newlines=True) + except OSError: sys.exit(1) return_vals = re.findall(r'^HTTP\/\d+\.?\d\s+(\d+)\s+(.*)$', @@ -146,9 +142,6 @@ def get_remote_config(remote_file): curl_cmd = 'curl {0} -# {1}'.format(redirect_opt, remote_file) try: - config_file = subprocess.check_output(curl_cmd, shell=True, - universal_newlines=True) - except subprocess.CalledProcessError: - config_file = None - - return config_file + return cmd(curl_cmd, universal_newlines=True) + except OSError: + return None diff --git a/python/vyos/util.py b/python/vyos/util.py index c8ab43c11..fa2b4dd99 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -16,7 +16,7 @@ import os import re import sys -from subprocess import Popen, PIPE, STDOUT +from subprocess import Popen, PIPE, STDOUT, DEVNULL # debugging @@ -33,36 +33,65 @@ def debug_msg(message, section=''): # commands - -def popen(command, section=''): - p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) - tmp = p.communicate()[0].strip() +# popen does not raise +# it returns the output of the command and the error code +def popen(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None): + use_shell = shell + if shell is None: + use_shell = True if ' ' in command else False + p = Popen( + command, + stdout=stdout, stderr=stderr, + env=env, shell=use_shell, + universal_newlines=universal_newlines, + ) + tmp = p.communicate(input, timeout)[0].strip() debug_msg(f"cmd '{command}'", section) - decoded = tmp.decode() + decoded = tmp.decode(decode) if decode else tmp.decode() if decoded: debug_msg(f"returned:\n{decoded}", section) return decoded, p.returncode - -def cmd(command, section=''): - decoded, code = popen(command, section) +# run does not raise +# it returns the error code +def run(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None): + _, code = popen( + command, section, + stdout=stdout, stderr=stderr, + input=input, timeout=timeout, + env=env, shell=shell, + universal_newlines=universal_newlines, + decode=decode, + ) + return code + +# cmd does raise +# it returns the output +def cmd(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None, raising=None, message=''): + decoded, code = popen( + command, section, + stdout=stdout, stderr=stderr, + input=input, timeout=timeout, + env=env, shell=shell, + universal_newlines=universal_newlines, + decode=decode, + ) if code != 0: - # error code can be recovered with .errno - raise OSError(code, f'{command}\nreturned: {decoded}') + feedback = message + '\n' if message else '' + feedback += f'failed to run command: {command}\n' + feedback += f'returned: {decoded}\n' + feedback += f'exit code: {code}' + if raising is None: + # error code can be recovered with .errno + raise OSError(code, feedback) + else: + raise raising(feedback) return decoded # file manipulation - -def subprocess_cmd(command): - """ execute arbitrary command via Popen """ - from subprocess import Popen, PIPE - p = Popen(command, stdout=PIPE, shell=True) - p.communicate() - - def read_file(path): """ Read a file to string """ with open(path, 'r') as f: @@ -224,12 +253,11 @@ def commit_in_progress(): # Since this will be used in scripts that modify the config outside of the CLI # framework, those knowingly have root permissions. # For everything else, we add a safeguard. - from subprocess import check_output from psutil import process_iter, NoSuchProcess from vyos.defaults import commit_lock - id = check_output(['/usr/bin/id', '-u']).decode().strip() - if id != '0': + idu = cmd('/usr/bin/id -u') + if idu != '0': raise OSError("This functions needs root permissions to return correct results") for proc in process_iter(): |