feat(agent): add durable existing-agent credential transitions

This commit is contained in:
lussierj committed 2026-10-14 13:50:07 +00:00
1 parent abf5654a25
commit 3cfb0d1abe
33 files changed
+3828 -54

No files matched your search

+180 -1
View File
@@ -4,6 +4,7 @@ import unittest
from concurrent.futures import ThreadPoolExecutor
from uuid import uuid4
from psycopg.errors import ForeignKeyViolation
from psycopg.rows import dict_row
from app.agent_auth.exceptions import AgentAuthenticationFailed
@@ -11,6 +12,7 @@ from app.agent_auth.repository import AgentAuthRepository
from app.agent_auth.service import AgentAuthService, hash_agent_secret
from app.agent_enrollment.exceptions import (
AgentEnrollmentConflict,
AgentEnrollmentCredentialCollision,
AgentEnrollmentNotFound,
AgentEnrollmentTokenInvalid,
)
@@ -26,6 +28,7 @@ from app.agent_enrollment.service import AgentEnrollmentService
from app.agent_zones.models import AgentCheckinRequest
from app.agent_zones.repository import AgentZoneRepository
from app.agent_zones.service import AgentZoneService
from app.config import settings
class AgentEnrollmentPostgresTests(unittest.TestCase):
@@ -322,6 +325,7 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
agent_secret_hash,
credential_created_at,
credential_revoked_at,
legacy_auth_disabled_at,
last_payload::text AS last_payload
FROM minerops_site_agents
WHERE site_id = %s
@@ -345,6 +349,16 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
)
enrollment_row = cur.fetchone()
cur.execute(
"""
SELECT retired_at
FROM agent_legacy_auth_retirements
WHERE agent_id = %s
""",
(agent_id,),
)
retirement_row = cur.fetchone()
cur.execute(
"""
SELECT new_value_json::text AS payload
@@ -369,6 +383,15 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
)
self.assertIsNotNone(agent["credential_created_at"])
self.assertIsNone(agent["credential_revoked_at"])
self.assertEqual(
agent["legacy_auth_disabled_at"],
agent["credential_created_at"],
)
self.assertIsNotNone(retirement_row)
self.assertEqual(
retirement_row["retired_at"],
agent["credential_created_at"],
)
self.assertIsNotNone(enrollment_row["used_at"])
self.assertIsNone(enrollment_row["revoked_at"])
@@ -409,6 +432,17 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
"definitely-not-the-issued-secret",
)
original_legacy_id = settings.minerops_agent_id
original_legacy_secret = settings.minerops_agent_shared_secret
settings.minerops_agent_id = agent_id
settings.minerops_agent_shared_secret = "global-secret-must-not-work"
try:
with self.assertRaises(AgentAuthenticationFailed):
auth_service.authenticate(None, "global-secret-must-not-work")
finally:
settings.minerops_agent_id = original_legacy_id
settings.minerops_agent_shared_secret = original_legacy_secret
# Normal check-in must never mutate the credential.
secret_hash_before = agent["agent_secret_hash"]
@@ -433,7 +467,8 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
SELECT
agent_secret_hash,
credential_created_at,
credential_revoked_at
credential_revoked_at,
legacy_auth_disabled_at
FROM minerops_site_agents
WHERE agent_id = %s
""",
@@ -453,6 +488,150 @@ class AgentEnrollmentPostgresTests(unittest.TestCase):
self.assertIsNone(
after_checkin["credential_revoked_at"]
)
self.assertEqual(
after_checkin["legacy_auth_disabled_at"],
agent["legacy_auth_disabled_at"],
)
# 0017 enrollment integrity remains RESTRICT: the current Agent row
# cannot be deleted while its enrollment relationship exists.
connection = default_connection_factory()
try:
with self.assertRaises(ForeignKeyViolation):
with connection.cursor() as cur:
cur.execute(
"DELETE FROM minerops_site_agents WHERE agent_id = %s",
(agent_id,),
)
connection.rollback()
finally:
connection.close()
# After an operator deliberately removes the enrollment history, the
# independent retirement ledger must outlive deletion and recreation
# of the current Agent row with the identical identity.
connection = default_connection_factory()
try:
with connection.cursor() as cur:
cur.execute(
"DELETE FROM agent_enrollments WHERE id = %s",
(enrollment["id"],),
)
cur.execute(
"DELETE FROM minerops_site_agents WHERE agent_id = %s",
(agent_id,),
)
connection.commit()
finally:
connection.close()
original_legacy_id = settings.minerops_agent_id
original_legacy_secret = settings.minerops_agent_shared_secret
settings.minerops_agent_id = agent_id
settings.minerops_agent_shared_secret = "recreation-global-secret"
try:
with self.assertRaises(AgentAuthenticationFailed):
auth_service.authenticate(None, "recreation-global-secret")
connection = default_connection_factory()
try:
with connection.cursor(row_factory=dict_row) as cur:
cur.execute(
"""
INSERT INTO minerops_site_agents (
agent_id,
site_id,
agent_zone_id,
site_name
)
VALUES (%s, %s, %s, %s)
RETURNING legacy_auth_disabled_at
""",
(
agent_id,
self.site_id,
self.zone_id,
self.site_name,
),
)
recreated = cur.fetchone()
connection.commit()
finally:
connection.close()
self.assertEqual(
recreated["legacy_auth_disabled_at"],
retirement_row["retired_at"],
)
with self.assertRaises(AgentAuthenticationFailed):
auth_service.authenticate(agent_id, "recreation-global-secret")
finally:
settings.minerops_agent_id = original_legacy_id
settings.minerops_agent_shared_secret = original_legacy_secret
def test_failed_credential_issuance_rolls_back_new_retirement(self):
enrollment = self.create_enrollment("Collision Agent")
collision_id = f"agent-collision-{uuid4().hex}"
connection = default_connection_factory()
try:
with connection.cursor() as cur:
cur.execute(
"""
INSERT INTO minerops_site_agents (agent_id, site_name)
VALUES (%s, 'Existing uncredentialed identity')
""",
(collision_id,),
)
connection.commit()
finally:
connection.close()
try:
with self.assertRaises(AgentEnrollmentCredentialCollision):
AgentEnrollmentRepository().redeem_enrollment(
token_hash=hash_agent_secret(enrollment["enrollment_token"]),
agent_id=collision_id,
agent_secret_hash=hash_agent_secret("never-issued-secret"),
)
connection = default_connection_factory()
try:
with connection.cursor(row_factory=dict_row) as cur:
cur.execute(
"""
SELECT count(*) AS count
FROM agent_legacy_auth_retirements
WHERE agent_id = %s
""",
(collision_id,),
)
self.assertEqual(cur.fetchone()["count"], 0)
cur.execute(
"""
SELECT used_at, enrolled_agent_id
FROM agent_enrollments
WHERE id = %s
""",
(enrollment["id"],),
)
enrollment_row = cur.fetchone()
finally:
connection.close()
self.assertIsNone(enrollment_row["used_at"])
self.assertIsNone(enrollment_row["enrolled_agent_id"])
finally:
connection = default_connection_factory()
try:
with connection.cursor() as cur:
cur.execute(
"DELETE FROM minerops_site_agents WHERE agent_id = %s",
(collision_id,),
)
connection.commit()
finally:
connection.close()
def test_expired_token_is_rejected_without_side_effects(self):
enrollment = self.create_enrollment()