From 65b769984b6990a0c54d3971a9c10070ce46d3d9 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 10 Oct 2018 11:27:10 -0700 Subject: [PATCH] Change make_dnf_dirs to be run as root It needs to be root in order to set the ownership and permissions on the directories that are under /var/lib/lorax/composer/ Refactor the directory creation into a utility function, and use a umask of 0o006 to ensure that the parent directories created do not have o+rw set on them (makedirs behavior is different between Python 3.6 and 3.7 so umask of 0 doesn't work consistently). --- src/pylorax/api/config.py | 65 +++++++++++++++++++++++++++------------ src/sbin/lorax-composer | 6 ++-- tests/test_cli.sh | 7 ++++- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/pylorax/api/config.py b/src/pylorax/api/config.py index 3c9b2d69..8f9a30de 100644 --- a/src/pylorax/api/config.py +++ b/src/pylorax/api/config.py @@ -17,6 +17,7 @@ import configparser import grp import os +import pwd from pylorax.sysutils import joinpaths @@ -67,20 +68,57 @@ def configure(conf_file="/etc/lorax/composer.conf", root_dir="/", test_config=Fa return conf -def make_dnf_dirs(conf): - """Make any missing dnf directories +def make_owned_dir(p_dir, uid, gid): + """Make a directory and its parents, setting owner and group + + :param p_dir: path to directory to create + :type p_dir: string + :param uid: uid of owner + :type uid: int + :param gid: gid of owner + :type gid: int + :returns: list of errors + :rtype: list of str + + Check to make sure it does not have o+rw permissions and that it is owned by uid:gid + """ + errors = [] + if not os.path.isdir(p_dir): + # Make sure no o+rw permissions are set + orig_umask = os.umask(0o006) + os.makedirs(p_dir, 0o771) + os.chown(p_dir, uid, gid) + os.umask(orig_umask) + else: + p_stat = os.stat(p_dir) + if p_stat.st_mode & 0o006 != 0: + errors.append("Incorrect permissions on %s, no o+rw permissions are allowed." % p_dir) + + if p_stat.st_gid != gid or p_stat.st_uid != 0: + gr_name = grp.getgrgid(gid).gr_name + u_name = pwd.getpwuid(uid) + errors.append("%s should be owned by %s:%s" % (p_dir, u_name, gr_name)) + + return errors + +def make_dnf_dirs(conf, uid, gid): + """Make any missing dnf directories owned by user:group :param conf: The configuration to use :type conf: ComposerConfig - :returns: None + :param uid: uid of owner + :type uid: int + :param gid: gid of owner + :type gid: int + :returns: list of errors + :rtype: list of str """ + errors = [] for p in ["dnf_conf", "repo_dir", "cache_dir", "dnf_root"]: p_dir = os.path.abspath(conf.get("composer", p)) if p == "dnf_conf": p_dir = os.path.dirname(p_dir) - - if not os.path.isdir(p_dir): - os.makedirs(p_dir) + errors.extend(make_owned_dir(p_dir, uid, gid)) def make_queue_dirs(conf, gid): """Make any missing queue directories @@ -96,18 +134,5 @@ def make_queue_dirs(conf, gid): lib_dir = conf.get("composer", "lib_dir") for p in ["queue/run", "queue/new", "results"]: p_dir = joinpaths(lib_dir, p) - if not os.path.exists(p_dir): - orig_umask = os.umask(0) - os.makedirs(p_dir, 0o771) - os.chown(p_dir, 0, gid) - os.umask(orig_umask) - else: - p_stat = os.stat(p_dir) - if p_stat.st_mode & 0o006 != 0: - errors.append("Incorrect permissions on %s, no o+rw permissions are allowed." % p_dir) - - if p_stat.st_gid != gid or p_stat.st_uid != 0: - gr_name = grp.getgrgid(gid).gr_name - errors.append("%s should be owned by root:%s" % (p_dir, gr_name)) - + errors.extend(make_owned_dir(p_dir, 0, gid)) return errors diff --git a/src/sbin/lorax-composer b/src/sbin/lorax-composer index ea164901..953eb448 100755 --- a/src/sbin/lorax-composer +++ b/src/sbin/lorax-composer @@ -210,6 +210,9 @@ if __name__ == '__main__': log.error(e) sys.exit(1) + # Make sure dnf directories are created (owned by user:group) + make_dnf_dirs(server.config["COMPOSER_CFG"], uid, gid) + # Did systemd pass any extra fds (for socket activation)? try: fds = int(os.environ['LISTEN_FDS']) @@ -241,9 +244,6 @@ if __name__ == '__main__': # Switch to a home directory we can access (libgit2 uses this to look for .gitconfig) os.environ["HOME"] = server.config["COMPOSER_CFG"].get("composer", "lib_dir") - # Make sure dnf directories are created - make_dnf_dirs(server.config["COMPOSER_CFG"]) - # Get a dnf.Base to share with the requests try: server.config["DNFLOCK"] = DNFLock(server.config["COMPOSER_CFG"]) diff --git a/tests/test_cli.sh b/tests/test_cli.sh index abc70dc7..eecea4ea 100755 --- a/tests/test_cli.sh +++ b/tests/test_cli.sh @@ -10,7 +10,12 @@ export top_srcdir=`pwd` ./src/sbin/lorax-composer --sharedir ./share/ ./tests/pylorax/blueprints/ & # wait for the backend to become ready -until curl --unix-socket /run/weldr/api.socket http://localhost:4000/api/status | grep '"db_supported":true'; do +tries=0 +until curl -m 15 --unix-socket /run/weldr/api.socket http://localhost:4000/api/status | grep 'db_supported.*true'; do + tries=$((tries + 1)) + if [ $tries -gt 20 ]; then + exit 1 + fi sleep 2 echo "DEBUG: Waiting for backend API to become ready before testing ..." done;