-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Prompt correctly for secrets defined in codebases with namespaced prefixes #11058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |||||
| import { Runtime } from "./runtimes/supported"; | ||||||
| import { ExprParseError } from "./cel"; | ||||||
| import { defineSecret } from "firebase-functions/params"; | ||||||
| import { toUpperSnakeCase } from "../../functions/secrets"; | ||||||
|
Berlioz marked this conversation as resolved.
|
||||||
|
|
||||||
| export const REGION_TBD = "REGION_TBD"; | ||||||
| export const SECRET_REF_PREFIX = "FIREBASE_SECRET_REF_"; | ||||||
|
|
@@ -354,15 +355,15 @@ | |||||
| envs: Record<string, params.ParamValue>; | ||||||
| secretRefs: Record<string, string>; | ||||||
| }> { | ||||||
| const { paramValues: paramValues, secretRefs: secretRefs } = await params.resolveParams( | ||||||
| opts.build.params, | ||||||
| opts.firebaseConfig, | ||||||
| envWithTypes(opts.build.params, opts.userEnvs), | ||||||
| opts.codebase, | ||||||
| opts.nonInteractive, | ||||||
| opts.force, | ||||||
| opts.isEmulator, | ||||||
| ); | ||||||
| const { paramValues: paramValues, secretRefs: secretRefs } = await params.resolveParams({ | ||||||
| params: opts.build.params, | ||||||
| firebaseConfig: opts.firebaseConfig, | ||||||
| userEnvs: envWithTypes(opts.build.params, opts.userEnvs), | ||||||
| codebase: opts.codebase, | ||||||
| nonInteractive: opts.nonInteractive, | ||||||
| force: opts.force, | ||||||
| isEmulator: opts.isEmulator, | ||||||
| }); | ||||||
|
|
||||||
| return { backend: toBackend(opts.build, paramValues), envs: paramValues, secretRefs: secretRefs }; | ||||||
| } | ||||||
|
|
@@ -516,7 +517,7 @@ | |||||
| // List param, we try resolving a String param instead. | ||||||
| try { | ||||||
| regions = params.resolveList(bdEndpoint.region, paramValues); | ||||||
| } catch (err: any) { | ||||||
| if (err instanceof ExprParseError) { | ||||||
| regions = [params.resolveString(bdEndpoint.region, paramValues)]; | ||||||
| } else { | ||||||
|
|
@@ -740,6 +741,14 @@ | |||||
| * Prefixes all endpoint IDs and secret names in a build with a given prefix. | ||||||
| * This ensures that functions and their associated secrets from different codebases | ||||||
| * remain isolated and don't conflict when deployed to the same project. | ||||||
| * | ||||||
| * Secret params in a build are rewritten to point to resource names respecting | ||||||
| * the same prefixing, so that the interactive secret creation flow still works | ||||||
| * and the non-interactive message prints the correct secret to create. | ||||||
| * | ||||||
| * When deploying a function which already has secret bindings in its .env files, | ||||||
| * applyEnvSecretBindings will run after this and overwrite both the updated | ||||||
| * secret params and SecretEnvVars to reflect deployed reality. | ||||||
| */ | ||||||
| export function applyPrefix(build: Build, prefix: string): void { | ||||||
| if (!prefix) { | ||||||
|
|
@@ -767,12 +776,19 @@ | |||||
| if (endpoint.secretEnvironmentVariables) { | ||||||
| endpoint.secretEnvironmentVariables = endpoint.secretEnvironmentVariables.map((secret) => ({ | ||||||
| ...secret, | ||||||
| secret: `${prefix}-${secret.secret}`, | ||||||
| secret: toUpperSnakeCase(`${prefix}-${secret.secret}`), | ||||||
| })); | ||||||
| } | ||||||
| } | ||||||
| build.endpoints = newEndpoints; | ||||||
|
|
||||||
| for (const param of build.params) { | ||||||
| if (param.type !== "secret") { | ||||||
| continue; | ||||||
| } | ||||||
| param.resourceId = toUpperSnakeCase(`${prefix}-${param.resourceId || param.name}`); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should actually do it in both places, because
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fwiw lowercase and hyphens are allowed in gcp secret names so we could also just change |
||||||
| } | ||||||
|
|
||||||
| if (build.lifecycleHooks) { | ||||||
| for (const hook of Object.values(build.lifecycleHooks)) { | ||||||
| if ("task" in hook) { | ||||||
|
|
@@ -806,7 +822,7 @@ | |||||
| * /version can be omitted and will cause the secret to resolve to whatever the latest version was at time of deploy. | ||||||
| * | ||||||
| * For each binding imported from the .env file, | ||||||
| * 1) TODO: Check if a conflicting SecretParam with the same name exists. If so, override the param so that the prompting flow will look in the right place when deciding whether or not to create a new Secret. | ||||||
| * 1) Check if a conflicting SecretParam with the same name exists. If so, override the param so that the prompting flow will look in the right place when deciding whether or not to create a new Secret. | ||||||
| * 2) Upsert the binding directly into the Build's SecretEnvVars, which will cause it to be actually available in process.ENV | ||||||
| */ | ||||||
| export function applyEnvSecretBindings( | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.