diff --git a/roles/sys-svc-container/meta/packages.yml b/roles/sys-svc-container/meta/packages.yml index cb905aea76..56315d6b55 100644 --- a/roles/sys-svc-container/meta/packages.yml +++ b/roles/sys-svc-container/meta/packages.yml @@ -20,5 +20,6 @@ docker-cli: - docker-ce - docker-ce-cli - docker-compose-plugin + - iptables-nft repo: managed_externally: sys-svc-container configures the download.docker.com repository per distro before installing diff --git a/scripts/tests/deploy/ci/one.sh b/scripts/tests/deploy/ci/one.sh index b33b41f50f..3d09526d7e 100755 --- a/scripts/tests/deploy/ci/one.sh +++ b/scripts/tests/deploy/ci/one.sh @@ -19,7 +19,7 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)" . "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/pick.sh" filesystem_pick "${INFINITO_DEPLOY_MODE}/${apps}/${INFINITO_DISTRO}" runner if [ -n "${INFINITO_DOCKER_FILESYSTEM:-}" ]; then - sudo -E "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/docker_dataroot.sh" \ + sudo --preserve-env="$(compgen -e | paste -sd, -)" "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/docker_dataroot.sh" \ "${INFINITO_DOCKER_FILESYSTEM}" "${INFINITO_DOCKER_FILESYSTEM_REQUIRED}" 30G \ "${INFINITO_DEPLOY_MODE}-runner" fi diff --git a/scripts/tests/deploy/swarm/routine/00_one.sh b/scripts/tests/deploy/swarm/routine/00_one.sh index be215fdda2..b3c4ce4af1 100755 --- a/scripts/tests/deploy/swarm/routine/00_one.sh +++ b/scripts/tests/deploy/swarm/routine/00_one.sh @@ -165,7 +165,7 @@ fi matrix_cmd=(timeout "${step_timeout}" python3 -m utils.tests.swarm.matrix) if [ "$(id -u)" -ne 0 ]; then matrix_cmd=( - sudo -E env + sudo --preserve-env="$(compgen -e | paste -sd, -)" env "PATH=$PATH" "HOME=$HOME" "SWARM_NAME=${SWARM_NAME:-}" diff --git a/scripts/tests/deploy/swarm/routine/01_bootstrap.sh b/scripts/tests/deploy/swarm/routine/01_bootstrap.sh index b0b8ee7036..f974d43e31 100755 --- a/scripts/tests/deploy/swarm/routine/01_bootstrap.sh +++ b/scripts/tests/deploy/swarm/routine/01_bootstrap.sh @@ -26,7 +26,7 @@ if command -v apt-get >/dev/null 2>&1; then if [ "$(id -u)" -eq 0 ]; then timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error else - sudo -E timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error + sudo --preserve-env="$(compgen -e | paste -sd, -)" timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error fi fi diff --git a/tests/lint/repository/test_no_sudo_preserve_whole_env.py b/tests/lint/repository/test_no_sudo_preserve_whole_env.py new file mode 100644 index 0000000000..b9d79918f1 --- /dev/null +++ b/tests/lint/repository/test_no_sudo_preserve_whole_env.py @@ -0,0 +1,42 @@ +"""Forbid ``sudo -E`` and bare ``sudo --preserve-env`` in tracked .yml and .sh files.""" + +from __future__ import annotations + +import re +import unittest +from pathlib import Path + +from utils.cache.files import iter_project_files, read_text + +from . import PROJECT_ROOT + +_WHOLE_ENV = re.compile(r"\bsudo\s+(?:-\w+\s+)*(?:-\w*E\w*|--preserve-env)(?=\s|$)") + + +class TestNoSudoPreserveWholeEnv(unittest.TestCase): + def test_no_whole_environment_preservation(self) -> None: + offenders: list[str] = [] + for path_str in iter_project_files( + extensions=(".yml", ".yaml", ".sh"), + exclude_tests=True, + exclude_dirs=("docs",), + ): + rel = Path(path_str).relative_to(PROJECT_ROOT).as_posix() + for lineno, line in enumerate(read_text(path_str).splitlines(), 1): + if line.lstrip().startswith("#"): + continue + if _WHOLE_ENV.search(line): + offenders.append(f"{rel}:{lineno}: {line.strip()}") + + if offenders: + self.fail( + f"{len(offenders)} sudo call(s) preserve the whole environment. " + "sudo-rs (default sudo on ubuntu-26.04 runners) ignores -E and " + "drops every caller variable; name them instead with " + '--preserve-env="$(compgen -e | paste -sd, -)".\n' + + "\n".join(offenders) + ) + + +if __name__ == "__main__": + unittest.main()