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

+86 -3
View File
@@ -49,6 +49,14 @@ class AgentAuthServiceTests(unittest.TestCase):
"legacy-agent",
)
def test_secret_only_legacy_agent_maps_to_configured_identity(self):
self.assertEqual(
self.service().authenticate(None, "legacy-secret"),
"legacy-agent",
)
with self.assertRaises(AgentAuthenticationFailed):
self.service().authenticate(None, "wrong-secret")
def test_legacy_agent_with_null_credential_still_authenticates(self):
rows = {
"legacy-agent": {
@@ -116,13 +124,83 @@ class AgentAuthServiceTests(unittest.TestCase):
with self.subTest(secret=secret), self.assertRaises(AgentCredentialRevoked):
self.service(rows).authenticate("agent-new", secret)
def test_revoked_registry_row_never_falls_back_even_without_hash(self):
rows = {
"legacy-agent": {
"agent_id": "legacy-agent",
"agent_secret_hash": None,
"credential_created_at": None,
"credential_revoked_at": NOW,
}
}
for agent_id in ("legacy-agent", None):
with self.subTest(agent_id=agent_id), self.assertRaises(
AgentCredentialRevoked
):
self.service(rows).authenticate(agent_id, "legacy-secret")
def test_missing_identity_never_authenticates_enrolled_legacy_agent(self):
rows = {
"legacy-agent": {
"agent_id": "legacy-agent",
"agent_secret_hash": hash_agent_secret("unique-secret"),
"credential_created_at": NOW,
"credential_revoked_at": None,
}
}
for secret in ("unique-secret", "legacy-secret"):
with self.subTest(secret=secret), self.assertRaises(AgentAuthenticationFailed):
self.service(rows).authenticate(None, secret)
def test_missing_identity_reports_revoked_legacy_credential(self):
rows = {
"legacy-agent": {
"agent_id": "legacy-agent",
"agent_secret_hash": hash_agent_secret("unique-secret"),
"credential_created_at": NOW,
"credential_revoked_at": NOW,
}
}
with self.assertRaises(AgentCredentialRevoked):
self.service(rows).authenticate(None, "legacy-secret")
def test_durable_retirement_rejects_fallback_after_credentials_are_cleared(self):
rows = {
"legacy-agent": {
"agent_id": "legacy-agent",
"agent_secret_hash": None,
"credential_created_at": None,
"credential_revoked_at": None,
"legacy_auth_disabled_at": NOW,
}
}
for agent_id in ("legacy-agent", None):
with self.subTest(agent_id=agent_id), self.assertRaises(
AgentAuthenticationFailed
):
self.service(rows).authenticate(agent_id, "legacy-secret")
def test_identity_retirement_rejects_fallback_without_current_agent_row(self):
rows = {
"legacy-agent": {
"agent_id": "legacy-agent",
"agent_secret_hash": None,
"credential_created_at": None,
"credential_revoked_at": None,
"legacy_auth_disabled_at": NOW,
}
}
for agent_id in ("legacy-agent", None):
with self.subTest(agent_id=agent_id), self.assertRaises(
AgentAuthenticationFailed
):
self.service(rows).authenticate(agent_id, "legacy-secret")
def test_unknown_identity_does_not_use_shared_secret(self):
with self.assertRaises(AgentIdentityUnauthorized):
self.service().authenticate("unknown-agent", "legacy-secret")
def test_missing_identity_or_secret_is_rejected(self):
with self.assertRaises(AgentAuthenticationFailed):
self.service().authenticate(None, "legacy-secret")
def test_missing_secret_is_rejected(self):
with self.assertRaises(AgentAuthenticationFailed):
self.service().authenticate("legacy-agent", None)
@@ -131,6 +209,11 @@ class AgentAuthServiceTests(unittest.TestCase):
with self.assertRaises(AgentAuthenticationUnavailable):
self.service().authenticate("legacy-agent", "anything")
def test_secret_only_path_requires_configured_legacy_identity(self):
settings.minerops_agent_id = ""
with self.assertRaises(AgentAuthenticationUnavailable):
self.service().authenticate(None, "legacy-secret")
if __name__ == "__main__":
unittest.main()