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/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(), { 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/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/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/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/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 98% rename from components/scans/launch-workflow/launch-scan-workflow.tsx rename to components/scans/launch-workflow/launch-scan-workflow-form.tsx index 99e27bb90c..a19acfea42 100644 --- a/components/scans/launch-workflow/launch-scan-workflow.tsx +++ b/components/scans/launch-workflow/launch-scan-workflow-form.tsx @@ -39,11 +39,12 @@ export const LaunchScanWorkflow = ({ const isLoading = form.formState.isSubmitting; const onSubmitClient = async (values: z.infer) => { + const formValues = { ...values }; + 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/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 3e2d940e8e..0d8bfb4360 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,30 +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 ; - }, - }, - { - accessorKey: "trigger", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const { - attributes: { trigger }, - } = getScanData(row); - return

{trigger}

; - }, - }, + return ; + }, + }, { accessorKey: "status", header: ({ column }) => ( @@ -51,7 +37,32 @@ export const ColumnGetScans: ColumnDef[] = [ const { attributes: { state }, } = getScanData(row); - return ; + 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}

; }, }, { @@ -70,29 +81,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 }) => { @@ -103,23 +99,38 @@ 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}

; + return

{trigger}

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

{unique_resource_count}

; + if (name.length === 0) { + return -; + } + return {name}; }, }, { 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" }; } }