Files
GTI_GERENCIADOR_FISCAL/central/tests/test_agent_windows_install_script.py
T
gtiandClaude Sonnet 5 8d6122c096 feat: Agent distribution with secure enrollment from the control panel
One universal Windows Agent package per version (agent_releases: version/
platform/architecture/sha256/status DRAFT|PUBLISHED|REVOKED; the binary
lives on a local release-storage volume, never in PostgreSQL). An operator
creates a pending installation (agent_enrollments) from Agents / Servidores
-> + Nova instalação, then either downloads it directly or generates a
one-time HTTPS link (short TTL, single use). Either path streams the
package plus a freshly minted enrollment.json whose token is never written
to storage in plaintext, only its SHA-256 hash. On the client host,
gti-agent.ps1 install-auto verifies the bundle's SHA-256, refuses a non-
HTTPS Hub, enrolls via POST /v1/agents/enroll (deleting the enrollment
token immediately after, success or failure), writes an ACL-restricted
.env with the newly issued permanent Agent token, and registers the
Windows Service without starting it (Firebird stays unconfigured on
purpose). Idempotent, replay-proof, rate-limited per IP, fully audited,
never logs a secret.

Migration 0022_agent_releases_enrollment (verified fresh-DB ==
upgrade-from-0021 by pg_dump diff). GTI_FISCAL_VERSION/AGENT_VERSION
bumped to 1.1.0 as the single source of truth across code, packages, the
release manifest and every published AgentRelease row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 13:19:31 -03:00

64 lines
2.5 KiB
Python

"""Static checks on deploy/agent-windows/gti-agent.ps1's `install-auto` command
(the zero-touch path driven by the enrollment bundle from the panel). No
Windows host is available in CI, so these are text-level guarantees — the
same properties are exercised for real in the manual Windows smoke test
described in docs/PILOT_DEPLOYMENT.md.
"""
import re
from pathlib import Path
SCRIPT = (Path(__file__).parents[2] / "deploy" / "agent-windows" / "gti-agent.ps1").read_text(encoding="utf-8")
def install_auto_block() -> str:
start = SCRIPT.index("'install-auto' {")
end = SCRIPT.index("'configure' {")
return SCRIPT[start:end]
def test_install_auto_is_a_registered_command():
validate_set = re.search(r"ValidateSet\(([^)]*)\)", SCRIPT).group(1)
assert "'install-auto'" in validate_set
def test_install_auto_never_enables_firebird_writes():
block = install_auto_block()
assert "FIREBIRD_WRITES=0" in block
assert "FIREBIRD_WRITES=1" not in SCRIPT # nowhere in the whole script, not just this block
def test_install_auto_refuses_a_non_https_hub():
assert "hub_url -notmatch '^https://'" in install_auto_block()
def test_install_auto_verifies_package_sha256_before_installing():
block = install_auto_block()
assert "SHA256_VALIDATION" in block and "Get-FileHash" in block
assert block.index("SHA256_VALIDATION") < block.index("Invoke-RestMethod") # integrity checked before any network call
def test_install_auto_deletes_the_enrollment_bundle_after_use():
block = install_auto_block()
assert "Remove-Item $EnrollmentFile -Force" in block
assert block.index("Remove-Item $EnrollmentFile") > block.index("Invoke-RestMethod") # only after a successful enroll
def test_install_auto_registers_but_never_starts_the_service():
block = install_auto_block()
assert "install" in block and "Start-Service" not in block # Firebird config is still missing; starting it is a separate, explicit step
def test_install_auto_never_hardcodes_a_client_firebird_path():
block = install_auto_block()
assert "'FIREBIRD_DATABASE_PATH='" in block # written, but as an empty placeholder (no real path baked in)
def test_install_auto_restricts_the_env_file_acl():
block = install_auto_block()
assert "icacls $EnvFile /inheritance:r /grant:r 'Administrators:(F)' 'SYSTEM:(F)'" in block
def test_install_auto_is_idempotent_when_already_enrolled():
block = install_auto_block()
assert "Already enrolled and installed" in block and "exit 0" in block