Skip to content

Support loose binding / aliasing for existing GCP Secrets in defineSecret #10597

@eLoyyyyy

Description

@eLoyyyyy

Description

defineSecret() requires the GCP Secret Manager secret ID to match the parameter name exactly. This breaks down when secrets are managed externally (Terraform, for example) under different naming conventions. There's no way to map DB_PASSWORD in your function to prod-global-database-password-v2 in Secret Manager without either duplicating the secret or hardcoding the secret name in application code.

I'd like an option to point defineSecret() at an existing secret by resource path.

Key Use Case

A team manages a database credential via Terraform as prod-global-database-password-v2. The Firebase Function should only know about DB_PASSWORD. Currently, trying to bridge that gap via .env:

DB_PASSWORD=projects/my-project/secrets/prod-global-database-password-v2

causes firebase deploy to fail with a 400:

spec.template.spec.containers[0].env: Secret environment variable overlaps non secret environment variable: DB_PASSWORD

Firebase CLI writes the .env value to environmentVariables and the defineSecret binding to secretEnvironmentVariables. Cloud Run rejects both on the same key.

Proposed Solution

If a value in .env uses a Secret: prefix, Firebase CLI should write it to secretEnvironmentVariables instead of environmentVariables:

# .env
DB_PASSWORD=Secret:projects/my-project/secrets/prod-global-database-password-v2

(Open to alternate syntax — sm:// or secretmanager:// may align better with GCP conventions.)

TypeScript side stays unchanged:

const dbPassword = defineSecret("DB_PASSWORD");

export const myFunction = onRequest({ secrets: [dbPassword] }, (req, res) => {
  const token = dbPassword.value();
  res.send("Success");
});

How it maps to Cloud Run

Firebase CLI strips the Secret: prefix and writes directly to Cloud Run's secretKeyRef:

{
  "name": "DB_PASSWORD",
  "valueSource": {
    "secretKeyRef": {
      "secret": "prod-global-database-password-v2",
      "version": "latest"
    }
  }
}

This avoids the collision entirely.

Alternatives Considered

In-code mapping: Pass secrets: ["prod-global-database-password-v2"] and assign manually with const DB_PASSWORD = process.env.prod_global_database_password_v2 (Cloud Run converts hyphens to underscores). This hardcodes infrastructure names in application code and drops the benefits of defineSecret() (type checks, configuration validation).

Duplicate the secret: Create a DB_PASSWORD secret in the Firebase project that mirrors the Terraform-managed one. Two secrets to keep in sync.

I'm happy to submit a PR if the maintainers are open to the .env prefix approach.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions