mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 16:27:40 +00:00
Merge pull request #2617 from Infisical/misc/allow-secret-scanning-whitelist
misc: added secret scanning whitelist configuration
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-2
@@ -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 },
|
||||||
|
|||||||
@@ -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>>;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user