feat(agent): add durable existing-agent credential transitions
This commit is contained in:
1 parent
abf5654a25
commit
3cfb0d1abe
33 files changed
+3828
-54
No files matched your search
@@ -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()
|
||||
Reference in new issue
Block a user