mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-01-23 13:19:03 -05:00
99 lines
3.0 KiB
TypeScript
99 lines
3.0 KiB
TypeScript
import { readFileSync } from 'fs'
|
|
import { SecretManagerServiceClient } from '@google-cloud/secret-manager'
|
|
import { zip } from 'lodash'
|
|
|
|
// List of secrets that are available to backend (api, functions, scripts, etc.)
|
|
// Edit them at:
|
|
// https://console.cloud.google.com/security/secret-manager?project=compass-130ba
|
|
export const secrets = (
|
|
[
|
|
// 'STRIPE_APIKEY',
|
|
// 'STRIPE_WEBHOOKSECRET',
|
|
'SUPABASE_KEY',
|
|
'SUPABASE_JWT_SECRET',
|
|
'SUPABASE_DB_PASSWORD',
|
|
'TEST_CREATE_USER_KEY',
|
|
'GEODB_API_KEY',
|
|
'RESEND_KEY',
|
|
'NEXT_PUBLIC_FIREBASE_API_KEY',
|
|
// Some typescript voodoo to keep the string literal types while being not readonly.
|
|
] as const
|
|
).concat()
|
|
|
|
type SecretId = (typeof secrets)[number]
|
|
|
|
// Fetches all secrets from google cloud.
|
|
// For deployed google cloud service, no credential is needed.
|
|
// For local and Vercel deployments: requires credentials json object.
|
|
export const getSecrets = async (credentials?: any, ...ids: SecretId[]) => {
|
|
let client: SecretManagerServiceClient
|
|
if (credentials) {
|
|
const projectId = credentials['project_id']
|
|
client = new SecretManagerServiceClient({
|
|
credentials,
|
|
projectId,
|
|
})
|
|
} else {
|
|
client = new SecretManagerServiceClient()
|
|
}
|
|
const projectId = await client.getProjectId()
|
|
|
|
const secretIds = ids.length > 0 ? ids : secrets
|
|
|
|
const fullSecretNames = secretIds.map(
|
|
(secret: string) =>
|
|
`${client.projectPath(projectId)}/secrets/${secret}/versions/latest`
|
|
)
|
|
|
|
const secretResponses = await Promise.all(
|
|
fullSecretNames.map((name) =>
|
|
client.accessSecretVersion({
|
|
name,
|
|
})
|
|
)
|
|
)
|
|
const secretValues = secretResponses.map(([response]) =>
|
|
response.payload!.data!.toString()
|
|
)
|
|
const pairs = zip(secretIds, secretValues) as [string, string][]
|
|
return Object.fromEntries(pairs)
|
|
}
|
|
|
|
// Fetches all secrets and loads them into process.env.
|
|
// Useful for running random backend code.
|
|
export const loadSecretsToEnv = async (credentials?: any) => {
|
|
const allSecrets = await getSecrets(credentials)
|
|
for (const [key, value] of Object.entries(allSecrets)) {
|
|
if (key && value) {
|
|
process.env[key] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get service account credentials from Vercel environment variable or local file.
|
|
export const getServiceAccountCredentials = (env: 'PROD' | 'DEV') => {
|
|
// Vercel environment variable for service credential.
|
|
const value =
|
|
env === 'PROD'
|
|
? process.env.PROD_FIREBASE_SERVICE_ACCOUNT_KEY
|
|
: process.env.DEV_FIREBASE_SERVICE_ACCOUNT_KEY
|
|
if (value && !process.env.LOCAL) {
|
|
return JSON.parse(value)
|
|
}
|
|
|
|
// Local environment variable for service credential.
|
|
const envVar = `GOOGLE_APPLICATION_CREDENTIALS_${env}`
|
|
const keyPath = process.env[envVar]
|
|
if (keyPath == null) {
|
|
throw new Error(
|
|
`Please set the ${envVar} environment variable to contain the path to your ${env} environment key file.`
|
|
)
|
|
}
|
|
|
|
try {
|
|
return JSON.parse(readFileSync(keyPath, { encoding: 'utf8' }))
|
|
} catch (e) {
|
|
throw new Error(`Failed to load service account key from ${keyPath}.`)
|
|
}
|
|
}
|