Merge pull request #2617 from Infisical/misc/allow-secret-scanning-whitelist

misc: added secret scanning whitelist configuration
This commit is contained in:
Maidul Islam
2024-10-18 18:03:54 -04:00
committed by GitHub
8 changed files with 26 additions and 10 deletions
+4
View File
@@ -95,6 +95,10 @@ RUN mkdir frontend-build
# Production stage # Production stage
FROM base AS production FROM base AS production
RUN apk add --upgrade --no-cache ca-certificates 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 \ RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 non-root-user && adduser --system --uid 1001 non-root-user
@@ -2,6 +2,8 @@ import { z } from "zod";
import { GitAppOrgSchema, SecretScanningGitRisksSchema } from "@app/db/schemas"; import { GitAppOrgSchema, SecretScanningGitRisksSchema } from "@app/db/schemas";
import { SecretScanningRiskStatus } from "@app/ee/services/secret-scanning/secret-scanning-types"; 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 { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
@@ -23,6 +25,13 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { 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({ const session = await server.services.secretScanning.createInstallationSession({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
@@ -30,6 +39,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.body.organizationId orgId: req.body.organizationId
}); });
return session; return session;
} }
}); });
@@ -1,6 +1,6 @@
import { ProbotOctokit } from "probot"; 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 { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
@@ -61,7 +61,7 @@ export const secretScanningQueueFactory = ({
const getOrgAdminEmails = async (organizationId: string) => { const getOrgAdminEmails = async (organizationId: string) => {
// get emails of admins // get emails of admins
const adminsOfWork = await orgMemberDAL.findMembership({ const adminsOfWork = await orgMemberDAL.findMembership({
orgId: organizationId, [`${TableName.Organization}.id` as string]: organizationId,
role: OrgMembershipRole.Admin role: OrgMembershipRole.Admin
}); });
return adminsOfWork.filter((userObject) => userObject.email).map((userObject) => userObject.email as string); return adminsOfWork.filter((userObject) => userObject.email).map((userObject) => userObject.email as string);
@@ -90,7 +90,7 @@ export const secretScanningServiceFactory = ({
const { const {
data: { repositories } data: { repositories }
} = await octokit.apps.listReposAccessibleToInstallation(); } = await octokit.apps.listReposAccessibleToInstallation();
if (!appCfg.DISABLE_SECRET_SCANNING) { if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(actorOrgId)) {
await Promise.all( await Promise.all(
repositories.map(({ id, full_name }) => repositories.map(({ id, full_name }) =>
secretScanningQueue.startFullRepoScan({ secretScanningQueue.startFullRepoScan({
@@ -164,7 +164,7 @@ export const secretScanningServiceFactory = ({
}); });
if (!installationLink) return; if (!installationLink) return;
if (!appCfg.DISABLE_SECRET_SCANNING) { if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(installationLink.orgId)) {
await secretScanningQueue.startPushEventScan({ await secretScanningQueue.startPushEventScan({
commits, commits,
pusher: { name: pusher.name, email: pusher.email }, pusher: { name: pusher.name, email: pusher.email },
+3 -1
View File
@@ -142,6 +142,7 @@ const envSchema = z
SECRET_SCANNING_WEBHOOK_SECRET: zpStr(z.string().optional()), SECRET_SCANNING_WEBHOOK_SECRET: zpStr(z.string().optional()),
SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()), SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()),
SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()), SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()),
SECRET_SCANNING_ORG_WHITELIST: zpStr(z.string().optional()),
// LICENSE // LICENSE
LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")), LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")),
LICENSE_SERVER_KEY: zpStr(z.string().optional()), 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_GIT_APP_ID) &&
Boolean(data.SECRET_SCANNING_PRIVATE_KEY) && Boolean(data.SECRET_SCANNING_PRIVATE_KEY) &&
Boolean(data.SECRET_SCANNING_WEBHOOK_SECRET), 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<z.infer<typeof envSchema>>; let envCfg: Readonly<z.infer<typeof envSchema>>;
+1 -3
View File
@@ -225,9 +225,7 @@ export const registerRoutes = async (
}: { auditLogDb?: Knex; db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory } }: { auditLogDb?: Knex; db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory }
) => { ) => {
const appCfg = getConfig(); const appCfg = getConfig();
if (!appCfg.DISABLE_SECRET_SCANNING) { await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });
await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });
}
// db layers // db layers
const userDAL = userDALFactory(db); const userDAL = userDALFactory(db);
@@ -230,6 +230,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
(!orgs?.map((org) => org.id)?.includes(router.query.id as string) && (!orgs?.map((org) => org.id)?.includes(router.query.id as string) &&
!router.asPath.includes("project") && !router.asPath.includes("project") &&
!router.asPath.includes("personal") && !router.asPath.includes("personal") &&
!router.asPath.includes("secret-scanning") &&
!router.asPath.includes("integration"))) !router.asPath.includes("integration")))
) { ) {
router.push(`/org/${currentOrg?.id}/overview`); router.push(`/org/${currentOrg?.id}/overview`);
@@ -72,7 +72,8 @@ const SecretScanning = withPermission(
</div> </div>
{config.isSecretScanningDisabled && ( {config.isSecretScanningDisabled && (
<NoticeBanner title="Secret scanning is in maintenance" className="mb-4"> <NoticeBanner title="Secret scanning is in maintenance" className="mb-4">
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.
</NoticeBanner> </NoticeBanner>
)} )}
<div className="relative mb-6 flex justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6"> <div className="relative mb-6 flex justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6">
@@ -116,7 +117,7 @@ const SecretScanning = withPermission(
colorSchema="primary" colorSchema="primary"
onClick={generateNewIntegrationSession} onClick={generateNewIntegrationSession}
className="h-min py-2" className="h-min py-2"
isDisabled={!isAllowed || config.isSecretScanningDisabled} isDisabled={!isAllowed}
> >
Integrate with GitHub Integrate with GitHub
</Button> </Button>