From c119cece896260e7c2759c7c3015a2c7deb0d1cb Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Tue, 10 Jun 2025 10:43:27 +0200 Subject: [PATCH] feat: ThreatScore compliance detailed view (#7979) --- ui/CHANGELOG.md | 3 +- .../client-accordion-content.tsx | 19 +- ui/components/compliance/compliance-card.tsx | 1 + .../aws-well-architected-details.tsx | 126 +++++---- .../compliance-custom-details/cis-details.tsx | 150 +++++------ .../compliance-custom-details/ens-details.tsx | 75 +++--- .../compliance-custom-details/iso-details.tsx | 34 ++- .../kisa-details.tsx | 96 ++----- .../shared-components.tsx | 166 ++++++++++++ .../threat-details.tsx | 68 +++++ ui/lib/compliance/commons.ts | 12 + ui/lib/compliance/threat.tsx | 246 ++++++++++++++++++ ui/types/compliance.ts | 11 + 13 files changed, 734 insertions(+), 273 deletions(-) create mode 100644 ui/components/compliance/compliance-custom-details/shared-components.tsx create mode 100644 ui/components/compliance/compliance-custom-details/threat-details.tsx create mode 100644 ui/lib/compliance/threat.tsx diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 15fd774391..6a384b133c 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -20,7 +20,8 @@ All notable changes to the **Prowler UI** are documented in this file. - Add compliance detail view: CIS [(#7913)](https://github.com/prowler-cloud/prowler/pull/7913) - Add compliance detail view: AWS Well-Architected Framework [(#7925)](https://github.com/prowler-cloud/prowler/pull/7925) - Add compliance detail view: KISA [(#7965)](https://github.com/prowler-cloud/prowler/pull/7965) -- Improve `Scan ID` filter by adding more context and enhancing the UI/UX. [(#7949)](https://github.com/prowler-cloud/prowler/pull/7949) +- Add compliance detail view: ProwlerThreatScore [(#7966)](https://github.com/prowler-cloud/prowler/pull/7966) +- Improve `Scan ID` filter by adding more context and enhancing the UI/UX. [(#7979)](https://github.com/prowler-cloud/prowler/pull/7979) ### 🔄 Changed diff --git a/ui/components/compliance/compliance-accordion/client-accordion-content.tsx b/ui/components/compliance/compliance-accordion/client-accordion-content.tsx index bbcba71f26..5769e13259 100644 --- a/ui/components/compliance/compliance-accordion/client-accordion-content.tsx +++ b/ui/components/compliance/compliance-accordion/client-accordion-content.tsx @@ -125,8 +125,13 @@ export const ClientAccordionContent = ({ const checks = requirement.check_ids || []; const checksList = ( -
- {checks.join(", ")} +
+
+
+ + {checks.join(", ")} + +
); @@ -150,7 +155,9 @@ export const ClientAccordionContent = ({ if (findings?.data?.length && findings.data.length > 0) { return ( -
+ <> +

Findings

+ -
+ ); } @@ -176,12 +183,12 @@ export const ClientAccordionContent = ({ {renderDetails()} {checks.length > 0 && ( -
+
)} diff --git a/ui/components/compliance/compliance-card.tsx b/ui/components/compliance/compliance-card.tsx index 0445e8690a..1c8b772475 100644 --- a/ui/components/compliance/compliance-card.tsx +++ b/ui/components/compliance/compliance-card.tsx @@ -76,6 +76,7 @@ export const ComplianceCard: React.FC = ({ id.includes("iso") || id.includes("cis_") || id.includes("kisa") || + id.includes("threat") || id.includes("pillar"); const navigateToDetail = () => { diff --git a/ui/components/compliance/compliance-custom-details/aws-well-architected-details.tsx b/ui/components/compliance/compliance-custom-details/aws-well-architected-details.tsx index 35cc5c7114..b0069433ee 100644 --- a/ui/components/compliance/compliance-custom-details/aws-well-architected-details.tsx +++ b/ui/components/compliance/compliance-custom-details/aws-well-architected-details.tsx @@ -1,91 +1,87 @@ -import Link from "next/link"; - import { SeverityBadge } from "@/components/ui/table"; import { Requirement } from "@/types/compliance"; +import { + ComplianceBadge, + ComplianceBadgeContainer, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, + ComplianceLink, +} from "./shared-components"; + export const AWSWellArchitectedCustomDetails = ({ requirement, }: { requirement: Requirement; }) => { return ( -
+ {requirement.description && ( -
-

- Description -

-

{requirement.description}

-
+ + {requirement.description} + )} {requirement.well_architected_name && ( -
-

- Best Practice -

-

{requirement.well_architected_name}

-
+ + + {requirement.well_architected_name as string} + + )} - {requirement.well_architected_question_id && ( -
-

- Question ID -

-

{requirement.well_architected_question_id}

-
- )} + + {requirement.level_of_risk && ( +
+ + Risk Level: + + +
+ )} - {requirement.well_architected_practice_id && ( -
-

- Practice ID -

-

{requirement.well_architected_practice_id}

-
- )} - - {requirement.level_of_risk && ( -
-

- Level of Risk -

- -
- )} + )} - {requirement.assessment_method && ( -
-

- Assessment Method -

-

{requirement.assessment_method}

-
- )} + {requirement.well_architected_practice_id && ( + + )} + + {requirement.assessment_method && ( + + )} +
{requirement.implementation_guidance_url && ( -
-

- Implementation Guidance -

- + {requirement.implementation_guidance_url} - -
+ + )} -
+ ); }; diff --git a/ui/components/compliance/compliance-custom-details/cis-details.tsx b/ui/components/compliance/compliance-custom-details/cis-details.tsx index ebb04e48d8..6977c7d101 100644 --- a/ui/components/compliance/compliance-custom-details/cis-details.tsx +++ b/ui/components/compliance/compliance-custom-details/cis-details.tsx @@ -1,8 +1,16 @@ -import Link from "next/link"; import ReactMarkdown from "react-markdown"; import { Requirement } from "@/types/compliance"; +import { + ComplianceBadge, + ComplianceBadgeContainer, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, + ComplianceLink, +} from "./shared-components"; + interface CISDetailsProps { requirement: Requirement; } @@ -21,131 +29,105 @@ export const CISCustomDetails = ({ requirement }: CISDetailsProps) => { }; return ( -
- {requirement.profile && ( -
-

- Profile Level -

-

{requirement.profile}

-
+ + {requirement.description && ( + + {requirement.description} + )} + + {requirement.profile && ( + + )} + + {requirement.assessment_status && ( + + )} + + {requirement.subsection && ( -
-

- SubSection -

-

{requirement.subsection}

-
- )} - - {requirement.assessment_status && ( -
-

- Assessment Status -

-

{requirement.assessment_status}

-
- )} - - {requirement.description && ( -
-

- Description -

-

{requirement.description}

-
+ + + {requirement.subsection as string} + + )} {requirement.rationale_statement && ( -
-

- Rationale Statement -

-

{requirement.rationale_statement}

-
+ + + {requirement.rationale_statement as string} + + )} {requirement.impact_statement && ( -
-

- Impact Statement -

-

{requirement.impact_statement}

-
+ + + {requirement.impact_statement as string} + + )} {requirement.remediation_procedure && typeof requirement.remediation_procedure === "string" && ( -
-

- Remediation Procedure -

+ {/* Prettier -> "plugins": ["prettier-plugin-tailwindcss"] is not ready yet to "prose": */} {/* eslint-disable-next-line */}
{requirement.remediation_procedure}
-
+ )} {requirement.audit_procedure && typeof requirement.audit_procedure === "string" && ( -
-

- Audit Procedure -

+ {/* eslint-disable-next-line */}
{requirement.audit_procedure}
-
+ )} {requirement.additional_information && ( -
-

- Additional Information -

-

- {requirement.additional_information} -

-
+ + + {requirement.additional_information as string} + + )} {requirement.default_value && ( -
-

- Default Value -

-

{requirement.default_value}

-
+ + + {requirement.default_value as string} + + )} {requirement.references && ( -
-

- References -

-
+ +
{processReferences(requirement.references).map( (url: string, index: number) => (
- - {url} - + {url}
), )}
-
+ )} -
+
); }; diff --git a/ui/components/compliance/compliance-custom-details/ens-details.tsx b/ui/components/compliance/compliance-custom-details/ens-details.tsx index 2c133f7e11..9e947cea14 100644 --- a/ui/components/compliance/compliance-custom-details/ens-details.tsx +++ b/ui/components/compliance/compliance-custom-details/ens-details.tsx @@ -1,47 +1,50 @@ import { translateType } from "@/lib/compliance/ens"; import { Requirement } from "@/types/compliance"; +import { + ComplianceBadge, + ComplianceBadgeContainer, + ComplianceChipContainer, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, +} from "./shared-components"; + export const ENSCustomDetails = ({ requirement, }: { requirement: Requirement; }) => { return ( -
-
- {requirement.description} -
-
-
- Type: - - {translateType(requirement.type as string)} - -
-
- Level: - {requirement.nivel} -
- {requirement.dimensiones && - Array.isArray(requirement.dimensiones) && - requirement.dimensiones.length > 0 && ( -
- Dimensions: -
- {requirement.dimensiones.map( - (dimension: string, index: number) => ( - - {dimension} - - ), - )} -
-
- )} -
-
+ + {requirement.description && ( + + {requirement.description} + + )} + + + {requirement.type && ( + + )} + + {requirement.nivel && ( + + )} + + + + ); }; diff --git a/ui/components/compliance/compliance-custom-details/iso-details.tsx b/ui/components/compliance/compliance-custom-details/iso-details.tsx index 14699abe9a..425a6aa49f 100644 --- a/ui/components/compliance/compliance-custom-details/iso-details.tsx +++ b/ui/components/compliance/compliance-custom-details/iso-details.tsx @@ -1,23 +1,31 @@ import { Requirement } from "@/types/compliance"; +import { + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, +} from "./shared-components"; + export const ISOCustomDetails = ({ requirement, }: { requirement: Requirement; }) => { return ( -
-
- {requirement.description} -
-
- {requirement.objetive_name && ( -
- Objective: - {requirement.objetive_name} -
- )} -
-
+ + {requirement.description && ( + + {requirement.description} + + )} + + {requirement.objetive_name && ( + + + {requirement.objetive_name as string} + + + )} + ); }; diff --git a/ui/components/compliance/compliance-custom-details/kisa-details.tsx b/ui/components/compliance/compliance-custom-details/kisa-details.tsx index 8f0041be7f..c29a39b22d 100644 --- a/ui/components/compliance/compliance-custom-details/kisa-details.tsx +++ b/ui/components/compliance/compliance-custom-details/kisa-details.tsx @@ -1,5 +1,12 @@ import { Requirement } from "@/types/compliance"; +import { + ComplianceBulletList, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, +} from "./shared-components"; + export const KISACustomDetails = ({ requirement, }: { @@ -15,79 +22,32 @@ export const KISACustomDetails = ({ | undefined; return ( -
+ {requirement.description && ( -
-

- Description -

-

{requirement.description}

-
+ + {requirement.description} + )} - {auditChecklist && auditChecklist.length > 0 && ( -
-

- Audit Checklist -

-
- {auditChecklist.map((item: string, index: number) => ( -
- • -

{item}

-
- ))} -
-
- )} + - {relatedRegulations && relatedRegulations.length > 0 && ( -
-

- Related Regulations -

-
- {relatedRegulations.map((regulation: string, index: number) => ( -
- • -

{regulation}

-
- ))} -
-
- )} + - {auditEvidence && auditEvidence.length > 0 && ( -
-

- Audit Evidence -

-
- {auditEvidence.map((evidence: string, index: number) => ( -
- • -

{evidence}

-
- ))} -
-
- )} + - {nonComplianceCases && nonComplianceCases.length > 0 && ( -
-

- Non-Compliance Cases -

-
- {nonComplianceCases.map((caseItem: string, index: number) => ( -
- • -

{caseItem}

-
- ))} -
-
- )} -
+ + ); }; diff --git a/ui/components/compliance/compliance-custom-details/shared-components.tsx b/ui/components/compliance/compliance-custom-details/shared-components.tsx new file mode 100644 index 0000000000..2d1344b19b --- /dev/null +++ b/ui/components/compliance/compliance-custom-details/shared-components.tsx @@ -0,0 +1,166 @@ +import Link from "next/link"; + +import { cn } from "@/lib/utils"; + +export const ComplianceLink = ({ + href, + children, +}: { + href: string; + children: React.ReactNode; +}) => { + return ( + + {children} + + ); +}; + +export const ComplianceDetailContainer = ({ + children, +}: { + children: React.ReactNode; +}) => { + return
{children}
; +}; + +export const ComplianceDetailSection = ({ + title, + children, +}: { + title: string; + children: React.ReactNode; +}) => { + return ( +
+

+ {title} +

+ {children} +
+ ); +}; + +export const ComplianceDetailText = ({ + children, + className = "", +}: { + children: React.ReactNode; + className?: string; +}) => { + return

{children}

; +}; + +export const ComplianceBadgeContainer = ({ + children, +}: { + children: React.ReactNode; +}) => { + return
{children}
; +}; + +type BadgeColor = + | "red" // Risk/Level/Severity + | "blue" // Assessment/Method + | "orange" // Type/Category + | "green" // Weight/Score (positive) + | "purple" // Profile + | "indigo" // IDs/References + | "gray"; // Additional Info/Neutral + +export const ComplianceBadge = ({ + label, + value, + color, + conditional = false, +}: { + label: string; + value: string | number; + color: BadgeColor; + conditional?: boolean; +}) => { + const actualColor = conditional && Number(value) === 0 ? "gray" : color; + + const colorClasses = { + red: "bg-red-50 text-red-700 ring-red-600/10 dark:bg-red-400/10 dark:text-red-400 dark:ring-red-400/20", + blue: "bg-blue-50 text-blue-700 ring-blue-600/10 dark:bg-blue-400/10 dark:text-blue-400 dark:ring-blue-400/20", + orange: + "bg-orange-50 text-orange-700 ring-orange-600/10 dark:bg-orange-400/10 dark:text-orange-400 dark:ring-orange-400/20", + green: + "bg-green-50 text-green-700 ring-green-600/10 dark:bg-green-400/10 dark:text-green-400 dark:ring-green-400/20", + purple: + "bg-purple-50 text-purple-700 ring-purple-600/10 dark:bg-purple-400/10 dark:text-purple-400 dark:ring-purple-400/20", + indigo: + "bg-indigo-50 text-indigo-700 ring-indigo-600/10 dark:bg-indigo-400/10 dark:text-indigo-400 dark:ring-indigo-400/20", + gray: "bg-gray-50 text-gray-600 ring-gray-500/10 dark:bg-gray-400/10 dark:text-gray-400 dark:ring-gray-400/20", + }; + + return ( +
+ + {label}: + + + {value} + +
+ ); +}; + +export const ComplianceBulletList = ({ + title, + items, +}: { + title: string; + items: string[]; +}) => { + if (!items || items.length === 0) return null; + + return ( + +
+ {items.map((item: string, index: number) => ( +
+ • + {item} +
+ ))} +
+
+ ); +}; + +export const ComplianceChipContainer = ({ + title, + items, +}: { + title: string; + items: string[]; +}) => { + if (!items || items.length === 0) return null; + + return ( + +
+ {items.map((item: string, index: number) => ( + + {item} + + ))} +
+
+ ); +}; diff --git a/ui/components/compliance/compliance-custom-details/threat-details.tsx b/ui/components/compliance/compliance-custom-details/threat-details.tsx new file mode 100644 index 0000000000..4f2f5e87da --- /dev/null +++ b/ui/components/compliance/compliance-custom-details/threat-details.tsx @@ -0,0 +1,68 @@ +import { Requirement } from "@/types/compliance"; + +import { + ComplianceBadge, + ComplianceBadgeContainer, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, +} from "./shared-components"; + +export const ThreatCustomDetails = ({ + requirement, +}: { + requirement: Requirement; +}) => { + return ( + + {requirement.description && ( + + {requirement.description} + + )} + + {requirement.attributeDescription && ( + + + {requirement.attributeDescription} + + + )} + + + {typeof requirement.levelOfRisk === "number" && ( + + )} + + {typeof requirement.weight === "number" && ( + + )} + + {typeof requirement.score === "number" && ( + + )} + + + {requirement.additionalInformation && ( + + + {requirement.additionalInformation} + + + )} + + ); +}; diff --git a/ui/lib/compliance/commons.ts b/ui/lib/compliance/commons.ts index 49fb6bf932..0ede59f1c4 100644 --- a/ui/lib/compliance/commons.ts +++ b/ui/lib/compliance/commons.ts @@ -5,6 +5,7 @@ import { CISCustomDetails } from "@/components/compliance/compliance-custom-deta import { ENSCustomDetails } from "@/components/compliance/compliance-custom-details/ens-details"; import { ISOCustomDetails } from "@/components/compliance/compliance-custom-details/iso-details"; import { KISACustomDetails } from "@/components/compliance/compliance-custom-details/kisa-details"; +import { ThreatCustomDetails } from "@/components/compliance/compliance-custom-details/threat-details"; import { AccordionItemProps } from "@/components/ui/accordion/Accordion"; import { AttributesData, @@ -35,6 +36,10 @@ import { mapComplianceData as mapKISAComplianceData, toAccordionItems as toKISAAccordionItems, } from "./kisa"; +import { + mapComplianceData as mapThetaComplianceData, + toAccordionItems as toThetaAccordionItems, +} from "./threat"; export interface ComplianceMapper { mapComplianceData: ( @@ -131,6 +136,13 @@ const complianceMappers: Record = { getDetailsComponent: (requirement: Requirement) => React.createElement(KISACustomDetails, { requirement }), }, + ProwlerThreatScore: { + mapComplianceData: mapThetaComplianceData, + toAccordionItems: toThetaAccordionItems, + getTopFailedSections, + getDetailsComponent: (requirement: Requirement) => + React.createElement(ThreatCustomDetails, { requirement }), + }, }; // Default mapper (fallback to ENS for backward compatibility) diff --git a/ui/lib/compliance/threat.tsx b/ui/lib/compliance/threat.tsx new file mode 100644 index 0000000000..df59f11685 --- /dev/null +++ b/ui/lib/compliance/threat.tsx @@ -0,0 +1,246 @@ +import { ClientAccordionContent } from "@/components/compliance/compliance-accordion/client-accordion-content"; +import { ComplianceAccordionRequirementTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-requeriment-title"; +import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; +import { AccordionItemProps } from "@/components/ui/accordion/Accordion"; +import { FindingStatus } from "@/components/ui/table/status-finding-badge"; +import { + AttributesData, + Framework, + Requirement, + RequirementItemData, + RequirementsData, + RequirementStatus, + ThreatAttributesMetadata, +} from "@/types/compliance"; + +export const mapComplianceData = ( + attributesData: AttributesData, + requirementsData: RequirementsData, +): Framework[] => { + const attributes = attributesData?.data || []; + const requirements = requirementsData?.data || []; + + // Create a map for quick lookup of requirements by id + const requirementsMap = new Map(); + requirements.forEach((req: RequirementItemData) => { + requirementsMap.set(req.id, req); + }); + + const frameworks: Framework[] = []; + + // Process attributes and merge with requirements data + for (const attributeItem of attributes) { + const id = attributeItem.id; + const metadataArray = attributeItem.attributes?.attributes + ?.metadata as unknown as ThreatAttributesMetadata[]; + const attrs = metadataArray?.[0]; + if (!attrs) continue; + + // Get corresponding requirement data + const requirementData = requirementsMap.get(id); + if (!requirementData) continue; + + const frameworkName = attributeItem.attributes.framework; + const sectionName = attrs.Section; + const subSectionName = attrs.SubSection; + const title = attrs.Title; + const description = attributeItem.attributes.description; + const status = requirementData.attributes.status || ""; + const checks = attributeItem.attributes.attributes.check_ids || []; + const requirementName = id; + const levelOfRisk = attrs.LevelOfRisk; + const weight = attrs.Weight; + const attributeDescription = attrs.AttributeDescription; + const additionalInformation = attrs.AdditionalInformation; + + // Calculate score: if PASS = levelOfRisk * weight, if FAIL = 0 + const score = status === "PASS" ? levelOfRisk * weight : 0; + + // Find or create framework + let framework = frameworks.find((f) => f.name === frameworkName); + if (!framework) { + framework = { + name: frameworkName, + pass: 0, + fail: 0, + manual: 0, + categories: [], + }; + frameworks.push(framework); + } + + // Find or create category (Section) + let category = framework.categories.find((c) => c.name === sectionName); + if (!category) { + category = { + name: sectionName, + pass: 0, + fail: 0, + manual: 0, + controls: [], + }; + framework.categories.push(category); + } + + // Find or create control (SubSection) + let control = category.controls.find((c) => c.label === subSectionName); + if (!control) { + control = { + label: subSectionName, + pass: 0, + fail: 0, + manual: 0, + requirements: [], + }; + category.controls.push(control); + } + + // Create requirement + const finalStatus: RequirementStatus = status as RequirementStatus; + const requirement: Requirement = { + name: requirementName, + description: description, + status: finalStatus, + check_ids: checks, + pass: finalStatus === "PASS" ? 1 : 0, + fail: finalStatus === "FAIL" ? 1 : 0, + manual: finalStatus === "MANUAL" ? 1 : 0, + title: title, + levelOfRisk: levelOfRisk, + weight: weight, + score: score, + attributeDescription: attributeDescription, + additionalInformation: additionalInformation, + }; + + control.requirements.push(requirement); + } + + // Calculate counters and percentualScore + frameworks.forEach((framework) => { + framework.pass = 0; + framework.fail = 0; + framework.manual = 0; + + framework.categories.forEach((category) => { + category.pass = 0; + category.fail = 0; + category.manual = 0; + + // Calculate total score for this section and maximum possible score + let totalSectionScore = 0; + let maxPossibleSectionScore = 0; + + category.controls.forEach((control) => { + control.pass = 0; + control.fail = 0; + control.manual = 0; + + control.requirements.forEach((requirement) => { + if (requirement.status === "MANUAL") { + control.manual++; + } else if (requirement.status === "PASS") { + control.pass++; + } else if (requirement.status === "FAIL") { + control.fail++; + } + + // Add to total section score (actual score obtained) + totalSectionScore += (requirement.score as number) || 0; + + // Add to maximum possible score (weight * levelOfRisk for each requirement) + const levelOfRisk = (requirement.levelOfRisk as number) || 0; + const weight = (requirement.weight as number) || 0; + maxPossibleSectionScore += levelOfRisk * weight; + }); + + category.pass += control.pass; + category.fail += control.fail; + category.manual += control.manual; + }); + + // Calculate percentualScore for this section: (suma de scores obtenidos / suma de weight * levelOfRisk) * 100 + const percentualScore = + maxPossibleSectionScore > 0 + ? (totalSectionScore / maxPossibleSectionScore) * 100 + : 0; + + // Add percentualScore to category (we can extend the type or use a custom property) + (category as any).percentualScore = + Math.round(percentualScore * 100) / 100; // Round to 2 decimal places + + framework.pass += category.pass; + framework.fail += category.fail; + framework.manual += category.manual; + }); + }); + + return frameworks; +}; + +export const toAccordionItems = ( + data: Framework[], + scanId: string | undefined, +): AccordionItemProps[] => { + return data.flatMap((framework) => + framework.categories.map((category) => { + const percentualScore = (category as any).percentualScore || 0; + + return { + key: `${framework.name}-${category.name}`, + title: ( + + ), + content: "", + items: category.controls.map((control, i: number) => { + return { + key: `${framework.name}-${category.name}-control-${i}`, + title: ( + + ), + content: "", + items: control.requirements.map((requirement, j: number) => { + const itemKey = `${framework.name}-${category.name}-control-${i}-req-${j}`; + + return { + key: itemKey, + title: ( + + ), + content: ( + + ), + items: [], + }; + }), + isDisabled: + control.pass === 0 && control.fail === 0 && control.manual === 0, + }; + }), + }; + }), + ); +}; diff --git a/ui/types/compliance.ts b/ui/types/compliance.ts index f6551ba07e..c4f028331c 100644 --- a/ui/types/compliance.ts +++ b/ui/types/compliance.ts @@ -113,6 +113,16 @@ export interface AWSWellArchitectedAttributesMetadata { ImplementationGuidanceUrl: string; } +export interface ThreatAttributesMetadata { + Title: string; + Section: string; + SubSection: string; + AttributeDescription: string; + AdditionalInformation: string; + LevelOfRisk: number; + Weight: number; +} + export interface KISAAttributesMetadata { Domain: string; Subdomain: string; @@ -136,6 +146,7 @@ export interface AttributesItemData { | ISO27001AttributesMetadata[] | CISAttributesMetadata[] | AWSWellArchitectedAttributesMetadata[] + | ThreatAttributesMetadata[] | KISAAttributesMetadata[]; check_ids: string[]; };