diff --git a/deploy/auto-deploy.sh b/deploy/auto-deploy.sh index 93a9ba1..5e83003 100755 --- a/deploy/auto-deploy.sh +++ b/deploy/auto-deploy.sh @@ -171,7 +171,9 @@ fi if [ -n "$RESTART" ]; then log "Restarting:$RESTART" - sudo systemctl restart $RESTART + for svc in $RESTART; do + sudo systemctl restart "$svc" + done sleep 30 FAIL=0 diff --git a/deploy/install-auto-deploy-sudoers.sh b/deploy/install-auto-deploy-sudoers.sh new file mode 100755 index 0000000..ec02973 --- /dev/null +++ b/deploy/install-auto-deploy-sudoers.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Install the narrow sudoers rule required by teleo-auto-deploy.service. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SOURCE="$REPO_ROOT/deploy/sudoers/teleo-auto-deploy" +TARGET="/etc/sudoers.d/teleo-auto-deploy" + +if [ "$(id -u)" -ne 0 ]; then + echo "ERROR: run as root on the VPS" >&2 + exit 1 +fi + +install -m 0440 "$SOURCE" "$TARGET" +visudo -cf "$TARGET" +echo "Installed $TARGET" diff --git a/deploy/sudoers/teleo-auto-deploy b/deploy/sudoers/teleo-auto-deploy new file mode 100644 index 0000000..48b1594 --- /dev/null +++ b/deploy/sudoers/teleo-auto-deploy @@ -0,0 +1,14 @@ +# Narrow service privileges for teleo-auto-deploy.service, which runs as teleo. +# Keep command forms aligned with deploy/auto-deploy.sh. +teleo ALL=(root) NOPASSWD: /usr/bin/systemctl restart leoclean-gateway +teleo ALL=(root) NOPASSWD: /bin/systemctl restart leoclean-gateway +teleo ALL=(root) NOPASSWD: /usr/bin/systemctl restart leoclean-gateway.service +teleo ALL=(root) NOPASSWD: /bin/systemctl restart leoclean-gateway.service +teleo ALL=(root) NOPASSWD: /usr/bin/systemctl status leoclean-gateway +teleo ALL=(root) NOPASSWD: /bin/systemctl status leoclean-gateway +teleo ALL=(root) NOPASSWD: /usr/bin/systemctl status leoclean-gateway.service +teleo ALL=(root) NOPASSWD: /bin/systemctl status leoclean-gateway.service +teleo ALL=(root) NOPASSWD: /usr/bin/journalctl -u leoclean-gateway +teleo ALL=(root) NOPASSWD: /bin/journalctl -u leoclean-gateway +teleo ALL=(root) NOPASSWD: /usr/bin/journalctl -u leoclean-gateway.service +teleo ALL=(root) NOPASSWD: /bin/journalctl -u leoclean-gateway.service diff --git a/tests/test_teleo_agent_systemd.py b/tests/test_teleo_agent_systemd.py index f8e0101..38a3bab 100644 --- a/tests/test_teleo_agent_systemd.py +++ b/tests/test_teleo_agent_systemd.py @@ -83,15 +83,29 @@ def test_deploy_scripts_install_systemd_units_and_enable_agent_healthcheck(): def test_deploy_scripts_sync_leoclean_skills_and_restart_gateway_when_active(): auto_deploy = (REPO_ROOT / "deploy" / "auto-deploy.sh").read_text() manual_deploy = (REPO_ROOT / "deploy" / "deploy.sh").read_text() + sudoers = (REPO_ROOT / "deploy" / "sudoers" / "teleo-auto-deploy").read_text() assert 'LEOCLEAN_SKILLS_DIR="/home/teleo/.hermes/profiles/leoclean/skills"' in auto_deploy assert 'hermes-agent/leoclean-skills/vps/' in auto_deploy assert 'add_restart_if_unit_active leoclean-gateway' in auto_deploy + assert 'sudo systemctl restart "$svc"' in auto_deploy + assert "sudo systemctl restart $RESTART" not in auto_deploy + assert "NOPASSWD: /usr/bin/systemctl restart leoclean-gateway" in sudoers + assert "NOPASSWD: /bin/systemctl restart leoclean-gateway" in sudoers assert 'VPS_LEOCLEAN_SKILLS="/home/teleo/.hermes/profiles/leoclean/skills"' in manual_deploy assert 'hermes-agent/leoclean-skills/vps/' in manual_deploy assert 'systemctl is-active --quiet leoclean-gateway.service' in manual_deploy +def test_auto_deploy_sudoers_installer_is_root_only_and_visudo_checked(): + installer = (REPO_ROOT / "deploy" / "install-auto-deploy-sudoers.sh").read_text() + + assert 'TARGET="/etc/sudoers.d/teleo-auto-deploy"' in installer + assert 'id -u' in installer + assert 'install -m 0440 "$SOURCE" "$TARGET"' in installer + assert 'visudo -cf "$TARGET"' in installer + + def test_gcp_leoclean_skill_sync_targets_parallel_runtime_without_secrets(): script_path = REPO_ROOT / "deploy" / "sync-gcp-leoclean-skills.sh" script = script_path.read_text()