Skip to content

supabase: guarded, auto-expiring temporary support access to restricted tenants#3115

Open
skord wants to merge 1 commit into
masterfrom
mdanko/temporary-support-access
Open

supabase: guarded, auto-expiring temporary support access to restricted tenants#3115
skord wants to merge 1 commit into
masterfrom
mdanko/temporary-support-access

Conversation

@skord

@skord skord commented Jul 2, 2026

Copy link
Copy Markdown
Member

What

Adds a guarded, auto-expiring mechanism for temporary support access to restricted
tenants that are deliberately excluded from the standing estuary_support/ role.

Why

Today, giving a restricted tenant temporary support access means an operator with
broad database access hand-writes a role_grants row and is trusted to remove it.
There is no expiry, no record of who granted it or why, and it requires write
access to the system-wide authorization table, which is also the ability to grant
anyone admin on anything. See ADR estuary/security#746.

What's in this PR

  • internal.support_access tracking table: the source of truth for temporary
    grants, separate from role_grants.
  • internal.grant_support_access(tenant, reason, duration),
    internal.revoke_support_access(tenant), and internal.expire_support_access(),
    all SECURITY DEFINER.
  • revoke all ... from public on the three functions.
  • pgTAP coverage in supabase/tests/support_access.test.sql.

Why it's safe

  • Operators get EXECUTE on the functions and never write role_grants directly,
    so they cannot escalate their own access. The grant function only attaches
    estuary_support/ to a named, existing tenant, and records session_user,
    reason, and expiry.
  • The sweeper only deletes grants that have a tracking row, so the permanent
    estuary_support/ grants normal tenants receive are never touched.

Out of band (not in this migration)

  • EXECUTE on these functions is granted to operator roles by the departmental
    database-roles tooling (a separate private repo), not here.

  • Expiry is enforced by pg_cron on the Supabase database. It is registered once,
    out of band, because pg_cron is absent from the sqlx test cluster:

    select cron.schedule('expire-support-access', '* * * * *',
                         $$ select internal.expire_support_access() $$);

Testing

  • supabase db reset applies all migrations cleanly.
  • mise run ci:sql-tap passes, including the new tests: grant attaches and logs;
    blank reason and unknown tenant are rejected; expire sweeps only expired, tracked
    grants and preserves permanent ones; revoke detaches and marks the row revoked.

Related

  • Implements ADR estuary/security#746.

@skord skord requested a review from jgraettinger July 2, 2026 23:44
@skord skord self-assigned this Jul 2, 2026
…ed tenants

Restricted tenants are deliberately not attached to estuary_support/, so
support cannot reach them by default. This adds an internal.support_access
tracking table plus SECURITY DEFINER functions to grant, revoke, and expire
temporary support access to a single tenant.

Operators receive EXECUTE on the functions (granted out of band by the
departmental-roles tooling) and never write public.role_grants directly, so
they cannot escalate their own access. The grant function only attaches
estuary_support/ to a named, existing tenant and logs who granted it, why,
and when it expires.

Expiry is enforced by pg_cron on the Supabase database, registered out of
band since pg_cron is absent from the sqlx test cluster. The sweeper only
removes grants that have a support_access tracking row, so the permanent
estuary_support/ grants normal tenants receive are never affected.

Adds pgTAP coverage in supabase/tests/support_access.test.sql.

Implements ADR estuary/security#746.
@skord skord force-pushed the mdanko/temporary-support-access branch from ad2b4c6 to f8f4e2e Compare July 2, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant