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).
This commit is contained in:
Brian C. Lane 2018-10-10 11:27:10 -07:00
parent 5efce31772
commit 3499426b2d
3 changed files with 54 additions and 24 deletions

View File

@ -17,6 +17,7 @@
import configparser import configparser
import grp import grp
import os import os
import pwd
from pylorax.sysutils import joinpaths from pylorax.sysutils import joinpaths
@ -67,20 +68,57 @@ def configure(conf_file="/etc/lorax/composer.conf", root_dir="/", test_config=Fa
return conf return conf
def make_dnf_dirs(conf): def make_owned_dir(p_dir, uid, gid):
"""Make any missing dnf directories """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 :param conf: The configuration to use
:type conf: ComposerConfig :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"]: for p in ["dnf_conf", "repo_dir", "cache_dir", "dnf_root"]:
p_dir = os.path.abspath(conf.get("composer", p)) p_dir = os.path.abspath(conf.get("composer", p))
if p == "dnf_conf": if p == "dnf_conf":
p_dir = os.path.dirname(p_dir) p_dir = os.path.dirname(p_dir)
errors.extend(make_owned_dir(p_dir, uid, gid))
if not os.path.isdir(p_dir):
os.makedirs(p_dir)
def make_queue_dirs(conf, gid): def make_queue_dirs(conf, gid):
"""Make any missing queue directories """Make any missing queue directories
@ -96,18 +134,5 @@ def make_queue_dirs(conf, gid):
lib_dir = conf.get("composer", "lib_dir") lib_dir = conf.get("composer", "lib_dir")
for p in ["queue/run", "queue/new", "results"]: for p in ["queue/run", "queue/new", "results"]:
p_dir = joinpaths(lib_dir, p) p_dir = joinpaths(lib_dir, p)
if not os.path.exists(p_dir): errors.extend(make_owned_dir(p_dir, 0, gid))
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))
return errors return errors

View File

@ -210,6 +210,9 @@ if __name__ == '__main__':
log.error(e) log.error(e)
sys.exit(1) 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)? # Did systemd pass any extra fds (for socket activation)?
try: try:
fds = int(os.environ['LISTEN_FDS']) 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) # 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") 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 # Get a dnf.Base to share with the requests
try: try:
server.config["DNFLOCK"] = DNFLock(server.config["COMPOSER_CFG"]) server.config["DNFLOCK"] = DNFLock(server.config["COMPOSER_CFG"])

View File

@ -10,7 +10,12 @@ export top_srcdir=`pwd`
./src/sbin/lorax-composer --sharedir ./share/ ./tests/pylorax/blueprints/ & ./src/sbin/lorax-composer --sharedir ./share/ ./tests/pylorax/blueprints/ &
# wait for the backend to become ready # 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 sleep 2
echo "DEBUG: Waiting for backend API to become ready before testing ..." echo "DEBUG: Waiting for backend API to become ready before testing ..."
done; done;