diff --git a/Dockerfile.standalone-infisical b/Dockerfile.standalone-infisical index 8ffe7e3de..269cbfcf9 100644 --- a/Dockerfile.standalone-infisical +++ b/Dockerfile.standalone-infisical @@ -95,6 +95,10 @@ RUN mkdir frontend-build # Production stage FROM base AS production RUN apk add --upgrade --no-cache ca-certificates +RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical=0.31.1 && apk add --no-cache git + RUN addgroup --system --gid 1001 nodejs \ && adduser --system --uid 1001 non-root-user diff --git a/backend/src/ee/routes/v1/secret-scanning-router.ts b/backend/src/ee/routes/v1/secret-scanning-router.ts index 2604d7232..89784600a 100644 --- a/backend/src/ee/routes/v1/secret-scanning-router.ts +++ b/backend/src/ee/routes/v1/secret-scanning-router.ts @@ -2,6 +2,8 @@ import { z } from "zod"; import { GitAppOrgSchema, SecretScanningGitRisksSchema } from "@app/db/schemas"; import { SecretScanningRiskStatus } from "@app/ee/services/secret-scanning/secret-scanning-types"; +import { getConfig } from "@app/lib/config/env"; +import { BadRequestError } from "@app/lib/errors"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -23,6 +25,13 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) = }, onRequest: verifyAuth([AuthMode.JWT]), handler: async (req) => { + const appCfg = getConfig(); + if (!appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(req.auth.orgId)) { + throw new BadRequestError({ + message: "Secret scanning is temporarily unavailable." + }); + } + const session = await server.services.secretScanning.createInstallationSession({ actor: req.permission.type, actorId: req.permission.id, @@ -30,6 +39,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) = actorOrgId: req.permission.orgId, orgId: req.body.organizationId }); + return session; } }); diff --git a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts index 1b19fd7f5..1907ddd9a 100644 --- a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts +++ b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts @@ -1,6 +1,6 @@ import { ProbotOctokit } from "probot"; -import { OrgMembershipRole } from "@app/db/schemas"; +import { OrgMembershipRole, TableName } from "@app/db/schemas"; import { getConfig } from "@app/lib/config/env"; import { logger } from "@app/lib/logger"; import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; @@ -61,7 +61,7 @@ export const secretScanningQueueFactory = ({ const getOrgAdminEmails = async (organizationId: string) => { // get emails of admins const adminsOfWork = await orgMemberDAL.findMembership({ - orgId: organizationId, + [`${TableName.Organization}.id` as string]: organizationId, role: OrgMembershipRole.Admin }); return adminsOfWork.filter((userObject) => userObject.email).map((userObject) => userObject.email as string); diff --git a/backend/src/ee/services/secret-scanning/secret-scanning-service.ts b/backend/src/ee/services/secret-scanning/secret-scanning-service.ts index 913972cd1..945164094 100644 --- a/backend/src/ee/services/secret-scanning/secret-scanning-service.ts +++ b/backend/src/ee/services/secret-scanning/secret-scanning-service.ts @@ -90,7 +90,7 @@ export const secretScanningServiceFactory = ({ const { data: { repositories } } = await octokit.apps.listReposAccessibleToInstallation(); - if (!appCfg.DISABLE_SECRET_SCANNING) { + if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(actorOrgId)) { await Promise.all( repositories.map(({ id, full_name }) => secretScanningQueue.startFullRepoScan({ @@ -164,7 +164,7 @@ export const secretScanningServiceFactory = ({ }); if (!installationLink) return; - if (!appCfg.DISABLE_SECRET_SCANNING) { + if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(installationLink.orgId)) { await secretScanningQueue.startPushEventScan({ commits, pusher: { name: pusher.name, email: pusher.email }, diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 2b7a3a733..60f4b74a9 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -142,6 +142,7 @@ const envSchema = z SECRET_SCANNING_WEBHOOK_SECRET: zpStr(z.string().optional()), SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()), SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()), + SECRET_SCANNING_ORG_WHITELIST: zpStr(z.string().optional()), // LICENSE LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")), LICENSE_SERVER_KEY: zpStr(z.string().optional()), @@ -177,7 +178,8 @@ const envSchema = z Boolean(data.SECRET_SCANNING_GIT_APP_ID) && Boolean(data.SECRET_SCANNING_PRIVATE_KEY) && Boolean(data.SECRET_SCANNING_WEBHOOK_SECRET), - samlDefaultOrgSlug: data.DEFAULT_SAML_ORG_SLUG + samlDefaultOrgSlug: data.DEFAULT_SAML_ORG_SLUG, + SECRET_SCANNING_ORG_WHITELIST: data.SECRET_SCANNING_ORG_WHITELIST?.split(",") })); let envCfg: Readonly>; diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 326b283f5..68df7f2d9 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -225,9 +225,7 @@ export const registerRoutes = async ( }: { auditLogDb?: Knex; db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory } ) => { const appCfg = getConfig(); - if (!appCfg.DISABLE_SECRET_SCANNING) { - await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" }); - } + await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" }); // db layers const userDAL = userDALFactory(db); diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index 09f49652c..312e6af17 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -230,6 +230,7 @@ export const AppLayout = ({ children }: LayoutProps) => { (!orgs?.map((org) => org.id)?.includes(router.query.id as string) && !router.asPath.includes("project") && !router.asPath.includes("personal") && + !router.asPath.includes("secret-scanning") && !router.asPath.includes("integration"))) ) { router.push(`/org/${currentOrg?.id}/overview`); diff --git a/frontend/src/pages/org/[id]/secret-scanning/index.tsx b/frontend/src/pages/org/[id]/secret-scanning/index.tsx index fd44f6961..50e294d97 100644 --- a/frontend/src/pages/org/[id]/secret-scanning/index.tsx +++ b/frontend/src/pages/org/[id]/secret-scanning/index.tsx @@ -72,7 +72,8 @@ const SecretScanning = withPermission( {config.isSecretScanningDisabled && ( - We are working on improving the performance of secret scanning due to increased usage. + We are working on improving the performance of secret scanning due to increased + usage. )}
@@ -116,7 +117,7 @@ const SecretScanning = withPermission( colorSchema="primary" onClick={generateNewIntegrationSession} className="h-min py-2" - isDisabled={!isAllowed || config.isSecretScanningDisabled} + isDisabled={!isAllowed} > Integrate with GitHub