From 56d430afd6d0dfac63b58792906a86cd80166713 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 17 Jul 2023 16:41:33 -0400 Subject: [PATCH] update risk status and update email notifications --- .../v1/secretScanningController.ts | 12 ++++---- backend/src/routes/v1/secretScanning.ts | 1 + .../services/GithubSecretScanningService.ts | 9 +----- .../templates/secretLeakIncident.handlebars | 11 ++++++-- .../secret-scanning/getRisksByOrganization.ts | 3 +- .../components/RiskStatusSelection.tsx | 28 +++++++++++++++++++ .../components/SecretScanningLogsTable.tsx | 22 ++++----------- 7 files changed, 52 insertions(+), 34 deletions(-) create mode 100644 frontend/src/views/SecretScanning/components/RiskStatusSelection.tsx diff --git a/backend/src/controllers/v1/secretScanningController.ts b/backend/src/controllers/v1/secretScanningController.ts index 43ddc1a67..e84e5994c 100644 --- a/backend/src/controllers/v1/secretScanningController.ts +++ b/backend/src/controllers/v1/secretScanningController.ts @@ -5,7 +5,7 @@ import { Types } from "mongoose"; import { UnauthorizedRequestError } from "../../utils/errors"; import GitAppOrganizationInstallation from "../../models/gitAppOrganizationInstallation"; import { MembershipOrg } from "../../models"; -import GitRisks, { STATUS_UNRESOLVED } from "../../models/gitRisks"; +import GitRisks, { STATUS_RESOLVED_FALSE_POSITIVE, STATUS_RESOLVED_NOT_REVOKED, STATUS_RESOLVED_REVOKED } from "../../models/gitRisks"; export const createInstallationSession = async (req: Request, res: Response) => { const sessionId = crypto.randomBytes(16).toString("hex"); @@ -72,7 +72,7 @@ export const getCurrentOrganizationInstallationStatus = async (req: Request, res export const getRisksForOrganization = async (req: Request, res: Response) => { const { organizationId } = req.params - const risks = await GitRisks.find({ organization: organizationId, status: STATUS_UNRESOLVED }).sort({ createdAt: -1 }).lean() + const risks = await GitRisks.find({ organization: organizationId }).sort({ createdAt: -1 }).lean() res.json({ risks: risks }) @@ -81,9 +81,11 @@ export const getRisksForOrganization = async (req: Request, res: Response) => { export const updateRisksStatus = async (req: Request, res: Response) => { const { riskId } = req.params const { status } = req.body - const risks = await GitRisks.findByIdAndUpdate(riskId, { - sttaus: status + const isRiskResolved = status == STATUS_RESOLVED_FALSE_POSITIVE || status == STATUS_RESOLVED_REVOKED || status == STATUS_RESOLVED_NOT_REVOKED ? true : false + const risk = await GitRisks.findByIdAndUpdate(riskId, { + status: status, + isResolved: isRiskResolved }).lean() - res.json(risks) + res.json(risk) } \ No newline at end of file diff --git a/backend/src/routes/v1/secretScanning.ts b/backend/src/routes/v1/secretScanning.ts index a809fe3aa..fa162ce68 100644 --- a/backend/src/routes/v1/secretScanning.ts +++ b/backend/src/routes/v1/secretScanning.ts @@ -69,6 +69,7 @@ router.post( }), param("organizationId").exists().trim(), param("riskId").exists().trim(), + body("status").exists(), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], acceptedStatuses: [ACCEPTED], diff --git a/backend/src/services/GithubSecretScanningService.ts b/backend/src/services/GithubSecretScanningService.ts index 48426ea26..cda2351c4 100644 --- a/backend/src/services/GithubSecretScanningService.ts +++ b/backend/src/services/GithubSecretScanningService.ts @@ -3,7 +3,7 @@ import { exec } from "child_process"; import { mkdir, readFile, rm, writeFile } from "fs"; import { tmpdir } from "os"; import { join } from "path" -import GitRisks, { STATUS_RESOLVED_FALSE_POSITIVE } from "../models/gitRisks"; +import GitRisks from "../models/gitRisks"; import GitAppOrganizationInstallation from "../models/gitAppOrganizationInstallation"; import MembershipOrg from "../models/membershipOrg"; import { ADMIN, OWNER } from "../variables"; @@ -98,8 +98,6 @@ export default async (app: Probot) => { } // change to update - const noneFalsePositiveFindings: { [key: string]: SecretMatch; } = {} - for (const key in allFindingsByFingerprint) { const risk = await GitRisks.findOneAndUpdate({ fingerprint: allFindingsByFingerprint[key].Fingerprint }, { @@ -111,11 +109,6 @@ export default async (app: Probot) => { }, { upsert: true }).lean() - - if (risk?.status == STATUS_RESOLVED_FALSE_POSITIVE) { - noneFalsePositiveFindings[key] = { ...convertKeysToLowercase(allFindingsByFingerprint[key]) } - } - } // get emails of admins const adminsOfWork = await MembershipOrg.find({ diff --git a/backend/src/templates/secretLeakIncident.handlebars b/backend/src/templates/secretLeakIncident.handlebars index e3ef0b569..f38a5d728 100644 --- a/backend/src/templates/secretLeakIncident.handlebars +++ b/backend/src/templates/secretLeakIncident.handlebars @@ -11,9 +11,14 @@

Infisical has uncovered {{numberOfSecrets}} secret(s) from your recent push

View leaked secrets

One or more secret leaks have been detected in a recent commit pushed by {{pusher_name}} ({{pusher_email}}). If - the secrets are test secrets, please mark them as false positives in the Infisical dashboard. - Otherwise, please rotate the secrets immediately.

+ these are test secrets, please add `infisical-scan:ignore` at the end of the line containing the secret as comment + in the given programming. This will prevent future notifications from being sent out for the given secret(s).

+ +

If these are production secrets, please rotate them immediately.

+ +

Once you have taken action, be sure to update the status of the risk in yourInfisical + dashboard.

\ No newline at end of file diff --git a/frontend/src/pages/api/secret-scanning/getRisksByOrganization.ts b/frontend/src/pages/api/secret-scanning/getRisksByOrganization.ts index 3c357e7c6..822086b21 100644 --- a/frontend/src/pages/api/secret-scanning/getRisksByOrganization.ts +++ b/frontend/src/pages/api/secret-scanning/getRisksByOrganization.ts @@ -1,7 +1,7 @@ import SecurityClient from "@app/components/utilities/SecurityClient"; export type GitRisks = { - id: string; + _id: string; description: string; startLine: string; endLine: string; @@ -20,6 +20,7 @@ export type GitRisks = { tags: string[]; ruleID: string; fingerprint: string; + status: string; isFalsePositive: boolean; // New field for marking risks as false positives isResolved: boolean; // New field for marking risks as resolved diff --git a/frontend/src/views/SecretScanning/components/RiskStatusSelection.tsx b/frontend/src/views/SecretScanning/components/RiskStatusSelection.tsx new file mode 100644 index 000000000..fd1252df6 --- /dev/null +++ b/frontend/src/views/SecretScanning/components/RiskStatusSelection.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; + +import updateRiskStatus, { RiskStatus } from "@app/pages/api/secret-scanning/updateRiskStatus"; + +export const RiskStatusSelection = ({riskId, currentSelection}: {riskId: any, currentSelection: any }) => { + const [selectedRiskStatus, setSelectedRiskStatus] = useState(currentSelection); + useEffect(()=>{ + if (currentSelection !== selectedRiskStatus){ + const updateSelection = async () =>{ + await updateRiskStatus(String(localStorage.getItem("orgData.id")), riskId, selectedRiskStatus) + } + updateSelection() + } + },[selectedRiskStatus]) + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/src/views/SecretScanning/components/SecretScanningLogsTable.tsx b/frontend/src/views/SecretScanning/components/SecretScanningLogsTable.tsx index fee14b963..b3b0cf03f 100644 --- a/frontend/src/views/SecretScanning/components/SecretScanningLogsTable.tsx +++ b/frontend/src/views/SecretScanning/components/SecretScanningLogsTable.tsx @@ -11,17 +11,14 @@ import { Th, THead, Tr} from "@app/components/v2"; +import timeSince from "@app/ee/utilities/timeSince"; import getRisksByOrganization, { GitRisks } from "@app/pages/api/secret-scanning/getRisksByOrganization"; -import { RiskStatus } from "@app/pages/api/secret-scanning/updateRiskStatus"; + +import { RiskStatusSelection } from "./RiskStatusSelection"; export const SecretScanningLogsTable = () => { const [isLoading, setIsLoading] = useState(false); const [gitRisks, setGitRisks] = useState([]); - const [selectedRiskStatus, setSelectedRiskStatus] = useState(""); - - const handleSelectRiskStatusUpdate = (event: any) => { - setSelectedRiskStatus(event.target.value); - }; useEffect(() => { const fetchRisks = async () => { @@ -53,7 +50,7 @@ export const SecretScanningLogsTable = () => { {!isLoading && gitRisks && gitRisks?.map((risk) => { return ( - {risk.createdAt} + {timeSince(new Date(risk.createdAt))} {risk.ruleID} { {risk.isResolved ? "Resolved" : "Needs Attention"} - + );