fix: deliver RDP bundle via SAC HTTP zip download, not WinRM chunks (0.20.15)
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
"""WinRM command builder, bundle push and CLIXML error parsing tests."""
|
||||
"""WinRM bundle delivery and CLIXML error parsing tests."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.services.rdp_bundle_delivery import build_rdp_bundle_zip, get_rdp_bundle_zip, register_rdp_bundle_zip
|
||||
from app.services.winrm_connect import (
|
||||
RDP_BUNDLE_REQUIRED,
|
||||
RDP_REMOTE_STAGING,
|
||||
@@ -10,9 +11,9 @@ from app.services.winrm_connect import (
|
||||
_clixml_to_plain,
|
||||
_custom_deploy_body,
|
||||
_deploy_from_staging_body,
|
||||
_download_bundle_body,
|
||||
_prepare_staging_body,
|
||||
_winrm_failure_detail,
|
||||
_write_file_chunk_body,
|
||||
run_winrm_rdp_monitor_update,
|
||||
)
|
||||
|
||||
@@ -23,36 +24,42 @@ def test_prepare_staging_recreates_remote_dir():
|
||||
assert "_sac_staging" in script
|
||||
|
||||
|
||||
def test_download_bundle_uses_invoke_webrequest():
|
||||
script = _download_bundle_body(
|
||||
RDP_REMOTE_STAGING,
|
||||
"https://sac.example/api/v1/agent/rdp-bundle/token",
|
||||
)
|
||||
assert "Invoke-WebRequest" in script
|
||||
assert "Expand-Archive" in script
|
||||
assert "WriteAllBytes" not in script
|
||||
|
||||
|
||||
def test_deploy_from_staging_runs_local_bundle():
|
||||
script = _deploy_from_staging_body(RDP_REMOTE_STAGING)
|
||||
assert "-SourceShareRoot" in script
|
||||
assert "Deploy-LoginMonitor.ps1" in script
|
||||
|
||||
|
||||
def test_write_file_chunk_body_supports_append():
|
||||
first = _write_file_chunk_body(r"C:\temp\a.ps1", "YQ==", append=False)
|
||||
second = _write_file_chunk_body(r"C:\temp\a.ps1", "Yg==", append=True)
|
||||
assert "WriteAllBytes" in first
|
||||
assert "Append" in second
|
||||
|
||||
|
||||
def test_custom_deploy_script_uses_literal_path():
|
||||
script = _custom_deploy_body(r"C:\tmp\Deploy-LoginMonitor.ps1")
|
||||
assert r"C:\tmp\Deploy-LoginMonitor.ps1" in script
|
||||
assert "Test-Path -LiteralPath" in script
|
||||
|
||||
|
||||
def test_custom_deploy_script_escapes_single_quotes():
|
||||
script = _custom_deploy_body(r"C:\Users\O'Brien\Deploy-LoginMonitor.ps1")
|
||||
assert "O''Brien" in script
|
||||
|
||||
|
||||
def test_run_winrm_rdp_monitor_update_pushes_bundle_from_sac_git(tmp_path: Path):
|
||||
def test_rdp_bundle_zip_roundtrip(tmp_path: Path):
|
||||
repo = tmp_path / "repo"
|
||||
repo.mkdir()
|
||||
for name in RDP_BUNDLE_REQUIRED:
|
||||
(repo / name).write_text(name, encoding="utf-8")
|
||||
zip_bytes = build_rdp_bundle_zip(repo, tuple(RDP_BUNDLE_REQUIRED))
|
||||
token = register_rdp_bundle_zip(zip_bytes)
|
||||
assert get_rdp_bundle_zip(token) == zip_bytes
|
||||
|
||||
|
||||
def test_run_winrm_rdp_monitor_update_downloads_bundle_from_sac(tmp_path: Path):
|
||||
repo = tmp_path / "repo"
|
||||
repo.mkdir()
|
||||
for name in RDP_BUNDLE_REQUIRED:
|
||||
(repo / name).write_text(f"content-{name}", encoding="utf-8")
|
||||
(repo / "Sac-Client.ps1").write_text("Sac client", encoding="utf-8")
|
||||
|
||||
calls: list[str] = []
|
||||
|
||||
@@ -60,7 +67,9 @@ def test_run_winrm_rdp_monitor_update_pushes_bundle_from_sac_git(tmp_path: Path)
|
||||
calls.append(script)
|
||||
if "Remove-Item" in script:
|
||||
return WinRmCmdResult(ok=True, message="staging ok", target="pc", stdout="Staging ready")
|
||||
if "Deploy-LoginMonitor.ps1 missing" in script or "& $deploy" in script:
|
||||
if "Invoke-WebRequest" in script:
|
||||
return WinRmCmdResult(ok=True, message="download ok", target="pc", stdout="Bundle extracted")
|
||||
if "& $deploy" in script:
|
||||
return WinRmCmdResult(
|
||||
ok=True,
|
||||
message="WinRM OK (pc), exit 0",
|
||||
@@ -68,10 +77,11 @@ def test_run_winrm_rdp_monitor_update_pushes_bundle_from_sac_git(tmp_path: Path)
|
||||
stdout="deployed 1.2.3",
|
||||
exit_code=0,
|
||||
)
|
||||
return WinRmCmdResult(ok=True, message="chunk ok", target="pc", exit_code=0)
|
||||
return WinRmCmdResult(ok=True, message="ok", target="pc", exit_code=0)
|
||||
|
||||
with (
|
||||
patch("app.services.winrm_connect._fetch_rdp_bundle_dir", return_value=repo),
|
||||
patch("app.services.winrm_connect._bundle_download_url", return_value="https://sac.test/bundle.zip"),
|
||||
patch("app.services.winrm_connect.run_winrm_ps", side_effect=fake_run_ps),
|
||||
):
|
||||
result = run_winrm_rdp_monitor_update(
|
||||
@@ -82,24 +92,9 @@ def test_run_winrm_rdp_monitor_update_pushes_bundle_from_sac_git(tmp_path: Path)
|
||||
)
|
||||
|
||||
assert result.ok is True
|
||||
assert "SAC pushed" in result.stdout
|
||||
assert any("WriteAllBytes" in call or "Append" in call for call in calls)
|
||||
assert "git.exe" not in "\n".join(calls)
|
||||
|
||||
|
||||
def test_winrm_failure_detail_extracts_message_from_clixml():
|
||||
clixml = (
|
||||
"#< CLIXML\n"
|
||||
'<Objs><Obj><MS><S N="Message">Preparing modules for first use.</S>'
|
||||
'<S N="Message">Deploy-LoginMonitor.ps1 not found on client PC</S></MS></Obj></Objs>'
|
||||
)
|
||||
detail = _winrm_failure_detail("", clixml, 1)
|
||||
assert detail == "Deploy-LoginMonitor.ps1 not found on client PC"
|
||||
|
||||
|
||||
def test_winrm_failure_detail_prefers_plain_stderr():
|
||||
detail = _winrm_failure_detail("", "Access is denied", 5)
|
||||
assert detail == "Access is denied"
|
||||
assert "SAC served bundle" in result.stdout
|
||||
assert any("Invoke-WebRequest" in call for call in calls)
|
||||
assert not any("FromBase64String" in call for call in calls)
|
||||
|
||||
|
||||
def test_winrm_failure_detail_never_returns_raw_clixml_progress():
|
||||
@@ -109,7 +104,6 @@ def test_winrm_failure_detail_never_returns_raw_clixml_progress():
|
||||
)
|
||||
detail = _winrm_failure_detail("", clixml, 1)
|
||||
assert "#< CLIXML" not in detail
|
||||
assert "exit code" in detail.lower()
|
||||
|
||||
|
||||
def test_clixml_to_plain_strips_progress_only_blob():
|
||||
|
||||
Reference in New Issue
Block a user