Skip to content

fix(functions): fail-fast with actionable error when declarative security APIs are disabled - #11063

Merged
shettyvarun268 merged 12 commits into
mainfrom
shettyvarun268-declarative-security-api-check
Sep 11, 2026
Merged

fix(functions): fail-fast with actionable error when declarative security APIs are disabled#11063
shettyvarun268 merged 12 commits into
mainfrom
shettyvarun268-declarative-security-api-check

Conversation

@shettyvarun268

@shettyvarun268 shettyvarun268 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Description

When deploying functions configured with Declarative Security (requiresRole / Function Kits), deployment requires:

  1. iam.googleapis.com: To generate, inspect, and provision managed service accounts (firebase-fn-...).
  2. cloudresourcemanager.googleapis.com: To inspect and update project IAM policies.

If iam.googleapis.com is disabled on the target Google Cloud project, deployments previously passed the prepare phase, uploaded source code to Cloud Storage, and failed asynchronously 2–3 minutes later inside Cloud Build with an obscure error (generic::permission_denied: Identity and Access Management (IAM) API is disabled).

Rather than adding these APIs to STANDARD_APIS (which would auto-prompt enablement for all function deployments regardless of whether declarative security is used), this PR implements a lean fail-fast pre-flight check:

  1. Pre-Flight Validation (checkDeclarativeSecurityApisEnabled):

    • In discoverSecurityDetails(), checks that both iam.googleapis.com and cloudresourcemanager.googleapis.com are enabled on the project using ensureApiEnabled.check().
    • If either API is disabled, aborts immediately in Phase 4 ({ exit: 1 }) before creating service accounts or packaging code.
    • Provides an actionable error message containing:
      • The exact, copy-pasteable CLI command: gcloud services enable <apis> --project <projectId>
      • Direct Google Cloud Console enablement URLs (via ensureApiEnabled.enableApiURI(projectId, api)) for users without gcloud or who need to forward the link to their project owner.
  2. Least-Privilege & CI/CD Safety (Fail-Open):

    • Catches errors during the Service Usage inspection check (e.g. if a restricted CI/CD deployment service account lacks serviceusage.services.get) and fails open with logger.debug. This ensures deployment-only credentials that lack Service Usage read access are not falsely blocked when the APIs are actually enabled.
  3. Guards & Unenrollment Safety:

    • Standard functions (no requiresRole) bypass this check entirely.
    • Codebases unenrolling / opting out from declarative security (!requiredRoles && existingManagedSA) also bypass the check, ensuring users removing declarative security are never blocked.

Scenarios Tested

  • Unit Tests (src/deploy/functions/prepare.spec.ts):
    • ✔ Both iam.googleapis.com and cloudresourcemanager.googleapis.com disabled: asserts unified error message, combined gcloud command, and console URLs.
    • ✔ Only iam.googleapis.com disabled: asserts single-API isolation.
    • ✔ Only cloudresourcemanager.googleapis.com disabled: asserts single-API isolation.
    • ✔ Non-declarative codebase: asserts API enablement checks are completely skipped.
    • ✔ Restricted caller permissions: asserts that a 403 on serviceusage.services.get fails open and does not block deployment.
    • ✔ Unenrollment from declarative security: asserts unenrollment succeeds even if security APIs are disabled.
      (All 89 tests passing)

Sample Commands & Error Output

When required APIs are disabled:

$ firebase deploy --only functions:firestore-bigquery-export

Error: Cannot deploy functions with declarative security in codebase "firestore-bigquery-export". The following required Google Cloud API(s) are not enabled on project my-project:
  - iam.googleapis.com

Declarative security requires these APIs to provision and configure managed service accounts and IAM roles.
To enable them, run:

  gcloud services enable iam.googleapis.com --project my-project

Or ask a project owner to enable them in the Google Cloud Console:
  - iam.googleapis.com: https://console.cloud.google.com/apis/library/iam.googleapis.com?project=my-project

…rity APIs are disabled

When deploying functions with declarative security (requiresRole), check that iam.googleapis.com and cloudresourcemanager.googleapis.com are enabled on the project before attempting discovery or SA provisioning.

If either API is disabled, fail fast with an actionable error message providing both the exact gcloud services enable command and Google Cloud Console enablement URLs. Also handle downstream cached/race 403 SERVICE_DISABLED errors with cache eviction and friendly rethrowing.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a fail-fast mechanism that checks if the required Google Cloud APIs (IAM and Cloud Resource Manager) are enabled before deploying functions with declarative security, throwing actionable errors if they are not. The review feedback is highly constructive and identifies critical improvements: handling potential permission errors during API checks to avoid blocking users with restricted permissions, mapping service hostnames to friendly names to correctly match legacy GCP error messages, and adding a unit test to verify this mapping.

Comment thread src/deploy/functions/prepare.ts Outdated
Comment thread src/deploy/functions/prepare.ts Outdated
Comment thread src/deploy/functions/prepare.spec.ts Outdated
…I friendly names

- Catch errors in checkDeclarativeSecurityApisEnabled to fail open when caller lacks Service Usage permissions
- Add SERVICE_FRIENDLY_NAMES map in isServiceDisabledError for legacy GCP error messages
- Add unit tests verifying both cases
@shettyvarun268
shettyvarun268 marked this pull request as ready for review September 9, 2026 20:59
…ing cache

Remove downstream 403 catch and isServiceDisabledError helper, trusting local cache consistency like the rest of the CLI.

@ajperel ajperel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bunch of minor stuff but overall pretty good. Thanks for simplifying.

Comment thread src/deploy/functions/prepare.spec.ts Outdated
Comment thread src/deploy/functions/prepare.spec.ts Outdated
Comment thread src/deploy/functions/prepare.ts Outdated
Comment thread src/deploy/functions/prepare.ts Outdated
Comment thread src/deploy/functions/prepare.ts Outdated
… API check

- Move checkDeclarativeSecurityApisEnabled to src/deploy/functions/ensure.ts
- Scope fail-open error handling specifically to HTTP 403 and PERMISSION_DENIED
- Improve debug log message phrasing and preserve Winston error stack trace
- Use Sinon .withArgs(...) in prepare.spec.ts and shorten expectation assertions
- Add unit test verifying non-permission errors are re-thrown

@ajperel ajperel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Thanks for the fast iteration on this.

@shettyvarun268
shettyvarun268 merged commit 96d73f3 into main Sep 11, 2026
76 of 77 checks passed
@shettyvarun268
shettyvarun268 deleted the shettyvarun268-declarative-security-api-check branch September 11, 2026 23:32
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.

3 participants