fix(secrets): redact provider failure details

This commit is contained in:
2026-07-21 15:47:50 +02:00
parent 7843fe88e5
commit d64de50802
2 changed files with 18 additions and 6 deletions

View File

@@ -1512,14 +1512,14 @@ def store_caldav_credential(
value=secret, value=secret,
) )
).strip() ).strip()
except Exception as exc: except Exception:
raise CalendarError("Stored sync credential could not be written to its secret provider") from exc raise CalendarError("Stored sync credential could not be written to its secret provider") from None
if not provider_ref: if not provider_ref:
raise CalendarError("Secret provider returned an empty credential reference") raise CalendarError("Secret provider returned an empty credential reference")
if old_provider_ref and old_provider_ref != provider_ref: if old_provider_ref and old_provider_ref != provider_ref:
try: try:
provider.delete_secret(old_provider_ref) provider.delete_secret(old_provider_ref)
except Exception as exc: except Exception:
if not _provider_secret_is_absent(provider, old_provider_ref): if not _provider_secret_is_absent(provider, old_provider_ref):
compensation_failed = False compensation_failed = False
try: try:
@@ -1534,7 +1534,7 @@ def store_caldav_credential(
raise CalendarError( raise CalendarError(
"Previous sync credential could not be deleted from its secret provider; " "Previous sync credential could not be deleted from its secret provider; "
f"the replacement was not activated{compensation_detail}" f"the replacement was not activated{compensation_detail}"
) from exc ) from None
existing.secret_encrypted = None existing.secret_encrypted = None
existing.metadata_ = {"source_id": source.id, "provider_ref": provider_ref} existing.metadata_ = {"source_id": source.id, "provider_ref": provider_ref}
else: else:
@@ -1619,12 +1619,12 @@ def _delete_calendar_owned_credential(
) )
try: try:
provider.delete_secret(provider_ref) provider.delete_secret(provider_ref)
except Exception as exc: except Exception:
if not _provider_secret_is_absent(provider, provider_ref): if not _provider_secret_is_absent(provider, provider_ref):
raise CalendarError( raise CalendarError(
"Stored sync credential could not be deleted from its secret provider; " "Stored sync credential could not be deleted from its secret provider; "
"the requested deletion was not completed" "the requested deletion was not completed"
) from exc ) from None
storage_backend = "external_secret_provider" storage_backend = "external_secret_provider"
credential.secret_encrypted = None credential.secret_encrypted = None
credential.metadata_ = {"source_id": source_id} if source_id else {} credential.metadata_ = {"source_id": source_id} if source_id else {}

View File

@@ -593,6 +593,18 @@ class CalDAVSyncTests(unittest.TestCase):
self.assertEqual((credential.metadata_ or {})["provider_ref"], provider_ref) self.assertEqual((credential.metadata_ or {})["provider_ref"], provider_ref)
self.assertIn(provider_ref, provider.values) self.assertIn(provider_ref, provider.values)
with patch("govoplan_calendar.backend.service.secret_provider", return_value=provider), patch.object(
provider,
"delete_secret",
side_effect=RuntimeError(f"provider failed for {provider_ref}"),
):
with self.assertRaises(CalendarError) as raised:
delete_caldav_source(session, tenant_id="tenant-1", source_id=source.id)
self.assertNotIn(provider_ref, str(raised.exception))
session.rollback()
self.assertIsNone(source.deleted_at)
self.assertIsNone(credential.deleted_at)
def test_disabling_auth_immediately_scrubs_and_audits_database_credential(self) -> None: def test_disabling_auth_immediately_scrubs_and_audits_database_credential(self) -> None:
session = self.session() session = self.session()
session.add(Tenant(id="tenant-1", slug="tenant-1", name="Tenant")) session.add(Tenant(id="tenant-1", slug="tenant-1", name="Tenant"))