diff --git a/backend/package-lock.json b/backend/package-lock.json index 0423f0cb0..9655e1a28 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -33,7 +33,7 @@ "express-validator": "^6.14.2", "handlebars": "^4.7.7", "helmet": "^5.1.1", - "infisical-node": "^1.0.37", + "infisical-node": "^1.1.3", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", "jsrp": "^0.2.4", @@ -5322,6 +5322,14 @@ "node": ">=12" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6887,11 +6895,13 @@ } }, "node_modules/infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.1.3.tgz", + "integrity": "sha512-MLcZQ/zdpCYFRbj50Tn4Qm58wSKPQfKc3xX4I0c3NnFZvMGd50wnoG1jkkNKjKiYU5h7QDpOg0XZSvlU7yuG6g==", "dependencies": { "axios": "^1.3.3", + "dotenv": "^16.0.3", + "node-cache": "^5.1.2", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" } @@ -8385,6 +8395,17 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/node-fetch": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", @@ -17237,6 +17258,11 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -18427,11 +18453,13 @@ "dev": true }, "infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.1.3.tgz", + "integrity": "sha512-MLcZQ/zdpCYFRbj50Tn4Qm58wSKPQfKc3xX4I0c3NnFZvMGd50wnoG1jkkNKjKiYU5h7QDpOg0XZSvlU7yuG6g==", "requires": { "axios": "^1.3.3", + "dotenv": "^16.0.3", + "node-cache": "^5.1.2", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" } @@ -19579,6 +19607,14 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, "node-fetch": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", diff --git a/backend/package.json b/backend/package.json index 084f6b08e..425971d2b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -3,9 +3,8 @@ "@aws-sdk/client-secrets-manager": "^3.303.0", "@godaddy/terminus": "^4.11.2", "@octokit/rest": "^19.0.5", - "@sentry/node": "^7.45.0", - "@sentry/tracing": "^7.46.0", "@sentry/node": "^7.41.0", + "@sentry/tracing": "^7.46.0", "@types/crypto-js": "^4.1.1", "@types/libsodium-wrappers": "^0.7.10", "argon2": "^0.30.3", @@ -25,7 +24,7 @@ "express-validator": "^6.14.2", "handlebars": "^4.7.7", "helmet": "^5.1.1", - "infisical-node": "^1.0.37", + "infisical-node": "^1.1.3", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", "jsrp": "^0.2.4", diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index e2b52eab3..4c6bed800 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -1,69 +1,69 @@ import InfisicalClient from 'infisical-node'; -const infisical = new InfisicalClient({ +const client = new InfisicalClient({ token: process.env.INFISICAL_TOKEN! }); -export const getPort = async () => await infisical.get('PORT')! || 4000; -export const getInviteOnlySignup = async () => await infisical.get('INVITE_ONLY_SIGNUP')! == undefined ? false : await infisical.get('INVITE_ONLY_SIGNUP'); -export const getEncryptionKey = async () => await infisical.get('ENCRYPTION_KEY')!; -export const getSaltRounds = async () => parseInt(await infisical.get('SALT_ROUNDS')!) || 10; -export const getJwtAuthLifetime = async () => await infisical.get('JWT_AUTH_LIFETIME')! || '10d'; -export const getJwtAuthSecret = async () => await infisical.get('JWT_AUTH_SECRET')!; -export const getJwtMfaLifetime = async () => await infisical.get('JWT_MFA_LIFETIME')! || '5m'; -export const getJwtMfaSecret = async () => await infisical.get('JWT_MFA_LIFETIME')! || '5m'; -export const getJwtRefreshLifetime = async () => await infisical.get('JWT_REFRESH_LIFETIME')! || '90d'; -export const getJwtRefreshSecret = async () => await infisical.get('JWT_REFRESH_SECRET')!; -export const getJwtServiceSecret = async () => await infisical.get('JWT_SERVICE_SECRET')!; -export const getJwtSignupLifetime = async () => await infisical.get('JWT_SIGNUP_LIFETIME')! || '15m'; -export const getJwtSignupSecret = async () => await infisical.get('JWT_SIGNUP_SECRET')!; -export const getMongoURL = async () => await infisical.get('MONGO_URL')!; -export const getNodeEnv = async () => await infisical.get('NODE_ENV')! || 'production'; -export const getVerboseErrorOutput = async () => await infisical.get('VERBOSE_ERROR_OUTPUT')! === 'true' && true; -export const getLokiHost = async () => await infisical.get('LOKI_HOST')!; -export const getClientIdAzure = async () => await infisical.get('CLIENT_ID_AZURE')!; -export const getClientIdHeroku = async () => await infisical.get('CLIENT_ID_HEROKU')!; -export const getClientIdVercel = async () => await infisical.get('CLIENT_ID_VERCEL')!; -export const getClientIdNetlify = async () => await infisical.get('CLIENT_ID_NETLIFY')!; -export const getClientIdGitHub = async () => await infisical.get('CLIENT_ID_GITHUB')!; -export const getClientIdGitLab = async () => await infisical.get('CLIENT_ID_GITLAB')!; -export const getClientSecretAzure = async () => await infisical.get('CLIENT_SECRET_AZURE')!; -export const getClientSecretHeroku = async () => await infisical.get('CLIENT_SECRET_HEROKU')!; -export const getClientSecretVercel = async () => await infisical.get('CLIENT_SECRET_VERCEL')!; -export const getClientSecretNetlify = async () => await infisical.get('CLIENT_SECRET_NETLIFY')!; -export const getClientSecretGitHub = async () => await infisical.get('CLIENT_SECRET_GITHUB')!; -export const getClientSecretGitLab = async () => await infisical.get('CLIENT_SECRET_GITLAB')!; -export const getClientSlugVercel = async () => await infisical.get('CLIENT_SLUG_VERCEL')!; -export const getPostHogHost = async () => await infisical.get('POSTHOG_HOST')! || 'https://app.posthog.com'; -export const getPostHogProjectApiKey = async () => await infisical.get('POSTHOG_PROJECT_API_KEY')! || 'phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE'; -export const getSentryDSN = async () => await infisical.get('SENTRY_DSN')!; -export const getSiteURL = async () => await infisical.get('SITE_URL')!; -export const getSmtpHost = async () => await infisical.get('SMTP_HOST')!; -export const getSmtpSecure = async () => await infisical.get('SMTP_SECURE')! === 'true' || false; -export const getSmtpPort = async () => parseInt(await infisical.get('SMTP_PORT')!) || 587; -export const getSmtpUsername = async () => await infisical.get('SMTP_USERNAME')!; -export const getSmtpPassword = async () => await infisical.get('SMTP_PASSWORD')!; -export const getSmtpFromAddress = async () => await infisical.get('SMTP_FROM_ADDRESS')!; -export const getSmtpFromName = async () => await infisical.get('SMTP_FROM_NAME')! || 'Infisical'; -export const getStripeProductStarter = async () => await infisical.get('STRIPE_PRODUCT_STARTER')!; -export const getStripeProductPro = async () => await infisical.get('STRIPE_PRODUCT_PRO')!; -export const getStripeProductTeam = async () => await infisical.get('STRIPE_PRODUCT_TEAM')!; -export const getStripePublishableKey = async () => await infisical.get('STRIPE_PUBLISHABLE_KEY')!; -export const getStripeSecretKey = async () => await infisical.get('STRIPE_SECRET_KEY')!; -export const getStripeWebhookSecret = async () => await infisical.get('STRIPE_WEBHOOK_SECRET')!; -export const getTelemetryEnabled = async () => await infisical.get('TELEMETRY_ENABLED')! !== 'false' && true; -export const getLoopsApiKey = async () => await infisical.get('LOOPS_API_KEY')!; -export const getSmtpConfigured = async () => await infisical.get('SMTP_HOST') == '' || await infisical.get('SMTP_HOST') == undefined ? false : true +export const getPort = async () => (await client.getSecret('PORT')).secretValue || 4000; +export const getInviteOnlySignup = async () => (await client.getSecret('INVITE_ONLY_SIGNUP')).secretValue == undefined ? false : await client.getSecret('INVITE_ONLY_SIGNUP'); +export const getEncryptionKey = async () => (await client.getSecret('ENCRYPTION_KEY')).secretValue; +export const getSaltRounds = async () => parseInt((await client.getSecret('SALT_ROUNDS')).secretValue) || 10; +export const getJwtAuthLifetime = async () => (await client.getSecret('JWT_AUTH_LIFETIME')).secretValue || '10d'; +export const getJwtAuthSecret = async () => (await client.getSecret('JWT_AUTH_SECRET')).secretValue; +export const getJwtMfaLifetime = async () => (await client.getSecret('JWT_MFA_LIFETIME')).secretValue || '5m'; +export const getJwtMfaSecret = async () => (await client.getSecret('JWT_MFA_LIFETIME')).secretValue || '5m'; +export const getJwtRefreshLifetime = async () => (await client.getSecret('JWT_REFRESH_LIFETIME')).secretValue || '90d'; +export const getJwtRefreshSecret = async () => (await client.getSecret('JWT_REFRESH_SECRET')).secretValue; +export const getJwtServiceSecret = async () => (await client.getSecret('JWT_SERVICE_SECRET')).secretValue; +export const getJwtSignupLifetime = async () => (await client.getSecret('JWT_SIGNUP_LIFETIME')).secretValue || '15m'; +export const getJwtSignupSecret = async () => (await client.getSecret('JWT_SIGNUP_SECRET')).secretValue; +export const getMongoURL = async () => (await client.getSecret('MONGO_URL')).secretValue; +export const getNodeEnv = async () => (await client.getSecret('NODE_ENV')).secretValue || 'production'; +export const getVerboseErrorOutput = async () => (await client.getSecret('VERBOSE_ERROR_OUTPUT')).secretValue === 'true' && true; +export const getLokiHost = async () => (await client.getSecret('LOKI_HOST')).secretValue; +export const getClientIdAzure = async () => (await client.getSecret('CLIENT_ID_AZURE')).secretValue; +export const getClientIdHeroku = async () => (await client.getSecret('CLIENT_ID_HEROKU')).secretValue; +export const getClientIdVercel = async () => (await client.getSecret('CLIENT_ID_VERCEL')).secretValue; +export const getClientIdNetlify = async () => (await client.getSecret('CLIENT_ID_NETLIFY')).secretValue; +export const getClientIdGitHub = async () => (await client.getSecret('CLIENT_ID_GITHUB')).secretValue; +export const getClientIdGitLab = async () => (await client.getSecret('CLIENT_ID_GITLAB')).secretValue; +export const getClientSecretAzure = async () => (await client.getSecret('CLIENT_SECRET_AZURE')).secretValue; +export const getClientSecretHeroku = async () => (await client.getSecret('CLIENT_SECRET_HEROKU')).secretValue; +export const getClientSecretVercel = async () => (await client.getSecret('CLIENT_SECRET_VERCEL')).secretValue; +export const getClientSecretNetlify = async () => (await client.getSecret('CLIENT_SECRET_NETLIFY')).secretValue; +export const getClientSecretGitHub = async () => (await client.getSecret('CLIENT_SECRET_GITHUB')).secretValue; +export const getClientSecretGitLab = async () => (await client.getSecret('CLIENT_SECRET_GITLAB')).secretValue; +export const getClientSlugVercel = async () => (await client.getSecret('CLIENT_SLUG_VERCEL')).secretValue; +export const getPostHogHost = async () => (await client.getSecret('POSTHOG_HOST')).secretValue || 'https://app.posthog.com'; +export const getPostHogProjectApiKey = async () => (await client.getSecret('POSTHOG_PROJECT_API_KEY')).secretValue || 'phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE'; +export const getSentryDSN = async () => (await client.getSecret('SENTRY_DSN')).secretValue; +export const getSiteURL = async () => (await client.getSecret('SITE_URL')).secretValue; +export const getSmtpHost = async () => (await client.getSecret('SMTP_HOST')).secretValue; +export const getSmtpSecure = async () => (await client.getSecret('SMTP_SECURE')).secretValue === 'true' || false; +export const getSmtpPort = async () => parseInt((await client.getSecret('SMTP_PORT')).secretValue) || 587; +export const getSmtpUsername = async () => (await client.getSecret('SMTP_USERNAME')).secretValue; +export const getSmtpPassword = async () => (await client.getSecret('SMTP_PASSWORD')).secretValue; +export const getSmtpFromAddress = async () => (await client.getSecret('SMTP_FROM_ADDRESS')).secretValue; +export const getSmtpFromName = async () => (await client.getSecret('SMTP_FROM_NAME')).secretValue || 'Infisical'; +export const getStripeProductStarter = async () => (await client.getSecret('STRIPE_PRODUCT_STARTER')).secretValue; +export const getStripeProductPro = async () => (await client.getSecret('STRIPE_PRODUCT_PRO')).secretValue; +export const getStripeProductTeam = async () => (await client.getSecret('STRIPE_PRODUCT_TEAM')).secretValue; +export const getStripePublishableKey = async () => (await client.getSecret('STRIPE_PUBLISHABLE_KEY')).secretValue; +export const getStripeSecretKey = async () => (await client.getSecret('STRIPE_SECRET_KEY')).secretValue; +export const getStripeWebhookSecret = async () => (await client.getSecret('STRIPE_WEBHOOK_SECRET')).secretValue; +export const getTelemetryEnabled = async () => (await client.getSecret('TELEMETRY_ENABLED')).secretValue !== 'false' && true; +export const getLoopsApiKey = async () => (await client.getSecret('LOOPS_API_KEY')).secretValue; +export const getSmtpConfigured = async () => (await client.getSecret('SMTP_HOST')).secretValue == '' || (await client.getSecret('SMTP_HOST')).secretValue == undefined ? false : true export const getHttpsEnabled = async () => { if ((await getNodeEnv()) != "production") { // no https for anything other than prod return false } - if ((await infisical.get('HTTPS_ENABLED')) == undefined || (await infisical.get('HTTPS_ENABLED')) == "") { + if ((await client.getSecret('HTTPS_ENABLED')).secretValue == undefined || (await client.getSecret('HTTPS_ENABLED')).secretValue == "") { // default when no value present return true } - return (await infisical.get('HTTPS_ENABLED')) === 'true' && true + return (await client.getSecret('HTTPS_ENABLED')).secretValue === 'true' && true } \ No newline at end of file diff --git a/backend/src/helpers/secrets.ts b/backend/src/helpers/secrets.ts index 87b828659..c184bad9c 100644 --- a/backend/src/helpers/secrets.ts +++ b/backend/src/helpers/secrets.ts @@ -233,27 +233,29 @@ const initSecretBlindIndexDataHelper = async () => { } }); - const secretBlindIndexDataToInsert = workspaceIdsToBlindIndex.map((workspaceToBlindIndex) => { - const salt = crypto.randomBytes(16).toString('base64'); + const secretBlindIndexDataToInsert = await Promise.all( + workspaceIdsToBlindIndex.map(async (workspaceToBlindIndex) => { + const salt = crypto.randomBytes(16).toString('base64'); - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag - } = encryptSymmetric({ - plaintext: salt, - key: await getEncryptionKey() - }); + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag + } = encryptSymmetric({ + plaintext: salt, + key: await getEncryptionKey() + }); - const secretBlindIndexData = new SecretBlindIndexData({ - workspace: workspaceToBlindIndex, - encryptedSaltCiphertext, - saltIV, - saltTag + const secretBlindIndexData = new SecretBlindIndexData({ + workspace: workspaceToBlindIndex, + encryptedSaltCiphertext, + saltIV, + saltTag + }) + + return secretBlindIndexData; }) - - return secretBlindIndexData; - }); + ); if (secretBlindIndexDataToInsert.length > 0) { await SecretBlindIndexData.insertMany(secretBlindIndexDataToInsert); diff --git a/backend/src/index.ts b/backend/src/index.ts index 7aecafe9e..c278da13f 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,7 +1,6 @@ import mongoose from 'mongoose'; import dotenv from 'dotenv'; dotenv.config(); -import infisical from 'infisical-node'; import express from 'express'; import helmet from 'helmet'; import cors from 'cors';