feat: add self-enrolling Windows Agent package

This commit is contained in:
lussierj committed 2026-08-28 17:50:39 +00:00
1 parent b9b5e5e36f
commit abf5654a25
20 files changed
+1834 -42

No files matched your search

@@ -0,0 +1,633 @@
"""Runtime PostgreSQL isolation tests for Agent-owned machine transport."""
import asyncio
import json
import os
import unittest
from uuid import UUID
import psycopg
from fastapi import HTTPException
from starlette.requests import Request
from app.agent_zones.repository import AgentZoneRepository
from app.agent_zones.service import AgentZoneService
from app.config import settings
from app.main import (
minerops_agent_api3_enrichment,
minerops_agent_miner_enrichment_v2,
minerops_agent_miner_enrichment_v3,
)
SITE_A = UUID("00000000-0000-4000-8000-000000001710")
SITE_B = UUID("00000000-0000-4000-8000-000000001711")
ZONE_A = UUID("00000000-0000-4000-8000-000000001712")
ZONE_B = UUID("00000000-0000-4000-8000-000000001713")
MINER_A = UUID("00000000-0000-4000-8000-000000001714")
MINER_B = UUID("00000000-0000-4000-8000-000000001715")
AGENT_A = "agent-transport-isolation-a"
AGENT_B = "agent-transport-isolation-b"
IP_A = "198.51.100.171"
IP_B = "198.51.100.172"
MAC_A = "02:00:00:00:17:A1"
MAC_B = "02:00:00:00:17:B1"
def connect():
return psycopg.connect(
host=settings.postgres_host,
port=settings.postgres_port,
dbname=settings.postgres_db,
user=settings.postgres_user,
password=settings.postgres_password,
connect_timeout=5,
)
def json_request(path, payload):
body = json.dumps(payload).encode("utf-8")
delivered = False
async def receive():
nonlocal delivered
if delivered:
return {
"type": "http.request",
"body": b"",
"more_body": False,
}
delivered = True
return {
"type": "http.request",
"body": body,
"more_body": False,
}
scope = {
"type": "http",
"asgi": {"version": "3.0"},
"http_version": "1.1",
"method": "POST",
"scheme": "http",
"path": path,
"raw_path": path.encode("ascii"),
"query_string": b"",
"headers": [(b"content-type", b"application/json")],
"client": ("testclient", 12345),
"server": ("testserver", 80),
}
return Request(scope, receive)
class AgentTransportIsolationPostgresTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
if os.environ.get(
"MINEROPS_TRANSPORT_ISOLATION_DISPOSABLE"
) != "1":
raise unittest.SkipTest(
"Runtime Agent transport isolation is executed "
"by its dedicated disposable PostgreSQL runner."
)
connection = connect()
try:
with connection.cursor() as cur:
cur.execute(
"""
INSERT INTO sites (id, name)
VALUES
(%s, 'Transport Isolation Site A'),
(%s, 'Transport Isolation Site B')
ON CONFLICT (id) DO NOTHING
""",
(SITE_A, SITE_B),
)
cur.execute(
"""
INSERT INTO agent_zones (
id,
site_id,
name,
is_enabled
)
VALUES
(
%s,
%s,
'Transport Isolation Zone A',
true
),
(
%s,
%s,
'Transport Isolation Zone B',
true
)
ON CONFLICT (id) DO UPDATE
SET is_enabled = true
""",
(ZONE_A, SITE_A, ZONE_B, SITE_B),
)
cur.execute(
"""
INSERT INTO minerops_site_agents (
agent_id,
site_id,
agent_zone_id,
site_name,
last_payload
)
VALUES
(
%s,
%s,
%s,
'Transport Isolation Site A',
'{}'::jsonb
),
(
%s,
%s,
%s,
'Transport Isolation Site B',
'{}'::jsonb
)
ON CONFLICT (agent_id) DO UPDATE
SET
site_id = EXCLUDED.site_id,
agent_zone_id = EXCLUDED.agent_zone_id,
site_name = EXCLUDED.site_name,
last_payload = EXCLUDED.last_payload
""",
(
AGENT_A,
SITE_A,
ZONE_A,
AGENT_B,
SITE_B,
ZONE_B,
),
)
connection.commit()
finally:
connection.close()
@classmethod
def tearDownClass(cls):
# Immutable identity/history rows intentionally are not deleted.
# The disposable Compose runner destroys the database volume.
pass
@staticmethod
def _delete_optional_rows(cur, table, predicate, params):
cur.execute(
"SELECT to_regclass(%s)",
(f"public.{table}",),
)
if cur.fetchone()[0] is not None:
cur.execute(
f"DELETE FROM {table} WHERE {predicate}",
params,
)
def setUp(self):
self.zone_service = AgentZoneService(
AgentZoneRepository(connect)
)
connection = connect()
try:
with connection.cursor() as cur:
cur.execute(
"""
INSERT INTO miners (
id,
site_id,
agent_zone_id,
asset_tag,
current_mac,
current_ip,
hostname,
miner_sn,
model,
miner_type,
api_version,
firmware_version,
platform,
status,
notes,
api3_supported
)
VALUES
(
%s,
%s,
%s,
'TRANSPORT-ZONE-A',
%s,
%s::inet,
'zone-a-before',
'ZONE-A-SERIAL',
'Zone A Model',
'Zone A Model',
'1.0-a',
'fw-a',
'platform-a',
'online',
'Zone A baseline',
false
),
(
%s,
%s,
%s,
'TRANSPORT-ZONE-B',
%s,
%s::inet,
'zone-b-before',
'ZONE-B-SERIAL',
'Zone B Model',
'Zone B Model',
'1.0-b',
'fw-b',
'platform-b',
'online',
'Zone B baseline',
false
)
ON CONFLICT (id) DO NOTHING
""",
(
MINER_A,
SITE_A,
ZONE_A,
MAC_A,
IP_A,
MINER_B,
SITE_B,
ZONE_B,
MAC_B,
IP_B,
),
)
connection.commit()
finally:
connection.close()
def _table_exists(self, cur, table):
cur.execute(
"SELECT to_regclass(%s)",
(f"public.{table}",),
)
return cur.fetchone()[0] is not None
def _snapshot_rows(self, cur, table):
cur.execute(
f"""
SELECT to_jsonb(t)
FROM {table} AS t
WHERE miner_id IN (%s, %s)
ORDER BY to_jsonb(t)::text
""",
(MINER_A, MINER_B),
)
return [row[0] for row in cur.fetchall()]
def _count_optional_miner_rows(self, cur, table, miner_id):
if not self._table_exists(cur, table):
return 0
cur.execute(
f"""
SELECT COUNT(*)
FROM {table}
WHERE miner_id = %s
""",
(miner_id,),
)
return cur.fetchone()[0]
def _capture_inventory_state(self):
connection = connect()
try:
with connection.cursor() as cur:
cur.execute(
"""
SELECT id::text, to_jsonb(m)
FROM miners AS m
WHERE id IN (%s, %s)
ORDER BY id
""",
(MINER_A, MINER_B),
)
miners = {
row[0]: row[1]
for row in cur.fetchall()
}
ownerships = self._snapshot_rows(
cur,
"miner_mac_ownerships",
)
identities = self._snapshot_rows(
cur,
"miner_network_identities",
)
counts = {}
for table in (
"miner_status_snapshots",
"miner_api3_enrichment_snapshots",
"miner_api3_hashboard_snapshots",
"miner_pool_snapshots",
):
counts[(table, "A")] = (
self._count_optional_miner_rows(
cur,
table,
MINER_A,
)
)
counts[(table, "B")] = (
self._count_optional_miner_rows(
cur,
table,
MINER_B,
)
)
return {
"miners": miners,
"mac_ownerships": ownerships,
"network_identities": identities,
"snapshot_counts": counts,
}
finally:
connection.close()
def _cross_zone_api3_probe_count(self):
connection = connect()
try:
with connection.cursor() as cur:
if not self._table_exists(
cur,
"miner_api3_enrichment_snapshots",
):
return 0
cur.execute(
"""
SELECT COUNT(*)
FROM miner_api3_enrichment_snapshots
WHERE agent_id = %s
AND (
host(ip_address) = %s
OR upper(mac_address) = upper(%s)
)
""",
(AGENT_A, IP_B, MAC_B),
)
return cur.fetchone()[0]
finally:
connection.close()
def test_v2_cannot_address_other_zone_miner_directly(self):
before = self._capture_inventory_state()
request = json_request(
"/api/agent/miner-enrichment-v2",
{
"miner_id": str(MINER_B),
"mac_address": MAC_B,
"hostname": "zone-a-must-not-write-this",
"model": "cross-zone-v2-probe",
},
)
with self.assertRaises(HTTPException) as context:
asyncio.run(
minerops_agent_miner_enrichment_v2(
request,
AGENT_A,
self.zone_service,
)
)
self.assertEqual(context.exception.status_code, 404)
after = self._capture_inventory_state()
self.assertEqual(after, before)
def test_v2_cross_zone_mac_merge_cannot_mutate_either_miner(self):
before = self._capture_inventory_state()
request = json_request(
"/api/agent/miner-enrichment-v2",
{
"miner_id": str(MINER_A),
"ip_address": IP_A,
"mac_address": MAC_B,
"hostname": "cross-zone-merge-probe",
"miner_sn": "MUST-NOT-CROSS-ZONES",
"model": "Cross Zone Merge Probe",
},
)
error = None
try:
asyncio.run(
minerops_agent_miner_enrichment_v2(
request,
AGENT_A,
self.zone_service,
)
)
except Exception as exc:
error = exc
self.assertIsNotNone(
error,
"A Zone A miner must not successfully claim a Zone B MAC",
)
after = self._capture_inventory_state()
self.assertEqual(after, before)
def test_v3_cannot_match_or_mutate_other_zone_miner(self):
before = self._capture_inventory_state()
request = json_request(
"/api/agent/miner-enrichment-v3",
{
"miner_id": str(MINER_B),
"ip_address": IP_B,
"mac_address": MAC_B,
"hostname": "zone-a-v3-cross-zone-probe",
"miner_sn": "V3-MUST-NOT-MUTATE",
"model": "V3 Cross Zone Probe",
"api_version": "99.99",
"firmware_version": "cross-zone",
"platform": "cross-zone",
"raw_version": {"cross_zone": True},
"raw_miner_info": {"cross_zone": True},
},
)
result = asyncio.run(
minerops_agent_miner_enrichment_v3(
request,
AGENT_A,
self.zone_service,
)
)
self.assertFalse(result["matched"])
after = self._capture_inventory_state()
self.assertEqual(after, before)
def test_api3_ingestion_cannot_associate_or_mutate_other_zone_miner(self):
before = self._capture_inventory_state()
self.assertEqual(
self._cross_zone_api3_probe_count(),
0,
)
request = json_request(
"/api/agent/api3-enrichment",
{
"agent_id": AGENT_B,
"site_name": "spoofed-zone-b",
"items": [
{
"ip": IP_B,
"mac": MAC_B,
"api3_supported": True,
"api3_error": None,
"device_info": {
"msg": {
"network": {
"ip": IP_B,
"mac": MAC_B,
},
"miner": {
"type": "Cross Zone API3 Probe",
"miner-sn": "API3-MUST-NOT-MUTATE",
},
"system": {
"api": "99.99",
"apiswitch": "on",
"fwversion": "cross-zone-fw",
"platform": "cross-zone-platform",
},
"power": {
"sn": "cross-zone-power",
"model": "cross-zone-psu",
},
}
},
"miner_setting": {
"msg": {
"power-mode": "high",
}
},
"miner_status": {
"msg": {
"summary": {
"hash-average": 999,
"power-realtime": 9999,
"power-rate": 99,
"chip-temp-avg": 99,
"chip-temp-max": 100,
},
"pools": [
{
"id": 0,
"status": "Alive",
"account": "cross-zone-worker",
"url": "stratum+tcp://invalid.example:3333",
}
],
"edevs": [
{
"slot": 0,
"hash-average": 999,
"factory-hash": 999,
"freq": 999,
"effective-chips": 999,
}
],
}
},
"fan_setting": {
"msg": {
"mode": "cross-zone",
}
},
"custom_data": {
"msg": {
"CustomerSn": "CROSS-ZONE-CUSTOMER",
}
},
}
],
},
)
asyncio.run(
minerops_agent_api3_enrichment(
request,
AGENT_A,
self.zone_service,
)
)
after = self._capture_inventory_state()
self.assertEqual(after, before)
self.assertEqual(
self._cross_zone_api3_probe_count(),
0,
(
"Agent A must not persist API3 enrichment associated "
"with Zone B identity data"
),
)
if __name__ == "__main__":
unittest.main()