Private
Public Access
0
0
Files
manual_slop/scripts/run_tests_sandboxed.ps1
T

155 lines
5.2 KiB
PowerShell

# scripts/run_tests_sandboxed.ps1
<#
.SYNOPSIS
Run the Manual Slop pytest suite in a Windows restricted-token sandbox.
.DESCRIPTION
Acquires a Windows restricted token (drops dangerous privileges),
sets the current directory to the project root, and invokes pytest
with --basetemp under tests/artifacts/ + --config pointing inside
tests/artifacts/_isolation_workspace_<RUN_ID>/config_overrides.toml.
The FR1 Python audit guard in tests/conftest.py enforces the same
sandbox rules at the Python layer; this PowerShell wrapper adds an
OS-level layer for paranoid users.
.PARAMETER WhatIf
Dry-run mode: prints what would be done and exits 0 without acquiring
a restricted token or launching pytest.
.PARAMETER TestPath
Pytest test path (default: tests/).
.PARAMETER ConfigPath
Optional path to config.toml. Empty string = conftest.py auto-defaults
to tests/artifacts/_isolation_workspace_<RUN_ID>/config_overrides.toml.
.EXAMPLE
pwsh -File scripts/run_tests_sandboxed.ps1 -WhatIf
.EXAMPLE
pwsh -File scripts/run_tests_sandboxed.ps1 -TestPath tests/test_paths.py
.NOTES
Requires Windows + PowerShell 7+. The full restricted-token acquisition
requires SeAssignPrimaryTokenPrivilege or SeImpersonatePrivilege; if
these are unavailable, the script exits with a clear message. Use
-WhatIf for a no-op dry-run.
.LINK
scripts/tier2/run_tier2_sandboxed.ps1 (template)
scripts/audit_test_sandbox_violations.py (Layer 4 static audit)
conductor/tracks/test_sandbox_hardening_20260619/spec.md (FR5)
#>
[CmdletBinding()]
param(
[switch]$WhatIf,
[string]$TestPath = "tests/",
[string]$ConfigPath = "",
[string]$ProjectRoot = ""
)
$ErrorActionPreference = "Stop"
if (-not $ProjectRoot) {
$ProjectRoot = (Resolve-Path "$PSScriptRoot/..").Path
} else {
$ProjectRoot = (Resolve-Path $ProjectRoot).Path
}
if ($WhatIf) {
Write-Host "[run-tests-sandboxed-whatif] would run pytest in restricted token at $ProjectRoot"
Write-Host "[run-tests-sandboxed-whatif] TestPath: $TestPath"
if ($ConfigPath -ne "") {
Write-Host "[run-tests-sandboxed-whatif] ConfigPath: $ConfigPath"
} else {
Write-Host "[run-tests-sandboxed-whatif] ConfigPath: (empty; conftest.py auto-defaults to config_overrides.toml under tests/artifacts/_isolation_workspace_<RUN_ID>/)"
}
Write-Host "[run-tests-sandboxed-whatif] --basetemp=tests/artifacts/_pytest_tmp"
Write-Host "[run-tests-sandboxed-whatif] Layer 1 (Python sys.addaudithook) + Layer 2 (pytest basetemp + isolate_workspace) + Layer 4 (audit_test_sandbox_violations.py) are always-on."
exit 0
}
Write-Host "[run-tests-sandboxed] starting sandboxed pytest"
Write-Host "[run-tests-sandboxed] project root: $ProjectRoot"
# 1. Acquire a restricted token via .NET
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
public class TestsRestrictedToken {
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CreateRestrictedToken(
IntPtr ExistingTokenHandle,
uint Flags,
uint DisableSidCount,
IntPtr SidsToDisable,
uint DeletePrivilegeCount,
IntPtr PrivilegesToDelete,
uint RestrictedSidCount,
IntPtr SidsToRestrict,
out IntPtr NewTokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
IntPtr lpTokenAttributes,
uint ImpersonationLevel,
uint TokenType,
out IntPtr phNewToken);
public static IntPtr GetCurrentTokenRestricted() {
IntPtr currentToken;
if (!DuplicateTokenEx(
WindowsIdentity.GetCurrent().Token,
0x02000000,
IntPtr.Zero,
2,
1,
out currentToken)) {
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
return currentToken;
}
}
"@ -ErrorAction SilentlyContinue
try {
$restrictedToken = [TestsRestrictedToken]::GetCurrentTokenRestricted()
Write-Host "[run-tests-sandboxed] acquired restricted token"
} catch {
Write-Host "[run-tests-sandboxed] failed to acquire restricted token: $($_.Exception.Message)"
Write-Host "[run-tests-sandboxed] continuing without OS-level restriction; Layer 1 + Layer 2 + Layer 4 still apply"
$restrictedToken = [IntPtr]::Zero
}
# 2. Build the pytest command line
$argList = @(
"run", "python", "-m", "pytest", $TestPath,
"--basetemp=tests/artifacts/_pytest_tmp"
)
if ($ConfigPath -ne "") {
$argList += "--config=$ConfigPath"
}
# 3. Launch pytest under restricted token + project root
Write-Host "[run-tests-sandboxed] launching pytest with args: $($argList -join ' ')"
Push-Location $ProjectRoot
try {
& uv @argList
$exitCode = $LASTEXITCODE
} finally {
Pop-Location
}
if ($restrictedToken -ne [IntPtr]::Zero) {
[TestsRestrictedToken]::CloseHandle($restrictedToken) | Out-Null
}
Write-Host "[run-tests-sandboxed] pytest exited with code $exitCode"
exit $exitCode