forked from Mirror/pmbootstrap
Use doas instead of sudo if installed (MR 2091)
Prefer using doas over sudo if both are installed. Let the user override the sudo tool with PMB_SUDO.
This commit is contained in:
parent
2801b5d687
commit
c1407f921b
8 changed files with 60 additions and 8 deletions
|
@ -195,6 +195,12 @@ $ pmbootstrap stats --arch=armhf
|
||||||
$ pmbootstrap log_distccd
|
$ pmbootstrap log_distccd
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Use alternative sudo
|
||||||
|
|
||||||
|
pmbootstrap supports `doas` and `sudo`.
|
||||||
|
If multiple sudo implementations are installed, pmbootstrap will use `doas`.
|
||||||
|
You can set the `PMB_SUDO` environmental variable to define the sudo implementation you want to use.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
### Requirements for running tests
|
### Requirements for running tests
|
||||||
* [Shellcheck](https://shellcheck.net/)
|
* [Shellcheck](https://shellcheck.net/)
|
||||||
|
|
|
@ -71,7 +71,7 @@ def root(args, cmd, suffix="native", working_dir="/", output="log",
|
||||||
executables = executables_absolute_path()
|
executables = executables_absolute_path()
|
||||||
cmd_chroot = [executables["chroot"], chroot, "/bin/sh", "-c",
|
cmd_chroot = [executables["chroot"], chroot, "/bin/sh", "-c",
|
||||||
pmb.helpers.run.flat_cmd(cmd, working_dir)]
|
pmb.helpers.run.flat_cmd(cmd, working_dir)]
|
||||||
cmd_sudo = ["sudo", "env", "-i", executables["sh"], "-c",
|
cmd_sudo = [pmb.config.sudo, "env", "-i", executables["sh"], "-c",
|
||||||
pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)]
|
pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)]
|
||||||
return pmb.helpers.run_core.core(args, msg, cmd_sudo, None, output,
|
return pmb.helpers.run_core.core(args, msg, cmd_sudo, None, output,
|
||||||
output_return, check, True,
|
output_return, check, True,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import sys
|
||||||
from pmb.config.load import load
|
from pmb.config.load import load
|
||||||
from pmb.config.save import save
|
from pmb.config.save import save
|
||||||
from pmb.config.merge_with_args import merge_with_args
|
from pmb.config.merge_with_args import merge_with_args
|
||||||
|
from pmb.config.sudo import which_sudo
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -50,6 +51,7 @@ ondev_min_version = "0.2.0"
|
||||||
# in sync with README.md, and try to keep the list as small as possible. The
|
# in sync with README.md, and try to keep the list as small as possible. The
|
||||||
# idea is to run almost everything in Alpine chroots.
|
# idea is to run almost everything in Alpine chroots.
|
||||||
required_programs = ["git", "openssl", "ps"]
|
required_programs = ["git", "openssl", "ps"]
|
||||||
|
sudo = which_sudo()
|
||||||
|
|
||||||
# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
|
# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
|
||||||
config_keys = ["aports",
|
config_keys = ["aports",
|
||||||
|
|
28
pmb/config/sudo.py
Normal file
28
pmb/config/sudo.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright 2021 Anjandev Momi
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
def which_sudo():
|
||||||
|
"""
|
||||||
|
Find whether sudo or doas is installed for commands that require root.
|
||||||
|
Allows user to override preferred sudo with PMB_SUDO env variable.
|
||||||
|
"""
|
||||||
|
supported_sudos = ['doas', 'sudo']
|
||||||
|
|
||||||
|
user_set_sudo = os.getenv("PMB_SUDO")
|
||||||
|
if user_set_sudo is not None:
|
||||||
|
if shutil.which(user_set_sudo) is None:
|
||||||
|
raise RuntimeError("PMB_SUDO environmental variable is set to"
|
||||||
|
f" {user_set_sudo} but pmbootstrap cannot find"
|
||||||
|
" this command on your system.")
|
||||||
|
return user_set_sudo
|
||||||
|
|
||||||
|
for sudo in supported_sudos:
|
||||||
|
if shutil.which(sudo) is not None:
|
||||||
|
return sudo
|
||||||
|
|
||||||
|
raise RuntimeError("Can't find sudo or doas required to run pmbootstrap."
|
||||||
|
" Please install sudo, doas, or specify your own sudo"
|
||||||
|
" with the PMB_SUDO environmental variable.")
|
|
@ -62,7 +62,7 @@ def user(args, cmd, working_dir=None, output="log", output_return=False,
|
||||||
def root(args, cmd, working_dir=None, output="log", output_return=False,
|
def root(args, cmd, working_dir=None, output="log", output_return=False,
|
||||||
check=None, env={}):
|
check=None, env={}):
|
||||||
"""
|
"""
|
||||||
Run a command on the host system as root, with sudo.
|
Run a command on the host system as root, with sudo or doas.
|
||||||
|
|
||||||
:param env: dict of environment variables to be passed to the command, e.g.
|
:param env: dict of environment variables to be passed to the command, e.g.
|
||||||
{"JOBS": "5"}
|
{"JOBS": "5"}
|
||||||
|
@ -72,7 +72,7 @@ def root(args, cmd, working_dir=None, output="log", output_return=False,
|
||||||
"""
|
"""
|
||||||
if env:
|
if env:
|
||||||
cmd = ["sh", "-c", flat_cmd(cmd, env=env)]
|
cmd = ["sh", "-c", flat_cmd(cmd, env=env)]
|
||||||
cmd = ["sudo"] + cmd
|
cmd = [pmb.config.sudo] + cmd
|
||||||
|
|
||||||
return user(args, cmd, working_dir, output, output_return, check, env,
|
return user(args, cmd, working_dir, output, output_return, check, env,
|
||||||
True)
|
True)
|
||||||
|
|
|
@ -224,7 +224,10 @@ def sudo_timer_iterate():
|
||||||
Run sudo -v and schedule a new timer to repeat the same.
|
Run sudo -v and schedule a new timer to repeat the same.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if pmb.config.sudo == "sudo":
|
||||||
subprocess.Popen(["sudo", "-v"]).wait()
|
subprocess.Popen(["sudo", "-v"]).wait()
|
||||||
|
else:
|
||||||
|
subprocess.Popen([pmb.config.sudo, "true"]).wait()
|
||||||
|
|
||||||
timer = threading.Timer(interval=60, function=sudo_timer_iterate)
|
timer = threading.Timer(interval=60, function=sudo_timer_iterate)
|
||||||
timer.daemon = True
|
timer.daemon = True
|
||||||
|
|
|
@ -79,8 +79,9 @@ def bootimg(args, path):
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
raise RuntimeError("Could not find file '" + path + "'")
|
raise RuntimeError("Could not find file '" + path + "'")
|
||||||
|
|
||||||
logging.info("NOTE: You will be prompted for your sudo password, so we can"
|
logging.info("NOTE: You will be prompted for your sudo/doas password, so"
|
||||||
" set up a chroot to extract and analyze your boot.img file")
|
" we can set up a chroot to extract and analyze your"
|
||||||
|
" boot.img file")
|
||||||
pmb.chroot.apk.install(args, ["file", "unpackbootimg"])
|
pmb.chroot.apk.install(args, ["file", "unpackbootimg"])
|
||||||
|
|
||||||
temp_path = pmb.chroot.other.tempfolder(args, "/tmp/bootimg_parser")
|
temp_path = pmb.chroot.other.tempfolder(args, "/tmp/bootimg_parser")
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import pytest
|
import pytest
|
||||||
|
import time
|
||||||
|
|
||||||
import pmb_test # noqa
|
import pmb_test # noqa
|
||||||
import pmb.helpers.run_core
|
import pmb.helpers.run_core
|
||||||
|
@ -81,7 +82,7 @@ def test_foreground_pipe(args):
|
||||||
assert ret == (-9, "first\n")
|
assert ret == (-9, "first\n")
|
||||||
|
|
||||||
# Kill with output timeout as root
|
# Kill with output timeout as root
|
||||||
cmd = ["sudo", "sh", "-c", "printf first; sleep 2; printf second"]
|
cmd = [pmb.config.sudo, "sh", "-c", "printf first; sleep 2; printf second"]
|
||||||
args.timeout = 0.3
|
args.timeout = 0.3
|
||||||
ret = func(args, cmd, output_return=True, output_timeout=True,
|
ret = func(args, cmd, output_return=True, output_timeout=True,
|
||||||
sudo=True)
|
sudo=True)
|
||||||
|
@ -97,7 +98,7 @@ def test_foreground_pipe(args):
|
||||||
# Check if all child processes are killed after timeout.
|
# Check if all child processes are killed after timeout.
|
||||||
# The first command uses ps to get its process group id (pgid) and echo it
|
# The first command uses ps to get its process group id (pgid) and echo it
|
||||||
# to stdout. All of the test commands will be running under that pgid.
|
# to stdout. All of the test commands will be running under that pgid.
|
||||||
cmd = ["sudo", "sh", "-c",
|
cmd = [pmb.config.sudo, "sh", "-c",
|
||||||
"pgid=$(ps -o pgid= | grep ^${1:-$$});echo $pgid | tr -d '\n';" +
|
"pgid=$(ps -o pgid= | grep ^${1:-$$});echo $pgid | tr -d '\n';" +
|
||||||
"sleep 10 | sleep 20 | sleep 30"]
|
"sleep 10 | sleep 20 | sleep 30"]
|
||||||
args.timeout = 0.3
|
args.timeout = 0.3
|
||||||
|
@ -152,3 +153,14 @@ def test_core(args):
|
||||||
with pytest.raises(RuntimeError) as e:
|
with pytest.raises(RuntimeError) as e:
|
||||||
func(args, msg, ["sleep", "1"], output="log")
|
func(args, msg, ["sleep", "1"], output="log")
|
||||||
assert str(e.value).startswith("Command failed:")
|
assert str(e.value).startswith("Command failed:")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip_ci
|
||||||
|
def test_sudo_timer(args):
|
||||||
|
pmb.helpers.run.root(args, ["whoami"])
|
||||||
|
|
||||||
|
time.sleep(300)
|
||||||
|
|
||||||
|
out = pmb.helpers.run.root(args, ["whoami"])
|
||||||
|
|
||||||
|
assert out == 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue