railiance-platform/tests/test_application_recovery_identities.py
codex 12f2056272
All checks were successful
CCR intake gate / gate (push) Successful in 5m17s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Prepare scoped recovery resources and bounded construction renewal
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a17f16-d99c-7ea3-95f0-8212897fba6b
2026-10-29 21:52:55 +01:00

239 lines
12 KiB
Python

"""Synthetic provider responses only; no live identity or network access."""
import copy
import importlib.util
import json
import os
import tempfile
import unittest
from datetime import UTC, datetime, timedelta
from pathlib import Path
from unittest.mock import patch
from urllib.parse import parse_qs, urlsplit
from urllib.request import HTTPRedirectHandler, Request
SOURCE = Path(__file__).resolve().parents[1] / "scripts/application_recovery_identities.py"
spec = importlib.util.spec_from_file_location("recovery_identities", SOURCE)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
NOW = datetime(2026, 10, 28, 10, tzinfo=UTC)
class Provider:
def __init__(self):
self.calls, self.projects, self.policies, self.keys = [], {}, {}, {}
self.apps = {module.PUBLISHER: {"id": module.PUBLISHER, "name":
"coulomb-social-backup-primary", "organization_id": "synthetic-org"}}
self.rules = {}
self.extra_org_rule = False
self.uncertain_key = False
self.key_http_error = None
self.foreign_key_response = False
self.unbounded_bootstrap = False
self.issued_keys = 0
def __call__(self, method, url, data=None):
self.calls.append((method, url, copy.deepcopy(data)))
path = urlsplit(url).path
if path.endswith("/permission-sets"):
names = sorted({p for role in module.ROLES.values() for p in role["permissions"]})
return {"permission_sets": [{"name": n} for n in names], "total_count": str(len(names))}
if path.endswith("/rules"):
policy_id = parse_qs(urlsplit(url).query)["policy_id"][0]
rules = copy.deepcopy(self.rules[policy_id])
if self.extra_org_rule:
rules[0]["organization_id"] = "synthetic-org"
return {"rules": rules}
for suffix, store, key in [("projects", self.projects, "projects"),
("applications", self.apps, "applications"),
("policies", self.policies, "policies"),
("api-keys", self.keys, "api_keys")]:
if path.endswith("/" + suffix):
if method == "GET":
return {key: list(store.values()), "total_count": str(len(store))}
if method == "POST":
identity = suffix + "-" + str(len(store) + 1)
created = {"id": identity, **copy.deepcopy(data)}
if suffix == "policies":
self.rules[identity] = created.pop("rules")
if suffix == "api-keys":
self.issued_keys += 1
identity = suffix + "-" + str(self.issued_keys)
created["id"] = identity
created.update(access_key=identity,
secret_key="SYNTHETIC_SECRET_" + identity)
if self.foreign_key_response:
created["application_id"] = "foreign-application"
if self.unbounded_bootstrap:
created["expires_at"] = None
store[identity] = created
if suffix == "api-keys" and self.uncertain_key:
raise OSError("synthetic lost acknowledgement")
if suffix == "api-keys" and self.key_http_error:
raise module.ProviderError(self.key_http_error)
return copy.deepcopy(created)
marker = "/" + suffix + "/"
if marker in path:
identity = path.split(marker, 1)[1]
if method == "DELETE":
del store[identity]
return {}
if identity not in store:
raise module.ProviderError(404)
return copy.deepcopy(store[identity])
raise AssertionError("Unexpected synthetic request")
class IdentityBootstrap(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory(dir="/tmp")
self.addCleanup(self.temporary.cleanup)
self.directory = Path(self.temporary.name)
self.directory.chmod(0o700)
# Some workstations manage /tmp itself as a Git worktree. Isolate the
# synthetic provider cases; exercise the real Git guard separately below.
self.git_guard = patch.object(module, "inside_git", return_value=False)
self.git_guard.start()
self.addCleanup(self.git_guard.stop)
self.api = Provider()
def run_bootstrap(self):
return module.Bootstrap(self.api, self.directory, NOW).run()
def test_project_only_grants_private_pairs_no_publisher_rotation_and_idempotent_resume(self):
before = copy.deepcopy(self.api.apps[module.PUBLISHER])
result = self.run_bootstrap()
self.assertFalse(result["organization_wide_grants"])
self.assertFalse(result["native_s3_escrow_boundaries_verified"])
policies = [d for method, path, d in self.api.calls
if method == "POST" and path.endswith("/policies")]
self.assertEqual(len(policies), 4)
for policy in policies:
self.assertEqual(policy["rules"][0]["project_ids"], ["projects-1"])
self.assertNotIn("organization_id", policy["rules"][0])
self.assertFalse(any(p.startswith(("IAM", "AllProducts"))
for p in policy["rules"][0]["permission_set_names"]))
self.assertEqual(self.api.apps[module.PUBLISHER], before)
self.assertFalse(any(k["application_id"] == module.PUBLISHER
for k in self.api.keys.values()))
for role in ["bootstrap", "reader", "custodian"]:
path = self.directory / (role + "-pair.json")
self.assertEqual(path.stat().st_mode & 0o777, 0o600)
self.assertIn("AWS_SECRET_ACCESS_KEY", json.loads(path.read_text()))
self.assertNotIn("SYNTHETIC_SECRET", (self.directory / "identity-state.json").read_text())
self.assertNotIn("SYNTHETIC_SECRET", json.dumps(result))
posts = sum(method == "POST" for method, _, _ in self.api.calls)
self.run_bootstrap()
self.assertEqual(sum(method == "POST" for method, _, _ in self.api.calls), posts)
def test_untracked_existing_project_is_not_adopted_or_granted_access(self):
self.api.projects["foreign"] = {"id": "foreign", "name": module.PROJECT,
"organization_id": "synthetic-org"}
with self.assertRaisesRegex(module.Refused, "untracked_existing_project"):
self.run_bootstrap()
self.assertFalse(any(method == "POST" for method, _, _ in self.api.calls))
def test_expired_construction_key_renews_only_its_owned_role(self):
self.run_bootstrap()
routine = {r: (self.directory / (r + "-pair.json")).read_bytes()
for r in ("reader", "custodian")}
prior = json.loads((self.directory / "bootstrap-pair.json").read_text())["AWS_ACCESS_KEY_ID"]
result = module.Bootstrap(self.api, self.directory, NOW + timedelta(days=1)).run()
self.assertEqual(result["status"], "identity_bootstrap_complete_native_boundaries_pending")
self.assertNotIn(prior, self.api.keys)
self.assertEqual(len(self.api.keys), 3)
for role, value in routine.items():
self.assertEqual((self.directory / (role + "-pair.json")).read_bytes(), value)
def test_effective_org_wide_rule_refuses_before_any_key_is_issued(self):
self.api.extra_org_rule = True
with self.assertRaisesRegex(module.Refused, "effective_project_rule"):
self.run_bootstrap()
self.assertEqual(self.api.keys, {})
def test_unknown_key_outcome_stops_restart_without_minting_a_duplicate(self):
self.api.uncertain_key = True
with self.assertRaises(OSError):
self.run_bootstrap()
self.assertEqual(len(self.api.keys), 1)
calls = len(self.api.calls)
with self.assertRaisesRegex(module.Refused, "uncertain_key_issue"):
self.run_bootstrap()
self.assertEqual(len(self.api.calls), calls)
def test_server_error_during_issuance_remains_uncertain_and_blocks_duplicate(self):
self.api.key_http_error = 503
with self.assertRaises(module.ProviderError):
self.run_bootstrap()
calls = len(self.api.calls)
with self.assertRaisesRegex(module.Refused, "uncertain_key_issue"):
self.run_bootstrap()
self.assertEqual(len(self.api.calls), calls)
def test_unbounded_bootstrap_key_is_revoked_and_never_delivered(self):
self.api.unbounded_bootstrap = True
with self.assertRaisesRegex(module.Refused, "pair_persistence_failed"):
self.run_bootstrap()
self.assertEqual(self.api.keys, {})
self.assertFalse((self.directory / "bootstrap-pair.json").exists())
def test_mismatched_returned_application_never_authorizes_deleting_a_foreign_key(self):
self.api.foreign_key_response = True
with self.assertRaisesRegex(module.Refused, "pair_persistence_failed"):
self.run_bootstrap()
self.assertFalse(any(method == "DELETE" for method, _, _ in self.api.calls))
self.assertIn("pending_key_issue", json.loads((
self.directory / "identity-state.json").read_text()))
def test_pair_write_failure_revokes_only_the_just_issued_owned_key(self):
real_open = os.open
def fail_reader(path, *args, **kwargs):
if str(path).endswith("reader-pair.json"):
raise OSError("synthetic disk failure")
return real_open(path, *args, **kwargs)
with (patch.object(module.os, "open", fail_reader),
self.assertRaisesRegex(module.Refused, "pair_persistence_failed")):
self.run_bootstrap()
deletions = [path for method, path, _ in self.api.calls if method == "DELETE"]
self.assertEqual(deletions, ["/iam/v1alpha1/api-keys/api-keys-2"])
self.assertEqual(len(self.api.keys), 1) # Earlier persisted bootstrap pair is retained.
def test_private_credentials_cannot_be_written_inside_a_git_checkout(self):
self.git_guard.stop()
(self.directory / ".git").mkdir()
with self.assertRaisesRegex(module.Refused, "outside_git"):
module.Bootstrap(self.api, self.directory, NOW)
self.assertEqual(self.api.calls, [])
def test_bootstrap_retirement_revokes_only_temporary_key_and_retains_routine_pairs(self):
self.run_bootstrap()
before = {role: (self.directory / (role + "-pair.json")).read_bytes()
for role in ["reader", "custodian"]}
result = module.Bootstrap(self.api, self.directory, NOW).retire_bootstrap()
self.assertEqual(result["status"], "bootstrap_api_key_retired")
self.assertEqual(len(self.api.keys), 2)
self.assertFalse((self.directory / "bootstrap-pair.json").exists())
for role, value in before.items():
self.assertEqual((self.directory / (role + "-pair.json")).read_bytes(), value)
self.assertTrue(module.Bootstrap(self.api, self.directory, NOW).retire_bootstrap())
def test_retirement_cannot_delete_a_key_after_foreign_application_binding_drift(self):
self.run_bootstrap()
bootstrap_key = json.loads((self.directory / "bootstrap-pair.json").read_text())
self.api.keys[bootstrap_key["AWS_ACCESS_KEY_ID"]]["application_id"] = "foreign"
with self.assertRaisesRegex(module.Refused, "retirement_key_binding_refused"):
module.Bootstrap(self.api, self.directory, NOW).retire_bootstrap()
self.assertFalse(any(method == "DELETE" for method, _, _ in self.api.calls))
def test_provider_redirect_cannot_forward_the_temporary_operator_token(self):
transport = module.Transport({"session_token": "synthetic-only", "user_agent": "test"})
handler = next(h for h in transport.opener.handlers if isinstance(h, HTTPRedirectHandler))
with self.assertRaisesRegex(module.Refused, "provider_redirect_refused"):
handler.redirect_request(Request("https://api.scaleway.com/"), None, 302, "",
{}, "https://example.invalid/")
if __name__ == "__main__":
unittest.main()