79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
"""Tests for rsync push sudo elevation (non-root auto_sudo policy)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from server.domain.models import Server
|
|
from server.utils.rsync_elevation import (
|
|
RSYNC_SUDO_RECEIVER_PATH,
|
|
is_root_ssh_user,
|
|
rsync_elevation_log_hint,
|
|
rsync_receiver_path_for_push,
|
|
)
|
|
|
|
|
|
def test_root_ssh_skips_sudo_rsync():
|
|
server = Server(name="t", domain="1.2.3.4", username="root")
|
|
assert is_root_ssh_user(server) is True
|
|
assert rsync_receiver_path_for_push(server) is None
|
|
assert rsync_elevation_log_hint(server) is None
|
|
|
|
|
|
def test_non_root_default_auto_sudo_uses_sudo_rsync():
|
|
"""Unset extra_attrs → normalize to auto_sudo → sudo rsync (Ubuntu/deploy 默认)."""
|
|
server = Server(name="t", domain="1.2.3.4", username="ubuntu")
|
|
assert rsync_receiver_path_for_push(server) == RSYNC_SUDO_RECEIVER_PATH
|
|
assert rsync_elevation_log_hint(server) == "rsync=sudo"
|
|
|
|
|
|
def test_non_root_always_sudo_uses_sudo_rsync():
|
|
server = Server(
|
|
name="t",
|
|
domain="1.2.3.4",
|
|
username="deploy",
|
|
extra_attrs={"files_elevation": "always_sudo"},
|
|
)
|
|
assert rsync_receiver_path_for_push(server) == RSYNC_SUDO_RECEIVER_PATH
|
|
|
|
|
|
def test_non_root_off_disables_sudo_rsync():
|
|
server = Server(
|
|
name="t",
|
|
domain="1.2.3.4",
|
|
username="deploy",
|
|
extra_attrs={"files_elevation": "off"},
|
|
)
|
|
assert rsync_receiver_path_for_push(server) is None
|
|
assert rsync_elevation_log_hint(server) is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_rsync_push_passes_sudo_path_for_non_root(monkeypatch, tmp_path):
|
|
import asyncio
|
|
|
|
from server.application.services import sync_engine_v2 as se
|
|
|
|
source = tmp_path / "src"
|
|
source.mkdir()
|
|
(source / "a.txt").write_text("hi", encoding="utf-8")
|
|
|
|
server = Server(
|
|
name="t",
|
|
domain="127.0.0.1",
|
|
username="ubuntu",
|
|
ssh_key_path="/nonexistent/key",
|
|
)
|
|
|
|
captured: list[str | None] = []
|
|
|
|
async def fake_execute(_server, _src, _dest, **kwargs):
|
|
captured.append(kwargs.get("rsync_receiver_path"))
|
|
return {"exit_code": 0, "stdout": "", "stderr": ""}
|
|
|
|
monkeypatch.setattr(se, "_execute_rsync_push", fake_execute)
|
|
|
|
result = await se._rsync_push(server, str(source), "/www/wwwroot/site")
|
|
assert captured == [RSYNC_SUDO_RECEIVER_PATH]
|
|
assert result["elevated"] is True
|