test: reset Windows native runs from clean baseline
This commit is contained in:
@@ -192,7 +192,7 @@ scripts/test-e2e [--scenario NAME|all] [--run-id ID] [--resume]
|
||||
scripts/test-env doctor|coverage|status|logs|collect|recover|reuse|stop|reset|purge|gc ...
|
||||
scripts/build build|verify|doctor|recover|clean (pinned toolchain; host-safe)
|
||||
scripts/windows/build-test-bundle --run-id ID --config FILE [--ca FILE]
|
||||
scripts/windows/test-host status|prepare|stage|run|collect|stop|reset|recover
|
||||
scripts/windows/test-host status|prepare|stage|install|run|collect|stop|reset|recover
|
||||
```
|
||||
|
||||
Scripts are thin, reviewed orchestration wrappers. `scripts/test-unit` invokes
|
||||
@@ -813,8 +813,8 @@ mirror; update both documents when the fixture is reprovisioned.
|
||||
| Diagnostic VRDE | Enabled at `192.168.50.162:3389`, external/`VBoxAuthSimple` authentication, input/display enabled, audio/USB/clipboard/RDPDR disabled; diagnostic-only because client compatibility is unreliable |
|
||||
| Native Windows RDP | Disabled in baseline (`TermService` stopped, `fDenyTSConnections=1`); port 3390 must not be treated as a usable control endpoint |
|
||||
| Test account | Local `rvboxtest`; split-token local administrator; console session 1 observed; Guest Control verified with `whoami`, `whoami /groups`, and `query user` |
|
||||
| Baseline | `baseline-clean` (UUID `5e79176a-3e56-4c5d-bb61-a405a6dcdd59`) and child `baseline-disk-first` (UUID `9430a9a4-754a-4b22-beaa-8dfd90043f5b`); both are clean and must be retained |
|
||||
| Last checked state | `poweroff`, current snapshot `baseline-disk-first`; the harness must re-check state and leave the VM powered off after cleanup |
|
||||
| Baseline | Reset target `baseline-clean` (UUID `5e79176a-3e56-4c5d-bb61-a405a6dcdd59`): no RVBox service, tray registration, state, logs, or staged binary. Retain child `baseline-disk-first` (UUID `9430a9a4-754a-4b22-beaa-8dfd90043f5b`) for diagnostics only. |
|
||||
| Last checked state | `poweroff`, current snapshot `baseline-disk-first`; restore `baseline-clean` before native runs, and leave that reset target selected after cleanup |
|
||||
|
||||
The guest password, SSH key, and any host account secret are test secrets. Keep
|
||||
them in the operator/CI secret store or a mode-600 password file outside the
|
||||
@@ -826,17 +826,19 @@ overridden with `RVBOX_TEST_GUEST_PASSWORD_FILE`; the password value is never a
|
||||
default or repository value. The account name and VM metadata above are not
|
||||
credentials.
|
||||
|
||||
Guest Control uses this split-token administrator's medium-integrity token; its
|
||||
Administrators SID is deny-only. Do not bypass UAC to create the service during
|
||||
automation. A one-time interactive elevated fixture bootstrap must install the
|
||||
test `RVBoxClient` service in the reset baseline and grant `rvboxtest` only
|
||||
query/change-config/start/stop service access plus write access to its dedicated
|
||||
test subtree. Each native run then changes that bootstrapped service's explicit
|
||||
image/configuration and starts it through SCM. This is fixture administration,
|
||||
not a second product worker/elevation broker or a Task Scheduler dependency.
|
||||
Keep the exact service SDDL and test-subtree ACL with the fixture record before
|
||||
taking its replacement baseline snapshot. The production installer/UAC flow is
|
||||
tested separately through an interactive elevated lane.
|
||||
Guest Control uses `rvboxtest`'s split-token, medium-integrity identity; its
|
||||
Administrators SID is deny-only. The reset snapshot contains no RVBox
|
||||
installation and the harness proves that `RVBoxClient` is absent immediately
|
||||
after every `prepare`. Do not bypass UAC or turn this active-session test user
|
||||
into an always-elevated account. Instead, provision a separate fixture-only
|
||||
full-token administrator, with its username and a mode-0600 host-side password
|
||||
file held outside the repository. `test-host install` uses that identity only
|
||||
to execute the staged real `rvbox.exe --install-service` path and proves it by
|
||||
polling SCM. It is not an RVBox product process, a service/broker, or a Task
|
||||
Scheduler dependency, and it never enters the daemon's command-context choice.
|
||||
The normal active `rvboxtest` session remains the target for execution-role
|
||||
tests. The consent-prompt branch itself remains an interactive UAC test; an
|
||||
invisible Guest Control session must never answer it.
|
||||
|
||||
For this provisioned lane, the approved host-only credential-file location is
|
||||
`/home/cabbage/.local/share/rvbox-secrets/rvbox-win10-test.password`. It must
|
||||
@@ -861,7 +863,7 @@ identity in the run manifest:
|
||||
```sh
|
||||
export RVBOX_TEST_VBOX_HOST=helium-remote
|
||||
export RVBOX_TEST_VBOX_VM=rvbox-win10-test
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT=baseline-disk-first
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT=baseline-clean
|
||||
export RVBOX_TEST_GUEST_USER=rvboxtest
|
||||
export RVBOX_TEST_GUEST_PASSWORD_FILE=/secure/outside-repo/rvbox-win10-test.password
|
||||
```
|
||||
@@ -880,7 +882,7 @@ ssh "$RVBOX_TEST_VBOX_HOST" \
|
||||
|
||||
# Restore only while powered off, then boot without a GUI.
|
||||
ssh "$RVBOX_TEST_VBOX_HOST" \
|
||||
'VBoxManage snapshot "rvbox-win10-test" restore "baseline-disk-first"'
|
||||
'VBoxManage snapshot "rvbox-win10-test" restore "baseline-clean"'
|
||||
ssh "$RVBOX_TEST_VBOX_HOST" \
|
||||
'VBoxManage startvm "rvbox-win10-test" --type headless'
|
||||
|
||||
@@ -928,7 +930,7 @@ Use this shutdown/reset sequence for every native run:
|
||||
acpipowerbutton` and poll. Use `controlvm ... poweroff` only for a hung,
|
||||
disposable test; it intentionally loses guest state.
|
||||
3. Collect diagnostics while the VM is still available, then restore
|
||||
`baseline-disk-first` and verify the snapshot UUID/current marker.
|
||||
`baseline-clean` and verify the snapshot UUID/current marker.
|
||||
4. Leave the VM powered off after cleanup. Never delete either baseline
|
||||
snapshot, unregister the VM, or modify `win10_dev` (that name refers to a
|
||||
stale unregistered configuration with a missing disk on this host).
|
||||
|
||||
+50
-33
@@ -6,7 +6,9 @@ Windows release matrix. Keep the values here in sync with the VM before adding
|
||||
or changing native test automation.
|
||||
|
||||
Last configuration check: 2026-09-09 UTC. The VM was observed powered off with
|
||||
`baseline-disk-first` selected. A test run must still perform its own identity,
|
||||
`baseline-disk-first` selected. The native harness now targets `baseline-clean`;
|
||||
the fixture must be rechecked and its current snapshot returned to that clean
|
||||
baseline before native runs resume. A test run must still perform its own identity,
|
||||
snapshot, readiness, and exclusive-lease checks rather than relying on that
|
||||
observation.
|
||||
|
||||
@@ -25,7 +27,7 @@ observation.
|
||||
| Guest OS | Windows 10 Pro 22H2, build `19045.2006`, en-US, BIOS boot |
|
||||
| Guest account | Local `rvboxtest`; split-token local administrator; console session 1 was observed during provisioning |
|
||||
| Guest Additions | `7.2.16r174877`; readiness requires published Guest Additions version and Windows OS-release properties (this build does not publish a RunLevel property) |
|
||||
| Last observed state | `poweroff`; current snapshot `baseline-disk-first` |
|
||||
| Last observed state | `poweroff`; current snapshot `baseline-disk-first` (must be restored to `baseline-clean` before native runs) |
|
||||
|
||||
The Guest Control credential is test-only. The account name is safe to record,
|
||||
but the password value is intentionally not committed to this repository. On
|
||||
@@ -84,7 +86,9 @@ and collection. Do not expose the VM's RDP endpoints beyond the test LAN.
|
||||
|
||||
## Snapshots and reset contract
|
||||
|
||||
Two clean snapshots exist and must be retained:
|
||||
Two clean snapshots exist and must be retained. `baseline-clean` is the only
|
||||
reset target: it contains no `RVBoxClient` SCM service, RVBox tray Run-key
|
||||
registration, RVBox state, logs, or staged binaries.
|
||||
|
||||
| Snapshot | UUID | Description |
|
||||
| --- | --- | --- |
|
||||
@@ -95,12 +99,12 @@ Restore only while the VM is powered off. Every destructive or potentially
|
||||
stateful run must:
|
||||
|
||||
1. Acquire the run lease and verify the VM name, UUID, and snapshot UUID.
|
||||
2. Restore `baseline-disk-first` if the current state is not the baseline.
|
||||
2. Restore `baseline-clean` if the current state is not the baseline.
|
||||
3. Start headless and wait for `VMState=running` plus Guest Additions readiness.
|
||||
4. Run the bounded test, collect redacted artifacts, and close every Guest
|
||||
Control process that was opened by the run.
|
||||
5. Request a graceful guest shutdown and wait for `VMState=poweroff`.
|
||||
6. Restore `baseline-disk-first` again and leave the VM powered off.
|
||||
6. Restore `baseline-clean` again and leave the VM powered off.
|
||||
|
||||
Use `controlvm ... poweroff` only for a hung, disposable test; it can lose
|
||||
guest state. Never delete either clean snapshot, unregister the VM, or alter
|
||||
@@ -112,7 +116,7 @@ The canonical adapter is the POSIX controller script
|
||||
[`scripts/windows/test-host`](../scripts/windows/test-host). It runs from the
|
||||
Linux controller and invokes `VBoxManage` only through SSH on Helium; the
|
||||
fixture host is Arch Linux and does not provide PowerShell. Its actions are
|
||||
`status`, `prepare`, `stage`, `run`, `collect`, `stop`, `reset`, and `recover`.
|
||||
`status`, `prepare`, `stage`, `install`, `run`, `collect`, `stop`, `reset`, and `recover`.
|
||||
The legacy [`test-host.ps1`](../scripts/windows/test-host.ps1) is retained only
|
||||
as a reference for a future Windows-hosted fixture and is not the Helium lane.
|
||||
|
||||
@@ -122,8 +126,8 @@ The adapter takes identity and credentials only from its environment:
|
||||
export RVBOX_TEST_VBOX_HOST=helium-remote
|
||||
export RVBOX_TEST_VBOX_VM=rvbox-win10-test
|
||||
export RVBOX_TEST_VBOX_VM_UUID=6cdc114f-71e5-4167-a394-e922e14e6f5c
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT=baseline-disk-first
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT_UUID=9430a9a4-754a-4b22-beaa-8dfd90043f5b
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT=baseline-clean
|
||||
export RVBOX_TEST_VBOX_SNAPSHOT_UUID=5e79176a-3e56-4c5d-bb61-a405a6dcdd59
|
||||
export RVBOX_TEST_GUEST_USER=rvboxtest
|
||||
export RVBOX_TEST_GUEST_PASSWORD_FILE=/home/cabbage/.local/share/rvbox-secrets/rvbox-win10-test.password
|
||||
```
|
||||
@@ -145,34 +149,47 @@ the single `/c` payload are preserved.
|
||||
|
||||
`stage` accepts one versioned non-secret test bundle and copies it first to an
|
||||
exact host staging directory, then to
|
||||
`C:\\ProgramData\\RVBox\\test-runs\\<run-id>`. `run` never directly executes the
|
||||
GUI-subsystem `rvbox.exe` through Guest Control. It uses `sc.exe` and other
|
||||
console-safe management tools to start/query/stop the installed RVBox service,
|
||||
then checks the service's real health endpoint, named-pipe response, durable
|
||||
state, and agent-server results. Before a WSS scenario it performs a bounded
|
||||
guest-to-nginx connectivity and CA-trust probe. The resulting service and
|
||||
artifact paths are recorded in the run report and reclaimed by the snapshot
|
||||
reset rather than broad guest deletion.
|
||||
`C:\\ProgramData\\RVBox\\test-runs\\<run-id>`. `install` performs the one
|
||||
purposeful direct Guest Control launch of the staged GUI-subsystem executable,
|
||||
using only the fixture provisioner's high token; because this VirtualBox build
|
||||
cannot reliably report that process's exit, SCM `RUNNING` is the completion
|
||||
proof. After installation, `run` uses `sc.exe` and other console-safe management
|
||||
tools to reconfigure/start/query/stop the installed RVBox service, then checks
|
||||
the service's real health endpoint, named-pipe response, durable state, and
|
||||
agent-server results. Before a WSS scenario it performs a bounded guest-to-nginx
|
||||
connectivity and CA-trust probe. The resulting service and artifact paths are
|
||||
recorded in the run report and reclaimed by the snapshot reset rather than broad
|
||||
guest deletion.
|
||||
|
||||
### Required one-time service bootstrap
|
||||
### Clean baseline and non-interactive installation
|
||||
|
||||
Guest Control launches `rvboxtest` with its filtered, medium-integrity UAC
|
||||
token: the Administrators SID is deny-only. The harness must not bypass UAC to
|
||||
create services. Before native service tests can run, an operator must use a
|
||||
trusted interactive elevated session to install one test-only `RVBoxClient`
|
||||
service in the baseline and grant only `rvboxtest` the service rights required
|
||||
by the harness: query status/configuration, change its image/configuration,
|
||||
start, and stop. The test account also needs write access only to the dedicated
|
||||
`C:\\ProgramData\\RVBox\\test-runs` subtree; SYSTEM retains ownership of normal
|
||||
RVBox state and logs. Record the resulting service SDDL and subtree ACL in this
|
||||
document before taking a new reset snapshot.
|
||||
`rvboxtest` deliberately remains a split-token administrator. Guest Control
|
||||
therefore launches it at medium integrity and it must never be used to create
|
||||
or modify machine-wide SCM state. The reset snapshot has no RVBox installation.
|
||||
|
||||
Each run then stages an exact bundle, changes the bootstrapped service image to
|
||||
that run's explicit `--service --config` command line, and starts it through
|
||||
SCM. The one-time bootstrap is fixture administration, not a second RVBox
|
||||
process, runtime elevation broker, or Task Scheduler mechanism. Native tests
|
||||
for the production installer/UAC flow remain a separately interactive test;
|
||||
they cannot be automated through this filtered Guest Control token.
|
||||
To automate the real install path, provision one separate **fixture-only**
|
||||
full-token local administrator and retain its username/password solely in the
|
||||
Helium secret store. It must be a genuinely high-integrity Guest Control token;
|
||||
do not globally disable UAC or change `rvboxtest` into an always-elevated user.
|
||||
The normal harness receives it only through these environment variables:
|
||||
|
||||
```sh
|
||||
export RVBOX_TEST_PROVISIONER_USER=FIXTURE_ONLY_FULL_ADMIN
|
||||
export RVBOX_TEST_PROVISIONER_PASSWORD_FILE=/home/cabbage/.local/share/rvbox-secrets/rvbox-win10-test-provisioner.password
|
||||
```
|
||||
|
||||
Both files remain mode `0600` on Helium and neither value is recorded in run
|
||||
reports or artifacts. `test-host install` first verifies that the reset guest
|
||||
has no `RVBoxClient`, checks the provisioner's High Mandatory Level, invokes
|
||||
the actual staged `rvbox.exe --install-service --config ...`, and polls SCM for
|
||||
`RUNNING`. `run` may then exercise reconfigure/start/restart paths. Snapshot
|
||||
reset removes the installed service and all RVBox data again.
|
||||
|
||||
The provisioner is fixture administration only: it is not shipped with RVBox,
|
||||
not a product service/broker, not a Task Scheduler dependency, and never
|
||||
participates in command-context selection. The separately interactive UAC
|
||||
prompt route remains a small manual test because an invisible Guest Control
|
||||
session cannot safely approve a consent prompt.
|
||||
|
||||
## Scope and known limitations
|
||||
|
||||
|
||||
+23
-18
@@ -49,6 +49,7 @@ scripts/windows/build-test-bundle \
|
||||
scripts/windows/test-host prepare --run-id windows-smoke
|
||||
scripts/windows/test-host stage --run-id windows-smoke \
|
||||
--bundle .test-runs/windows-smoke/windows-bundle
|
||||
scripts/windows/test-host install --run-id windows-smoke
|
||||
```
|
||||
|
||||
The bundle manifest records the source commit and SHA-256 of every bundled
|
||||
@@ -151,16 +152,17 @@ The provisioned fixture's non-secret identity values, including the host-local
|
||||
password-file path, are safe defaults in that script and may be overridden for
|
||||
another documented fixture; the password itself is never embedded.
|
||||
|
||||
The native lifecycle is `status`, `prepare`, `stage`, `run`, `collect`,
|
||||
`stop`, and `reset`. `prepare` verifies the VM and snapshot UUIDs, restores the
|
||||
baseline, starts headless, waits for Guest Additions, and records the selected
|
||||
login fixture. `stage` copies a versioned non-secret test bundle through a
|
||||
run-specific host directory to a run-specific guest directory. `run` starts
|
||||
the real RVBox SCM service and observes it through SCM, the local health/tray
|
||||
pipe, durable artifacts, and the test agent endpoint; it must not invoke the
|
||||
GUI-subsystem `rvbox.exe` directly through Guest Control. `collect` obtains
|
||||
only bounded/redacted artifacts, and `reset` restores the exact baseline and
|
||||
leaves the VM powered off.
|
||||
The native lifecycle is `status`, `prepare`, `stage`, `install`, `run`,
|
||||
`collect`, `stop`, and `reset`. `prepare` verifies the VM and snapshot UUIDs,
|
||||
restores the clean baseline, starts headless, waits for Guest Additions, and
|
||||
proves that `RVBoxClient` is absent. `stage` copies a versioned non-secret test
|
||||
bundle through a run-specific host directory to a run-specific guest directory.
|
||||
`install` uses the fixture-only high-integrity automation principal to invoke
|
||||
the real `rvbox.exe --install-service` path and proves completion through SCM.
|
||||
`run` is for reconfiguration/restart scenarios after that first installation.
|
||||
Neither action invokes the GUI-subsystem executable directly with the normal
|
||||
Guest Control account. `collect` obtains only bounded/redacted artifacts, and
|
||||
`reset` restores the exact clean baseline and leaves the VM powered off.
|
||||
|
||||
This service-driven protocol is required because VirtualBox Guest Control
|
||||
7.2.16 does not reliably complete a direct GUI-subsystem `rvbox.exe` run;
|
||||
@@ -171,14 +173,17 @@ also performs a bounded guest-to-nginx HTTPS/TCP readiness probe before it
|
||||
starts the service. Wine and protocol stubs are not equivalent Windows
|
||||
coverage.
|
||||
|
||||
The fixture needs a one-time operator-approved service bootstrap before the
|
||||
SCM smoke lane can run: Guest Control supplies the split-token administrator's
|
||||
medium UAC token, so it cannot safely install services. The bootstrap installs
|
||||
the test service in the reset baseline and grants the test account only the SCM
|
||||
query/change-config/start/stop rights plus access to its dedicated test subtree.
|
||||
Each run then reconfigures and starts that one service. This does not add a
|
||||
product broker or use Task Scheduler; it is fixture setup. See
|
||||
[testing-vm.md](testing-vm.md) for the exact boundary.
|
||||
The clean baseline intentionally contains no RVBox service, tray registration,
|
||||
or RVBox state. Guest Control supplies `rvboxtest` with a filtered medium UAC
|
||||
token, so it cannot safely perform the first machine-wide install. The fixture
|
||||
therefore has a separate test-only full-token automation principal, whose
|
||||
username and mode-600 host-side password-file are provided only as
|
||||
`RVBOX_TEST_PROVISIONER_USER` and `RVBOX_TEST_PROVISIONER_PASSWORD_FILE` for
|
||||
the `install`/machine-mutation actions. It is not an RVBox process, service,
|
||||
broker, or Task Scheduler dependency, and it is never used to choose a command
|
||||
execution context. The normal `rvboxtest` console session remains the subject
|
||||
of active-user and elevation tests. See [testing-vm.md](testing-vm.md) for the
|
||||
exact fixture contract.
|
||||
|
||||
The VM is the minimum smoke lane, so native multi-session/ambiguous-session,
|
||||
Server Core, and older-build entries remain explicitly blocked until their own
|
||||
|
||||
Reference in New Issue
Block a user