You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import { onInit } from "firebase-functions/v2";
import { onRequest } from "firebase-functions/https";
import { defineSecret } from "firebase-functions/params";
const SECRET = defineSecret("SECRET");
let coolApi: null | CoolApi = null;
onInit(() => {
coolApi = new CoolApi(SECRET.value());
});
/*
Can we do something like this??
onInit(
{ secrets: [SECRET] },
() => {
coolApi = new CoolApi(SECRET.value());
});
*/
export const joke1 = onRequest(
{ secrets: [SECRET] },
async (_req, res) => {
try {
const joke = await coolApi!.tellJoke();
res.status(200).send(joke);
} catch (error) {
console.error("Error: ", error);
res.status(500).send("Error fetching joke");
}
},
);
export const joke2 = onRequest(
async (_req, res) => {
try {
const joke = await coolApi!.tellJoke();
res.status(200).send(joke);
} catch (error) {
console.error("Error: ", error);
res.status(500).send("Error fetching joke");
}
},
);
class CoolApi {
private apiKey: string;
constructor(apiKey: string) {
if (apiKey) {
throw new Error("API key must be supplied");
}
this.apiKey = apiKey;
}
async tellJoke(): Promise<unknown> {
if (!this.apiKey) {
throw new Error("API key is not set");
}
const response = await fetch(`https://official-joke-api.appspot.com/random_joke?apiKey=${this.apiKey}`); // doesn't really need apikey
console.log("Response: ", response);
return response.json();
}
}
[REQUIRED] Steps to reproduce
Deploy functions
Go to link of joke1 function - joke is returned
Go to link of joke2 function - errors & no joke is returned
[REQUIRED] Expected behavior
Allow secrets to be bound to onInit() (or another initialization callback) so that global value can be initialized without having secrets declared in every Cloud Function consuming the global value.
Let's say we use a library initialized with an API key. It is heavily integrated to our firebase project and used in a lot of Cloud Functions and functions across the codebase. For example:
import {GoogleGenAI} from '@google/genai';
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const ai = new GoogleGenAI({apiKey: GEMINI_API_KEY});
...
// taken from @google/genai
// or in Firebase
import { GoogleGenAI } from "@google/genai";
import { defineSecret } from "firebase-functions/params";
const GEMINI_API_KEY = defineSecret("GEMINI_API_KEY");
let ai;
onInit(() => {
ai = new GoogleGenAI({ apiKey: GEMINI_API_KEY });
});
The issue is there is no way to check that the necessary secrets have been bound to all the Cloud Functions consuming the global value. This can be problematic as the project grows, or a Cloud Function is modified to use the API when it was not previously. Even more so when the API is used in shared functions that are called by Cloud Functions. The shared function is removed from the context of the Cloud Function where the secrets would be bound. The only way to surface this issue is at runtime.
Finally in the example above. If I do this
onInit(() => {
coolApi = new CoolApi(SECRET.value());
});
This will error whenever a Cloud Function is called that does not have SECRET bound to it. I could check if SECRET.value() is falsy before trying to initialize CoolApi - but it would then fail silently if it was ever undefined and should not be. I have no way of differentiating if it should be falsy or not.
I guess making a secret available in the global scope when it was not bound to a function introduces vulnerabilities??
We are migrating from firebase.config and having to trace back to the originating Cloud Function for every function that uses a globally declared API
It would be insanely useful to be able to initialize a global value and know it is going to be initialized properly and not wait to find out at runtime.
[REQUIRED] Actual behavior
Secrets cannot be accessed by onInit() unless they were bound to the Cloud Function that will use the global value. There is no way to ensure the Cloud Function has a secret bound until it fails at runtime
Were you able to successfully deploy your functions?
Yes
The text was updated successfully, but these errors were encountered:
Related issues
[REQUIRED] Version info
node: v20.18.1
firebase-functions: 6.3.2
firebase-tools: 14.4.0
firebase-admin: 13.4.0
[REQUIRED] Test case
index.ts
[REQUIRED] Steps to reproduce
joke1
function - joke is returnedjoke2
function - errors & no joke is returned[REQUIRED] Expected behavior
Allow secrets to be bound to
onInit()
(or another initialization callback) so that global value can be initialized without having secrets declared in every Cloud Function consuming the global value.Let's say we use a library initialized with an API key. It is heavily integrated to our firebase project and used in a lot of Cloud Functions and functions across the codebase. For example:
The issue is there is no way to check that the necessary secrets have been bound to all the Cloud Functions consuming the global value. This can be problematic as the project grows, or a Cloud Function is modified to use the API when it was not previously. Even more so when the API is used in shared functions that are called by Cloud Functions. The shared function is removed from the context of the Cloud Function where the secrets would be bound. The only way to surface this issue is at runtime.
Finally in the example above. If I do this
This will error whenever a Cloud Function is called that does not have
SECRET
bound to it. I could check ifSECRET.value()
is falsy before trying to initialize CoolApi - but it would then fail silently if it was ever undefined and should not be. I have no way of differentiating if it should be falsy or not.I guess making a secret available in the global scope when it was not bound to a function introduces vulnerabilities??
We are migrating from
firebase.config
and having to trace back to the originating Cloud Function for every function that uses a globally declared APIIt would be insanely useful to be able to initialize a global value and know it is going to be initialized properly and not wait to find out at runtime.
[REQUIRED] Actual behavior
Secrets cannot be accessed by
onInit()
unless they were bound to the Cloud Function that will use the global value. There is no way to ensure the Cloud Function has a secret bound until it fails at runtimeWere you able to successfully deploy your functions?
Yes
The text was updated successfully, but these errors were encountered: