Skip to content

Declarative security: failed first deploy orphans the managed SA, every retry creates a new one #10860

Description

@cabljac

Description

The managed SA is only rediscovered by reading serviceAccount off already-deployed endpoints (src/deploy/functions/prepare.ts:84-92). If the first deploy creates the SA and grants roles but function creation fails (e.g. #10859), there are zero deployed endpoints carrying it, so the next deploy finds no existingManagedSA and unconditionally mints a fresh random name via generateManagedServiceAccountName (prepare.ts:141-145, src/gcp/iam.ts:307-330).

Net effect: each failed deploy leaves behind a firebase-fn-<10digits> SA that nothing references, and the retry creates another one and grants the roles again. In our repro (storage-resize-images migration) a few retries produced several orphaned SAs, each holding Storage Admin and roles/aiplatform.user at project level. There's no cleanup path, so unused SAs with broad grants accumulate in the project IAM policy, which seems worth treating as a security issue as well as a correctness one.

Steps to reproduce

  1. Deploy a requireRoles codebase where function creation fails after SA creation (Declarative security: first deploy with a fresh managed SA fails with 404 actAs (no propagation wait or retry) #10859 reproduces this reliably)
  2. Re-deploy
  3. CLI logs Creating managed service account firebase-fn-<new number>... again; repeat for as many SAs as you like

A failing test reproducing this (empty have backend, SA already in project, new name generated anyway) is in draft PR #10858.

On the fix: should discovery fall back to looking up existing firebase-fn-* SAs in the project (the description already embeds the codebase, so they're identifiable, though gcp/iam.ts currently has no list API), or would you rather make the name deterministic per project+codebase so a retry converges on the same SA? The deterministic route also removes the need for the collision loop in generateManagedServiceAccountName.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions