security: contain physical miner commands in Stage A

Disable physical control through legacy HTTP/M30 producers, typed admission,
queue dispatch and upgraded Windows executors. Restrict diagnostic transports
to exact read-only operations, with ordinal PowerShell validation before sockets.

Retire unsupported pending/claimed work with atomic, idempotent security audits.
Preserve prior delivery evidence and report unknown outcomes after a prior claim,
including explicitly repaired pending rows. Include containment, cancellation,
concurrency and malformed-payload regressions and the old-Agent cutover runbook.

Validation: independent final application-security revalidation PASS. Two unchanged
baseline source-assertion failures are documented as exceptions. Production release
still requires native Windows validation and verified fencing/stop/drain/upgrade;
server cancellation alone cannot revoke a cached command held by an old Agent.
This commit is contained in:
lussierj committed 2026-10-15 20:39:45 +00:00
1 parent 2d89e80410
commit e898f283ab
28 files changed
+2377 -2379

No files matched your search

+44 -63
View File
@@ -71,64 +71,47 @@ class FakeRepository:
class MinerControlServiceTests(unittest.TestCase):
def test_supported_projection_is_factual_and_bounded(self):
def test_disabled_projection_preserves_facts_and_bounded_history(self):
repository = FakeRepository()
result = MinerControlService(repository).get_controls(MINER_ID)
self.assertEqual(result.service_control.state, "supported")
self.assertEqual(result.service_control.state, "unavailable")
self.assertEqual(result.service_control.reason, "physical_control_disabled_stage_a")
self.assertEqual(result.performance_mode, "normal")
self.assertEqual(result.available_service_action, "suspend")
self.assertIsNone(result.available_service_action)
self.assertEqual(repository.limits, [5])
def test_capability_missing_facts_is_not_optimistic(self):
cases = (
({"agent_zone_id": None}, "unavailable", "agent_zone_unassigned"),
({"agent_zone_exists": False}, "unavailable", "agent_zone_missing"),
({"agent_zone_enabled": False}, "unavailable", "agent_zone_disabled"),
({"agent_id": None}, "unavailable", "agent_unavailable"),
({"current_ip": None}, "unavailable", "current_ip_missing"),
({"api3_supported": False}, "unavailable", "api3_unsupported"),
({"api3_supported": None}, "unknown", "api3_support_unknown"),
({"last_payload": {}}, "unknown", "agent_capability_unknown"),
(
{"last_payload": {"control_available": False,
"control_unavailable_reason": "credentials_missing"}},
"unavailable", "credentials_missing",
),
)
for changes, state, reason in cases:
with self.subTest(reason=reason):
result = MinerControlService(FakeRepository(context(**changes))).get_controls(MINER_ID)
self.assertEqual(result.service_control.state, state)
self.assertEqual(result.service_control.reason, reason)
def test_capability_cannot_be_enabled_by_agent_claims(self):
for facts in ({}, {"control_available": True}, {"control_available": False}):
repository = FakeRepository(context(last_payload=facts))
result = MinerControlService(repository).get_controls(MINER_ID)
self.assertEqual(result.service_control.state, "unavailable")
self.assertEqual(result.service_control.reason, "physical_control_disabled_stage_a")
def test_resume_requires_known_stopped_state(self):
service = MinerControlService(FakeRepository(context(runtime_state="offline")))
with self.assertRaisesRegex(MinerControlUnavailable, "factually_stopped"):
service.queue_control(
MINER_ID, "resume", requested_value=None,
actor_user_id=USER_ID, actor_username="operator",
)
def test_resume_is_disabled_even_for_known_stopped_state(self):
service = MinerControlService(FakeRepository(context(runtime_state="stopped")))
with self.assertRaisesRegex(MinerControlUnavailable, "physical_control_disabled_stage_a"):
service.queue_control(MINER_ID, "resume", requested_value=None,
actor_user_id=USER_ID, actor_username="operator")
def test_queue_contains_routing_but_audit_and_response_do_not(self):
def test_all_current_actions_are_rejected_before_routing_or_queue_write(self):
for action in ("suspend", "resume", "performance_mode"):
repository = FakeRepository()
with self.assertRaisesRegex(MinerControlUnavailable, "physical_control_disabled_stage_a"):
MinerControlService(repository).queue_control(
MINER_ID, action, requested_value="high",
actor_user_id=USER_ID, actor_username="operator")
self.assertEqual(repository.enqueue_calls, [])
self.assertFalse(hasattr(repository, "requested_miner"))
def test_rejected_request_leaves_context_unchanged(self):
repository = FakeRepository()
result = MinerControlService(repository).queue_control(
MINER_ID, "performance_mode", requested_value="high",
actor_user_id=USER_ID, actor_username="operator",
)
call = repository.enqueue_calls[0]
self.assertEqual(call["request_payload"]["ip_address"], "192.0.2.10")
self.assertNotIn("ip_address", call["audit_payload"])
self.assertNotIn("agent_id", call["audit_payload"])
self.assertNotIn("password", str(call).lower())
self.assertNotIn("192.0.2.10", result.model_dump_json())
def test_no_projection_changes_when_work_is_queued(self):
repository = FakeRepository()
MinerControlService(repository).queue_control(
MINER_ID, "suspend", requested_value=None,
actor_user_id=USER_ID, actor_username="operator",
)
self.assertFalse(any("update" in key for key in repository.enqueue_calls[0]))
before = repository.miner_context.copy()
with self.assertRaises(MinerControlUnavailable):
MinerControlService(repository).queue_control(
MINER_ID, "suspend", requested_value=None,
actor_user_id=USER_ID, actor_username="operator")
self.assertEqual(repository.miner_context, before)
self.assertEqual(repository.enqueue_calls, [])
class MinerControlRouterTests(unittest.TestCase):
@@ -159,18 +142,16 @@ class MinerControlRouterTests(unittest.TestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["data"]["miner_id"], str(MINER_ID))
def test_posts_require_control_and_return_202_bounded_envelope(self):
path = f"/api/miners/{MINER_ID}/controls/suspend"
self.authenticate(("miners.view",))
self.assertEqual(self.client.post(path, json={}).status_code, 403)
self.authenticate(("miners.control",))
response = self.client.post(path, json={})
self.assertEqual(response.status_code, 202)
self.assertEqual(set(response.json()["data"]), {
"operation_id", "miner_id", "action", "requested_value", "status", "created_at"
})
self.assertNotIn("ip", response.text.lower())
self.assertNotIn("agent", response.text.lower())
def test_posts_require_control_and_then_fail_closed(self):
for action, body in (("suspend", {}), ("resume", {}), ("performance-mode", {"mode": "high"})):
path = f"/api/miners/{MINER_ID}/controls/{action}"
self.authenticate(("miners.view",))
self.assertEqual(self.client.post(path, json=body).status_code, 403)
self.authenticate(("miners.control",))
response = self.client.post(path, json=body)
self.assertEqual(response.status_code, 409)
self.assertIn("physical_control_disabled_stage_a", response.text)
self.assertEqual(self.repository.enqueue_calls, [])
def test_strict_bodies_reject_routing_commands_and_credentials(self):
self.authenticate(("miners.control",))
@@ -195,7 +176,7 @@ class MinerControlRouterTests(unittest.TestCase):
)
self.assertEqual(
self.client.post(path, json={}, headers={"Origin": "http://testserver"}).status_code,
202,
409,
)
def test_identity_permission_mapping_is_specific(self):