From d0d8de9028fee82610f71c2b924b17244e520aaa Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Fri, 8 Nov 2024 11:37:55 +0100 Subject: [PATCH 1/5] chore: add a default name for scans if it's empty by the user --- components/scans/launch-workflow/index.ts | 2 +- ...flow.tsx => launch-scan-workflow-form.tsx} | 15 +++++- .../scans/table/scans/column-get-scans.tsx | 53 ++++++++++--------- 3 files changed, 41 insertions(+), 29 deletions(-) rename components/scans/launch-workflow/{launch-scan-workflow.tsx => launch-scan-workflow-form.tsx} (91%) diff --git a/components/scans/launch-workflow/index.ts b/components/scans/launch-workflow/index.ts index 4ccdef368b..4f8a794d33 100644 --- a/components/scans/launch-workflow/index.ts +++ b/components/scans/launch-workflow/index.ts @@ -1,2 +1,2 @@ -export * from "./launch-scan-workflow"; +export * from "./launch-scan-workflow-form"; export * from "./select-scan-provider"; diff --git a/components/scans/launch-workflow/launch-scan-workflow.tsx b/components/scans/launch-workflow/launch-scan-workflow-form.tsx similarity index 91% rename from components/scans/launch-workflow/launch-scan-workflow.tsx rename to components/scans/launch-workflow/launch-scan-workflow-form.tsx index 99e27bb90c..b1149fceac 100644 --- a/components/scans/launch-workflow/launch-scan-workflow.tsx +++ b/components/scans/launch-workflow/launch-scan-workflow-form.tsx @@ -39,11 +39,22 @@ export const LaunchScanWorkflow = ({ const isLoading = form.formState.isSubmitting; const onSubmitClient = async (values: z.infer) => { + const formValues = { ...values }; + + if (!formValues.scanName?.trim()) { + const date = new Date(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); + const day = date.getDate().toString().padStart(2, "0"); + const year = date.getFullYear(); + const hours = date.getHours().toString().padStart(2, "0"); + const minutes = date.getMinutes().toString().padStart(2, "0"); + formValues.scanName = `scan:${month}/${day}/${year} ${hours}:${minutes}`; + } + const formData = new FormData(); - console.log(values); // Loop through form values and add to formData - Object.entries(values).forEach( + Object.entries(formValues).forEach( ([key, value]) => value !== undefined && formData.append( diff --git a/components/scans/table/scans/column-get-scans.tsx b/components/scans/table/scans/column-get-scans.tsx index 3e2d940e8e..604d67ef8b 100644 --- a/components/scans/table/scans/column-get-scans.tsx +++ b/components/scans/table/scans/column-get-scans.tsx @@ -29,18 +29,6 @@ export const ColumnGetScans: ColumnDef[] = [ return ; }, }, - { - accessorKey: "trigger", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const { - attributes: { trigger }, - } = getScanData(row); - return

{trigger}

; - }, - }, { accessorKey: "status", @@ -54,6 +42,27 @@ export const ColumnGetScans: ColumnDef[] = [ return ; }, }, + + { + accessorKey: "scanner_args", + header: "Scanner Args", + cell: ({ row }) => { + const { + attributes: { scanner_args }, + } = getScanData(row); + return

{scanner_args?.only_logs}

; + }, + }, + { + accessorKey: "resources", + header: "Resources", + cell: ({ row }) => { + const { + attributes: { unique_resource_count }, + } = getScanData(row); + return

{unique_resource_count}

; + }, + }, { accessorKey: "scheduled_at", header: ({ column }) => ( @@ -103,23 +112,15 @@ export const ColumnGetScans: ColumnDef[] = [ }, }, { - accessorKey: "scanner_args", - header: "Scanner Args", + accessorKey: "trigger", + header: ({ column }) => ( + + ), cell: ({ row }) => { const { - attributes: { scanner_args }, + attributes: { trigger }, } = getScanData(row); - return

{scanner_args?.only_logs}

; - }, - }, - { - accessorKey: "resources", - header: "Resources", - cell: ({ row }) => { - const { - attributes: { unique_resource_count }, - } = getScanData(row); - return

{unique_resource_count}

; + return

{trigger}

; }, }, { From 60c2c409b0d394b44f44db23351cdaf3592dc894 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Mon, 11 Nov 2024 13:02:03 +0100 Subject: [PATCH 2/5] fix: apply prettier to fix an error coming from main branch --- actions/auth/auth.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/actions/auth/auth.ts b/actions/auth/auth.ts index 3b7195688a..e0de4422b6 100644 --- a/actions/auth/auth.ts +++ b/actions/auth/auth.ts @@ -67,7 +67,6 @@ export const createNewUser = async ( }, }, }; - try { const response = await fetch(url.toString(), { From 2378b01ea978b4ec353fdd375f86dc09a9bf323b Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Mon, 11 Nov 2024 13:39:37 +0100 Subject: [PATCH 3/5] chore: apply tweaks to scan table --- actions/scans/scans.ts | 3 - app/(prowler)/findings/page.tsx | 23 ++++--- .../launch-scan-workflow-form.tsx | 10 --- components/scans/table/scan-detail.tsx | 8 ++- .../scans/table/scans/column-get-scans.tsx | 63 +++++++++++-------- components/ui/table/status-badge.tsx | 25 +++++++- lib/helper.ts | 1 - 7 files changed, 78 insertions(+), 55 deletions(-) diff --git a/actions/scans/scans.ts b/actions/scans/scans.ts index be481fc2ea..866918cf86 100644 --- a/actions/scans/scans.ts +++ b/actions/scans/scans.ts @@ -94,9 +94,6 @@ export const scanOnDemand = async (formData: FormData) => { type: "Scan", attributes: { name: scanName, - scanner_args: { - checks_to_execute: ["accessanalyzer_enabled"], - }, }, relationships: { provider: { diff --git a/app/(prowler)/findings/page.tsx b/app/(prowler)/findings/page.tsx index 1c277cad0c..4a0a80b8dd 100644 --- a/app/(prowler)/findings/page.tsx +++ b/app/(prowler)/findings/page.tsx @@ -58,17 +58,20 @@ const SSRDataTable = async ({ const providerDict = createDict("Provider", findingsData); // Expand each finding with its corresponding resource, scan, and provider - const expandedFindings = findingsData.data.map((finding: FindingProps) => { - const scan = scanDict[finding.relationships?.scan?.data?.id]; - const resource = - resourceDict[finding.relationships?.resources?.data?.[0]?.id]; - const provider = providerDict[resource?.relationships?.provider?.data?.id]; + const expandedFindings = findingsData?.data + ? findingsData.data.map((finding: FindingProps) => { + const scan = scanDict[finding.relationships?.scan?.data?.id]; + const resource = + resourceDict[finding.relationships?.resources?.data?.[0]?.id]; + const provider = + providerDict[resource?.relationships?.provider?.data?.id]; - return { - ...finding, - relationships: { scan, resource, provider }, - }; - }); + return { + ...finding, + relationships: { scan, resource, provider }, + }; + }) + : []; // Create the new object while maintaining the original structure const expandedResponse = { diff --git a/components/scans/launch-workflow/launch-scan-workflow-form.tsx b/components/scans/launch-workflow/launch-scan-workflow-form.tsx index b1149fceac..a19acfea42 100644 --- a/components/scans/launch-workflow/launch-scan-workflow-form.tsx +++ b/components/scans/launch-workflow/launch-scan-workflow-form.tsx @@ -41,16 +41,6 @@ export const LaunchScanWorkflow = ({ const onSubmitClient = async (values: z.infer) => { const formValues = { ...values }; - if (!formValues.scanName?.trim()) { - const date = new Date(); - const month = (date.getMonth() + 1).toString().padStart(2, "0"); - const day = date.getDate().toString().padStart(2, "0"); - const year = date.getFullYear(); - const hours = date.getHours().toString().padStart(2, "0"); - const minutes = date.getMinutes().toString().padStart(2, "0"); - formValues.scanName = `scan:${month}/${day}/${year} ${hours}:${minutes}`; - } - const formData = new FormData(); // Loop through form values and add to formData diff --git a/components/scans/table/scan-detail.tsx b/components/scans/table/scan-detail.tsx index c95e28fcfc..b0a85f73f3 100644 --- a/components/scans/table/scan-detail.tsx +++ b/components/scans/table/scan-detail.tsx @@ -23,7 +23,11 @@ export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => {

Scan Details

- +
@@ -156,7 +160,7 @@ export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => { diff --git a/components/scans/table/scans/column-get-scans.tsx b/components/scans/table/scans/column-get-scans.tsx index 604d67ef8b..fccc203ae6 100644 --- a/components/scans/table/scans/column-get-scans.tsx +++ b/components/scans/table/scans/column-get-scans.tsx @@ -4,7 +4,7 @@ import { ColumnDef } from "@tanstack/react-table"; import { useSearchParams } from "next/navigation"; import { InfoIcon } from "@/components/icons"; -import { DateWithTime, EntityInfoShort } from "@/components/ui/entities"; +import { DateWithTime, SnippetId } from "@/components/ui/entities"; import { TriggerSheet } from "@/components/ui/sheet"; import { DataTableColumnHeader, StatusBadge } from "@/components/ui/table"; import { ScanProps } from "@/types"; @@ -18,18 +18,16 @@ const getScanData = (row: { original: ScanProps }) => { export const ColumnGetScans: ColumnDef[] = [ { - accessorKey: "name", - header: ({ column }) => ( - - ), + accessorKey: "started_at", + header: () =>

Started at

, cell: ({ row }) => { const { - attributes: { name }, + attributes: { started_at }, } = getScanData(row); - return ; + + return ; }, }, - { accessorKey: "status", header: ({ column }) => ( @@ -39,7 +37,12 @@ export const ColumnGetScans: ColumnDef[] = [ const { attributes: { state }, } = getScanData(row); - return ; + return ( + + ); }, }, @@ -79,29 +82,14 @@ export const ColumnGetScans: ColumnDef[] = [ return ; }, }, - { - accessorKey: "started_at", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const { - attributes: { started_at }, - } = getScanData(row); - return ; - }, - }, + { accessorKey: "completed_at", header: ({ column }) => ( ), cell: ({ row }) => { @@ -123,6 +111,29 @@ export const ColumnGetScans: ColumnDef[] = [ return

{trigger}

; }, }, + + { + accessorKey: "id", + header: () => ID, + cell: ({ row }) => { + return ; + }, + }, + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const { + attributes: { name }, + } = getScanData(row); + if (name.length === 0) { + return -; + } + return {name}; + }, + }, { id: "moreInfo", header: "Details", diff --git a/components/ui/table/status-badge.tsx b/components/ui/table/status-badge.tsx index 932d4105d6..3639e3a8a1 100644 --- a/components/ui/table/status-badge.tsx +++ b/components/ui/table/status-badge.tsx @@ -1,4 +1,4 @@ -import { Chip } from "@nextui-org/react"; +import { Chip, CircularProgress } from "@nextui-org/react"; import React from "react"; export type Status = @@ -24,22 +24,41 @@ const statusColorMap: Record< export const StatusBadge = ({ status, size = "sm", + loadingProgress, ...props }: { status: Status; size?: "sm" | "md" | "lg"; + loadingProgress?: number; }) => { const color = statusColorMap[status as keyof typeof statusColorMap]; return ( - {status} + {status === "executing" ? ( +
+ + executing +
+ ) : ( + status + )}
); }; diff --git a/lib/helper.ts b/lib/helper.ts index aed48d9478..5b6d2ec8f2 100644 --- a/lib/helper.ts +++ b/lib/helper.ts @@ -30,7 +30,6 @@ export async function checkTaskStatus( await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); break; default: - console.warn(`Unexpected task state: ${state}`); return { completed: false, error: "Unexpected task state" }; } } From db36cdf37999d3bfa21005f04b0cf27773252267 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Wed, 13 Nov 2024 08:21:13 +0100 Subject: [PATCH 4/5] fix: fix the build, and run prettier --- actions/services/services.ts | 6 +- components/findings/table/column-findings.tsx | 7 +- .../findings/table/data-table-row-details.tsx | 3 - components/findings/table/finding-detail.tsx | 196 ++++++++++-------- components/findings/table/index.ts | 2 +- .../scans/table/scans/column-get-scans.tsx | 21 +- package.json | 2 +- 7 files changed, 130 insertions(+), 107 deletions(-) diff --git a/actions/services/services.ts b/actions/services/services.ts index dab8b80bb9..c4ab342f01 100644 --- a/actions/services/services.ts +++ b/actions/services/services.ts @@ -2,10 +2,10 @@ import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; +import { parse } from "path"; import { auth } from "@/auth.config"; import { getErrorMessage, parseStringify } from "@/lib"; -import { parse } from "path"; export const getServices = async ({}) => { const session = await auth(); @@ -63,10 +63,8 @@ export const getServices = async ({}) => { { id: "trustedadvisor", alias: "AWS Trusted Advisor" }, { id: "vpc", alias: "Amazon VPC" }, { id: "wafv2", alias: "AWS WAF" }, - { id: "wellarchitected", alias: "AWS Well-Architected Tool" } + { id: "wellarchitected", alias: "AWS Well-Architected Tool" }, ]; - - const parsedData = []; diff --git a/components/findings/table/column-findings.tsx b/components/findings/table/column-findings.tsx index 1d3d2a28d5..4d0d7dd3ab 100644 --- a/components/findings/table/column-findings.tsx +++ b/components/findings/table/column-findings.tsx @@ -2,12 +2,13 @@ import { ColumnDef } from "@tanstack/react-table"; +import { DataTableRowDetails } from "@/components/findings/table"; +import { PlusIcon } from "@/components/icons"; +import { TriggerSheet } from "@/components/ui/sheet"; import { SeverityBadge, Status, StatusBadge } from "@/components/ui/table"; import { FindingProps } from "@/types"; -import { TriggerSheet } from "@/components/ui/sheet"; + import { DataTableRowActions } from "./data-table-row-actions"; -import { PlusIcon } from "@/components/icons"; -import { DataTableRowDetails } from "@/components/findings/table"; const statusMap: Record<"PASS" | "FAIL" | "MANUAL" | "MUTED", Status> = { PASS: "completed", diff --git a/components/findings/table/data-table-row-details.tsx b/components/findings/table/data-table-row-details.tsx index b843847e7a..b93c61ec85 100644 --- a/components/findings/table/data-table-row-details.tsx +++ b/components/findings/table/data-table-row-details.tsx @@ -1,11 +1,8 @@ "use client"; -import { useEffect, useState } from "react"; - import { FindingDetail } from "@/components/findings/table"; import { FindingProps } from "@/types"; export const DataTableRowDetails = ({ finding }: { finding: FindingProps }) => { - console.log(finding); return ; }; diff --git a/components/findings/table/finding-detail.tsx b/components/findings/table/finding-detail.tsx index 2aa99a2719..4d2dfac867 100644 --- a/components/findings/table/finding-detail.tsx +++ b/components/findings/table/finding-detail.tsx @@ -1,97 +1,125 @@ "use client"; -import { Card, CardBody, CardHeader, Divider } from "@nextui-org/react"; +import { + Table, + TableBody, + TableCell, + TableColumn, + TableHeader, + TableRow, +} from "@nextui-org/react"; -import { DateWithTime, SnippetId } from "@/components/ui/entities"; -import { StatusBadge } from "@/components/ui/table/status-badge"; import { FindingProps } from "@/types"; -import {Table, TableHeader, TableColumn, TableBody, TableRow, TableCell} from "@nextui-org/react"; -export const FindingDetail = ({ findingDetails }: { findingDetails: FindingProps }) => { +export const FindingDetail = ({ + findingDetails, +}: { + findingDetails: FindingProps; +}) => { const finding = findingDetails; - console.log(finding) return (
- - - Name - Value - - - - Resource ID - {finding.relationships.resource.id} - - - Resource ARN - {finding.relationships.resource.attributes.uid} - - - Check ID - {finding.attributes.check_id} - - - Types - {finding.attributes.check_metadata.checktype} - - - Scan time - {finding.attributes.inserted_at} - - - Prowler Finding ID - {finding.relationships.resource.attributes.uid} - - - Severity - {finding.id} - - - Status - {finding.attributes.status} - - - Region - {finding.relationships.resource.attributes.region} - - - Service - {finding.relationships.resource.attributes.service} - - - Account - {finding.relationships.provider.attributes.uid} - - - Details - {finding.attributes.status_extended} - - - Risk - {finding.attributes.check_metadata.risk} - - - Recommendation - {finding.attributes.check_metadata.remediation.recommendation.text} - - - CLI - {finding.attributes.check_metadata.remediation.code.cli} - - - Other - {finding.attributes.check_metadata.remediation.code.other} - - - Terraform - {finding.attributes.check_metadata.remediation.code.terraform} - - -
- -
+ + Name + Value + + + + Resource ID + {finding.relationships.resource.id} + + + Resource ARN + + {finding.relationships.resource.attributes.uid} + + + + Check ID + {finding.attributes.check_id} + + + Types + + {finding.attributes.check_metadata.checktype} + + + + Scan time + {finding.attributes.inserted_at} + + + Prowler Finding ID + + {finding.relationships.resource.attributes.uid} + + + + Severity + {finding.id} + + + Status + {finding.attributes.status} + + + Region + + {finding.relationships.resource.attributes.region} + + + + Service + + {finding.relationships.resource.attributes.service} + + + + Account + + {finding.relationships.provider.attributes.uid} + + + + Details + {finding.attributes.status_extended} + + + Risk + {finding.attributes.check_metadata.risk} + + + Recommendation + + { + finding.attributes.check_metadata.remediation.recommendation + .text + } + + + + CLI + + {finding.attributes.check_metadata.remediation.code.cli} + + + + Other + + {finding.attributes.check_metadata.remediation.code.other} + + + + Terraform + + {finding.attributes.check_metadata.remediation.code.terraform} + + + + +
); }; diff --git a/components/findings/table/index.ts b/components/findings/table/index.ts index 3aad78e3f4..fe19b5dd6e 100644 --- a/components/findings/table/index.ts +++ b/components/findings/table/index.ts @@ -1,5 +1,5 @@ export * from "./column-findings"; export * from "./data-table-row-actions"; export * from "./data-table-row-details"; -export * from "./skeleton-table-findings"; export * from "./finding-detail"; +export * from "./skeleton-table-findings"; diff --git a/components/scans/table/scans/column-get-scans.tsx b/components/scans/table/scans/column-get-scans.tsx index fccc203ae6..0d8bfb4360 100644 --- a/components/scans/table/scans/column-get-scans.tsx +++ b/components/scans/table/scans/column-get-scans.tsx @@ -45,17 +45,16 @@ export const ColumnGetScans: ColumnDef[] = [ ); }, }, - - { - accessorKey: "scanner_args", - header: "Scanner Args", - cell: ({ row }) => { - const { - attributes: { scanner_args }, - } = getScanData(row); - return

{scanner_args?.only_logs}

; - }, - }, + // { + // accessorKey: "scanner_args", + // header: "Scanner Args", + // cell: ({ row }) => { + // const { + // attributes: { scanner_args }, + // } = getScanData(row); + // return

{scanner_args?.only_logs}

; + // }, + // }, { accessorKey: "resources", header: "Resources", diff --git a/package.json b/package.json index 2d9f0f0ba4..765c868597 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "build": "next build", "start": "next start", "typecheck": "tsc", - "healthcheck": "npm run typecheck && npm run lint:check", + "healthcheck": "npm run typecheck && npm run lint:check && npm run build", "lint:check": "./node_modules/.bin/eslint ./app", "lint:fix": "eslint . --ext .ts,.tsx -c .eslintrc.cjs --fix", "format:check": "./node_modules/.bin/prettier --check ./app", From 8fb6f5b11d222501fb205298f1f2088223894c49 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Wed, 13 Nov 2024 08:22:58 +0100 Subject: [PATCH 5/5] chore: add GitHub action to run the build --- .github/workflows/checks.yml | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9dfa42e70c..e58e18c793 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -25,3 +25,5 @@ jobs: run: npm install - name: Run Healthcheck run: npm run healthcheck + - name: Build the application + run: npm run build diff --git a/package.json b/package.json index 765c868597..2d9f0f0ba4 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "build": "next build", "start": "next start", "typecheck": "tsc", - "healthcheck": "npm run typecheck && npm run lint:check && npm run build", + "healthcheck": "npm run typecheck && npm run lint:check", "lint:check": "./node_modules/.bin/eslint ./app", "lint:fix": "eslint . --ext .ts,.tsx -c .eslintrc.cjs --fix", "format:check": "./node_modules/.bin/prettier --check ./app",