mirror of
https://github.com/prowler-cloud/prowler.git
synced 2025-12-19 05:17:47 +00:00
feat(compliance): add C5 Germany for aws (#8830)
Co-authored-by: Alan Buscaglia <gentlemanprogramming@gmail.com>
This commit is contained in:
@@ -7,6 +7,7 @@ All notable changes to the **Prowler API** are documented in this file.
|
||||
### Added
|
||||
- Default JWT keys are generated and stored if they are missing from configuration [(#8655)](https://github.com/prowler-cloud/prowler/pull/8655)
|
||||
- `compliance_name` for each compliance [(#7920)](https://github.com/prowler-cloud/prowler/pull/7920)
|
||||
- Support C5 compliance framework for the AWS provider [(#8830)](https://github.com/prowler-cloud/prowler/pull/8830)
|
||||
- Support for M365 Certificate authentication [(#8538)](https://github.com/prowler-cloud/prowler/pull/8538)
|
||||
- API Key support [(#8805)](https://github.com/prowler-cloud/prowler/pull/8805)
|
||||
- SAML role mapping protection for single-admin tenants to prevent accidental lockout [(#8882)](https://github.com/prowler-cloud/prowler/pull/8882)
|
||||
|
||||
@@ -20,6 +20,7 @@ from prowler.lib.outputs.asff.asff import ASFF
|
||||
from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected import (
|
||||
AWSWellArchitected,
|
||||
)
|
||||
from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5
|
||||
from prowler.lib.outputs.compliance.cis.cis_aws import AWSCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_azure import AzureCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS
|
||||
@@ -73,6 +74,7 @@ COMPLIANCE_CLASS_MAP = {
|
||||
(lambda name: name.startswith("iso27001_"), AWSISO27001),
|
||||
(lambda name: name.startswith("kisa"), AWSKISAISMSP),
|
||||
(lambda name: name == "prowler_threatscore_aws", ProwlerThreatScoreAWS),
|
||||
(lambda name: name.startswith("c5_"), AWSC5),
|
||||
],
|
||||
"azure": [
|
||||
(lambda name: name.startswith("cis_"), AzureCIS),
|
||||
|
||||
43
dashboard/compliance/c5_aws.py
Normal file
43
dashboard/compliance/c5_aws.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_3_levels
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
data["REQUIREMENTS_DESCRIPTION"] = (
|
||||
data["REQUIREMENTS_ID"] + " - " + data["REQUIREMENTS_DESCRIPTION"]
|
||||
)
|
||||
|
||||
data["REQUIREMENTS_DESCRIPTION"] = data["REQUIREMENTS_DESCRIPTION"].apply(
|
||||
lambda x: x[:150] + "..." if len(str(x)) > 150 else x
|
||||
)
|
||||
|
||||
data["REQUIREMENTS_ATTRIBUTES_SECTION"] = data[
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
].apply(lambda x: x[:80] + "..." if len(str(x)) > 80 else x)
|
||||
|
||||
data["REQUIREMENTS_ATTRIBUTES_SUBSECTION"] = data[
|
||||
"REQUIREMENTS_ATTRIBUTES_SUBSECTION"
|
||||
].apply(lambda x: x[:150] + "..." if len(str(x)) > 150 else x)
|
||||
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SUBSECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_3_levels(
|
||||
aux,
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SUBSECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
)
|
||||
@@ -11,6 +11,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- LLM provider using `promptfoo` [(#8555)](https://github.com/prowler-cloud/prowler/pull/8555)
|
||||
- Documentation for renaming checks [(#8717)](https://github.com/prowler-cloud/prowler/pull/8717)
|
||||
- Add explicit "name" field for each compliance framework and include "FRAMEWORK" and "NAME" in CSV output [(#7920)](https://github.com/prowler-cloud/prowler/pull/7920)
|
||||
- Add C5 compliance framework for the AWS provider [(#8830)](https://github.com/prowler-cloud/prowler/pull/8830)
|
||||
- Equality validation for CheckID, filename and classname [(#8690)](https://github.com/prowler-cloud/prowler/pull/8690)
|
||||
- Improve logging for Security Hub integration [(#8608)](https://github.com/prowler-cloud/prowler/pull/8608)
|
||||
- Support for Atlassian Document Format (ADF) in Jira integration [(#8878)](https://github.com/prowler-cloud/prowler/pull/8878)
|
||||
|
||||
@@ -49,6 +49,7 @@ from prowler.lib.outputs.asff.asff import ASFF
|
||||
from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected import (
|
||||
AWSWellArchitected,
|
||||
)
|
||||
from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5
|
||||
from prowler.lib.outputs.compliance.cis.cis_aws import AWSCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_azure import AzureCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS
|
||||
@@ -554,6 +555,18 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(prowler_threatscore)
|
||||
prowler_threatscore.batch_write_data_to_file()
|
||||
elif compliance_name == "c5_aws":
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
c5 = AWSC5(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(c5)
|
||||
c5.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
|
||||
10744
prowler/compliance/aws/c5_aws.json
Normal file
10744
prowler/compliance/aws/c5_aws.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -200,6 +200,17 @@ class Prowler_ThreatScore_Requirement_Attribute(BaseModel):
|
||||
Weight: int
|
||||
|
||||
|
||||
# C5 Germany Requirement Attribute
|
||||
class C5Germany_Requirement_Attribute(BaseModel):
|
||||
"""C5 Germany Requirement Attribute"""
|
||||
|
||||
Section: str
|
||||
SubSection: str
|
||||
Type: str
|
||||
AboutCriteria: str
|
||||
ComplementaryCriteria: str
|
||||
|
||||
|
||||
# Base Compliance Model
|
||||
# TODO: move this to compliance folder
|
||||
class Compliance_Requirement(BaseModel):
|
||||
@@ -216,6 +227,7 @@ class Compliance_Requirement(BaseModel):
|
||||
AWS_Well_Architected_Requirement_Attribute,
|
||||
KISA_ISMSP_Requirement_Attribute,
|
||||
Prowler_ThreatScore_Requirement_Attribute,
|
||||
C5Germany_Requirement_Attribute,
|
||||
# Generic_Compliance_Requirement_Attribute must be the last one since it is the fallback for generic compliance framework
|
||||
Generic_Compliance_Requirement_Attribute,
|
||||
]
|
||||
|
||||
0
prowler/lib/outputs/compliance/c5/__init__.py
Normal file
0
prowler/lib/outputs/compliance/c5/__init__.py
Normal file
98
prowler/lib/outputs/compliance/c5/c5.py
Normal file
98
prowler/lib/outputs/compliance/c5/c5.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from colorama import Fore, Style
|
||||
from tabulate import tabulate
|
||||
|
||||
from prowler.config.config import orange_color
|
||||
|
||||
|
||||
def get_c5_table(
|
||||
findings: list,
|
||||
bulk_checks_metadata: dict,
|
||||
compliance_framework: str,
|
||||
output_filename: str,
|
||||
output_directory: str,
|
||||
compliance_overview: bool,
|
||||
):
|
||||
section_table = {
|
||||
"Provider": [],
|
||||
"Section": [],
|
||||
"Status": [],
|
||||
"Muted": [],
|
||||
}
|
||||
pass_count = []
|
||||
fail_count = []
|
||||
muted_count = []
|
||||
sections = {}
|
||||
for index, finding in enumerate(findings):
|
||||
check = bulk_checks_metadata[finding.check_metadata.CheckID]
|
||||
check_compliances = check.Compliance
|
||||
for compliance in check_compliances:
|
||||
if compliance.Framework == "C5":
|
||||
for requirement in compliance.Requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
section = attribute.Section
|
||||
|
||||
if section not in sections:
|
||||
sections[section] = {"FAIL": 0, "PASS": 0, "Muted": 0}
|
||||
|
||||
if finding.muted:
|
||||
if index not in muted_count:
|
||||
muted_count.append(index)
|
||||
sections[section]["Muted"] += 1
|
||||
else:
|
||||
if finding.status == "FAIL" and index not in fail_count:
|
||||
fail_count.append(index)
|
||||
sections[section]["FAIL"] += 1
|
||||
elif finding.status == "PASS" and index not in pass_count:
|
||||
pass_count.append(index)
|
||||
sections[section]["PASS"] += 1
|
||||
|
||||
sections = dict(sorted(sections.items()))
|
||||
for section in sections:
|
||||
section_table["Provider"].append(compliance.Provider)
|
||||
section_table["Section"].append(section)
|
||||
if sections[section]["FAIL"] > 0:
|
||||
section_table["Status"].append(
|
||||
f"{Fore.RED}FAIL({sections[section]['FAIL']}){Style.RESET_ALL}"
|
||||
)
|
||||
else:
|
||||
if sections[section]["PASS"] > 0:
|
||||
section_table["Status"].append(
|
||||
f"{Fore.GREEN}PASS({sections[section]['PASS']}){Style.RESET_ALL}"
|
||||
)
|
||||
else:
|
||||
section_table["Status"].append(f"{Fore.GREEN}PASS{Style.RESET_ALL}")
|
||||
section_table["Muted"].append(
|
||||
f"{orange_color}{sections[section]['Muted']}{Style.RESET_ALL}"
|
||||
)
|
||||
|
||||
if (
|
||||
len(fail_count) + len(pass_count) + len(muted_count) > 1
|
||||
): # If there are no resources, don't print the compliance table
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
if not compliance_overview:
|
||||
if len(fail_count) > 0 and len(section_table["Section"]) > 0:
|
||||
print(
|
||||
f"\nFramework {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Results:"
|
||||
)
|
||||
print(
|
||||
tabulate(
|
||||
section_table,
|
||||
tablefmt="rounded_grid",
|
||||
headers="keys",
|
||||
)
|
||||
)
|
||||
print(f"\nDetailed results of {compliance_framework.upper()} are in:")
|
||||
print(
|
||||
f" - CSV: {output_directory}/compliance/{output_filename}_{compliance_framework}.csv\n"
|
||||
)
|
||||
92
prowler/lib/outputs/compliance/c5/c5_aws.py
Normal file
92
prowler/lib/outputs/compliance/c5/c5_aws.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from prowler.config.config import timestamp
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.c5.models import AWSC5Model
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class AWSC5(ComplianceOutput):
|
||||
"""
|
||||
This class represents the AWS C5 compliance output.
|
||||
|
||||
Attributes:
|
||||
- _data (list): A list to store transformed data from findings.
|
||||
- _file_descriptor (TextIOWrapper): A file descriptor to write data to a file.
|
||||
|
||||
Methods:
|
||||
- transform: Transforms findings into AWS C5 compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into AWS C5 compliance format.
|
||||
|
||||
Parameters:
|
||||
- findings (list): A list of findings.
|
||||
- compliance (Compliance): A compliance model.
|
||||
- compliance_name (str): The name of the compliance model.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
for finding in findings:
|
||||
# Get the compliance requirements for the finding
|
||||
finding_requirements = finding.compliance.get(compliance_name, [])
|
||||
for requirement in compliance.Requirements:
|
||||
if requirement.Id in finding_requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = AWSC5Model(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
AccountId=finding.account_uid,
|
||||
Region=finding.region,
|
||||
AssessmentDate=str(timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Type=attribute.Type,
|
||||
Requirements_Attributes_AboutCriteria=attribute.AboutCriteria,
|
||||
Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria,
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
Framework=compliance.Framework,
|
||||
Name=compliance.Name,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
# Add manual requirements to the compliance output
|
||||
for requirement in compliance.Requirements:
|
||||
if not requirement.Checks:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = AWSC5Model(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Type=attribute.Type,
|
||||
Requirements_Attributes_AboutCriteria=attribute.AboutCriteria,
|
||||
Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
Framework=compliance.Framework,
|
||||
Name=compliance.Name,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
30
prowler/lib/outputs/compliance/c5/models.py
Normal file
30
prowler/lib/outputs/compliance/c5/models.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic.v1 import BaseModel
|
||||
|
||||
|
||||
class AWSC5Model(BaseModel):
|
||||
"""
|
||||
AWSC5Model generates a finding's output in AWS C5 Compliance format.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
AccountId: str
|
||||
Region: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: str = None
|
||||
Requirements_Attributes_Type: str = None
|
||||
Requirements_Attributes_AboutCriteria: Optional[str] = None
|
||||
Requirements_Attributes_ComplementaryCriteria: Optional[str] = None
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
ResourceName: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
Framework: str
|
||||
Name: str
|
||||
@@ -2,6 +2,7 @@ import sys
|
||||
|
||||
from prowler.lib.check.models import Check_Report
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.outputs.compliance.c5.c5 import get_c5_table
|
||||
from prowler.lib.outputs.compliance.cis.cis import get_cis_table
|
||||
from prowler.lib.outputs.compliance.ens.ens import get_ens_table
|
||||
from prowler.lib.outputs.compliance.generic.generic_table import (
|
||||
@@ -84,6 +85,15 @@ def display_compliance_table(
|
||||
output_directory,
|
||||
compliance_overview,
|
||||
)
|
||||
elif "c5_" in compliance_framework:
|
||||
get_c5_table(
|
||||
findings,
|
||||
bulk_checks_metadata,
|
||||
compliance_framework,
|
||||
output_filename,
|
||||
output_directory,
|
||||
compliance_overview,
|
||||
)
|
||||
else:
|
||||
get_generic_compliance_table(
|
||||
findings,
|
||||
|
||||
@@ -12,6 +12,7 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
- React Compiler support for automatic optimization [(#8748)](https://github.com/prowler-cloud/prowler/pull/8748)
|
||||
- Turbopack support for faster development builds [(#8748)](https://github.com/prowler-cloud/prowler/pull/8748)
|
||||
- Add compliance name in compliance detail view [(#8775)](https://github.com/prowler-cloud/prowler/pull/8775)
|
||||
- Support C5 compliance framework for the AWS provider [(#8830)](https://github.com/prowler-cloud/prowler/pull/8830)
|
||||
- API key management in user profile [(#8308)](https://github.com/prowler-cloud/prowler/pull/8308)
|
||||
- Refresh access token error handling [(#8864)](https://github.com/prowler-cloud/prowler/pull/8864)
|
||||
|
||||
|
||||
@@ -7,12 +7,18 @@ interface ComplianceAccordionRequirementTitleProps {
|
||||
}
|
||||
|
||||
export const ComplianceAccordionRequirementTitle = ({
|
||||
type,
|
||||
name,
|
||||
status,
|
||||
}: ComplianceAccordionRequirementTitleProps) => {
|
||||
return (
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<div className="flex w-5/6 items-center gap-1">
|
||||
<div className="flex w-5/6 items-center gap-2">
|
||||
{type && (
|
||||
<span className="bg-primary/10 text-primary rounded-md px-2 py-0.5 text-xs font-medium">
|
||||
{type}
|
||||
</span>
|
||||
)}
|
||||
<span>{name}</span>
|
||||
</div>
|
||||
<StatusFindingBadge status={status} />
|
||||
|
||||
@@ -118,11 +118,13 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
|
||||
onClick={navigateToDetail}
|
||||
>
|
||||
<div className="flex w-full items-center gap-4">
|
||||
<Image
|
||||
src={getComplianceIcon(title)}
|
||||
alt={`${title} logo`}
|
||||
className="h-10 w-10 min-w-10 rounded-md border border-gray-300 bg-white object-contain p-1"
|
||||
/>
|
||||
{getComplianceIcon(title) && (
|
||||
<Image
|
||||
src={getComplianceIcon(title)}
|
||||
alt={`${title} logo`}
|
||||
className="h-10 w-10 min-w-10 rounded-md border border-gray-300 bg-white object-contain p-1"
|
||||
/>
|
||||
)}
|
||||
<div className="flex w-full flex-col">
|
||||
<h4 className="text-small mb-1 leading-5 font-bold">
|
||||
{formatTitle(title)}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Requirement } from "@/types/compliance";
|
||||
|
||||
import {
|
||||
ComplianceDetailContainer,
|
||||
ComplianceDetailSection,
|
||||
ComplianceDetailText,
|
||||
} from "./shared-components";
|
||||
|
||||
export const C5CustomDetails = ({
|
||||
requirement,
|
||||
}: {
|
||||
requirement: Requirement;
|
||||
}) => {
|
||||
const sections = [
|
||||
{
|
||||
title: "Description",
|
||||
content: requirement.description,
|
||||
},
|
||||
{
|
||||
title: "About Criteria",
|
||||
content: requirement.about_criteria as string | undefined,
|
||||
},
|
||||
{
|
||||
title: "Complementary Criteria",
|
||||
content: requirement.complementary_criteria as string | undefined,
|
||||
},
|
||||
].filter((section) => section.content);
|
||||
|
||||
return (
|
||||
<ComplianceDetailContainer>
|
||||
{sections.map((section) => (
|
||||
<ComplianceDetailSection key={section.title} title={section.title}>
|
||||
<ComplianceDetailText>{section.content}</ComplianceDetailText>
|
||||
</ComplianceDetailSection>
|
||||
))}
|
||||
</ComplianceDetailContainer>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import AWSLogo from "./aws.svg";
|
||||
import C5Logo from "./c5.svg";
|
||||
import CISLogo from "./cis.svg";
|
||||
import CISALogo from "./cisa.svg";
|
||||
import ENSLogo from "./ens.png";
|
||||
@@ -17,59 +18,31 @@ import PROWLERTHREATLogo from "./prowlerThreat.svg";
|
||||
import RBILogo from "./rbi.svg";
|
||||
import SOC2Logo from "./soc2.svg";
|
||||
|
||||
const COMPLIANCE_LOGOS = {
|
||||
aws: AWSLogo,
|
||||
cisa: CISALogo,
|
||||
cis: CISLogo,
|
||||
ens: ENSLogo,
|
||||
ffiec: FFIECLogo,
|
||||
fedramp: FedRAMPLogo,
|
||||
gdpr: GDPRLogo,
|
||||
gxp: GxPLogo,
|
||||
hipaa: HIPAALogo,
|
||||
iso: ISOLogo,
|
||||
mitre: MITRELogo,
|
||||
nist: NISTLogo,
|
||||
pci: PCILogo,
|
||||
rbi: RBILogo,
|
||||
soc2: SOC2Logo,
|
||||
kisa: KISALogo,
|
||||
prowlerthreatscore: PROWLERTHREATLogo,
|
||||
nis2: NIS2Logo,
|
||||
c5: C5Logo,
|
||||
} as const;
|
||||
|
||||
export const getComplianceIcon = (complianceTitle: string) => {
|
||||
if (complianceTitle.toLowerCase().includes("aws")) {
|
||||
return AWSLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("cisa")) {
|
||||
return CISALogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("cis")) {
|
||||
return CISLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("ens")) {
|
||||
return ENSLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("ffiec")) {
|
||||
return FFIECLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("fedramp")) {
|
||||
return FedRAMPLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("gdpr")) {
|
||||
return GDPRLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("gxp")) {
|
||||
return GxPLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("hipaa")) {
|
||||
return HIPAALogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("iso")) {
|
||||
return ISOLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("mitre")) {
|
||||
return MITRELogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("nist")) {
|
||||
return NISTLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("pci")) {
|
||||
return PCILogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("rbi")) {
|
||||
return RBILogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("soc2")) {
|
||||
return SOC2Logo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("kisa")) {
|
||||
return KISALogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("prowlerthreatscore")) {
|
||||
return PROWLERTHREATLogo;
|
||||
}
|
||||
if (complianceTitle.toLowerCase().includes("nis2")) {
|
||||
return NIS2Logo;
|
||||
}
|
||||
const lowerTitle = complianceTitle.toLowerCase();
|
||||
return Object.entries(COMPLIANCE_LOGOS).find(([keyword]) =>
|
||||
lowerTitle.includes(keyword),
|
||||
)?.[1];
|
||||
};
|
||||
|
||||
6
ui/components/icons/compliance/c5.svg
Normal file
6
ui/components/icons/compliance/c5.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 31 KiB |
@@ -8,6 +8,7 @@ import {
|
||||
AWSWellArchitectedAttributesMetadata,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -68,9 +69,9 @@ export const mapComplianceData = (
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
well_architected_name: attrs.Name,
|
||||
well_architected_question_id: attrs.WellArchitectedQuestionId,
|
||||
well_architected_practice_id: attrs.WellArchitectedPracticeId,
|
||||
|
||||
179
ui/lib/compliance/c5.tsx
Normal file
179
ui/lib/compliance/c5.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
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,
|
||||
C5AttributesMetadata,
|
||||
Control,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
|
||||
import {
|
||||
calculateFrameworkCounters,
|
||||
createRequirementsMap,
|
||||
findOrCreateCategory,
|
||||
findOrCreateControl,
|
||||
findOrCreateFramework,
|
||||
} from "./commons";
|
||||
|
||||
const getStatusCounters = (status: RequirementStatus) => ({
|
||||
pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
});
|
||||
|
||||
export const mapComplianceData = (
|
||||
attributesData: AttributesData,
|
||||
requirementsData: RequirementsData,
|
||||
): Framework[] => {
|
||||
const attributes = attributesData?.data || [];
|
||||
const requirementsMap = createRequirementsMap(requirementsData);
|
||||
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 C5AttributesMetadata[];
|
||||
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 categoryName = attrs.Section; // Level 1: Section (e.g., "Organisation of Information Security (OIS)")
|
||||
const controlLabel = attrs.SubSection; // Level 2: SubSection (e.g., "OIS-01 Information Security Management System (ISMS)")
|
||||
const description = attributeItem.attributes.description;
|
||||
const status = requirementData.attributes.status || "";
|
||||
const checks = attributeItem.attributes.attributes.check_ids || [];
|
||||
const requirementName = id;
|
||||
|
||||
// Find or create framework using common helper
|
||||
const framework = findOrCreateFramework(frameworks, frameworkName);
|
||||
|
||||
// Find or create category (Section) using common helper
|
||||
const category = findOrCreateCategory(framework.categories, categoryName);
|
||||
|
||||
// Find or create control (SubSection) using common helper
|
||||
const control = findOrCreateControl(category.controls, controlLabel);
|
||||
|
||||
// Create requirement
|
||||
const finalStatus: RequirementStatus = status as RequirementStatus;
|
||||
const requirement: Requirement = {
|
||||
name: requirementName,
|
||||
description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
...getStatusCounters(finalStatus),
|
||||
type: attrs.Type,
|
||||
about_criteria: attrs.AboutCriteria,
|
||||
complementary_criteria: attrs.ComplementaryCriteria,
|
||||
};
|
||||
|
||||
control.requirements.push(requirement);
|
||||
}
|
||||
|
||||
// Calculate counters using common helper
|
||||
calculateFrameworkCounters(frameworks);
|
||||
|
||||
return frameworks;
|
||||
};
|
||||
|
||||
const createRequirementItem = (
|
||||
requirement: Requirement,
|
||||
frameworkName: string,
|
||||
categoryName: string,
|
||||
controlIndex: number,
|
||||
reqIndex: number,
|
||||
scanId: string,
|
||||
): AccordionItemProps => ({
|
||||
key: `${frameworkName}-${categoryName}-control-${controlIndex}-req-${reqIndex}`,
|
||||
title: (
|
||||
<ComplianceAccordionRequirementTitle
|
||||
type={requirement.type as string}
|
||||
name={requirement.name}
|
||||
status={requirement.status as FindingStatus}
|
||||
/>
|
||||
),
|
||||
content: (
|
||||
<ClientAccordionContent
|
||||
requirement={requirement}
|
||||
scanId={scanId}
|
||||
framework={frameworkName}
|
||||
disableFindings={
|
||||
requirement.check_ids.length === 0 && requirement.manual === 0
|
||||
}
|
||||
/>
|
||||
),
|
||||
items: [],
|
||||
});
|
||||
|
||||
const createControlItem = (
|
||||
control: Control,
|
||||
frameworkName: string,
|
||||
categoryName: string,
|
||||
controlIndex: number,
|
||||
scanId: string,
|
||||
): AccordionItemProps => ({
|
||||
key: `${frameworkName}-${categoryName}-control-${controlIndex}`,
|
||||
title: (
|
||||
<ComplianceAccordionTitle
|
||||
label={control.label}
|
||||
pass={control.pass}
|
||||
fail={control.fail}
|
||||
manual={control.manual}
|
||||
/>
|
||||
),
|
||||
content: "",
|
||||
items: control.requirements.map((requirement, reqIndex) =>
|
||||
createRequirementItem(
|
||||
requirement,
|
||||
frameworkName,
|
||||
categoryName,
|
||||
controlIndex,
|
||||
reqIndex,
|
||||
scanId,
|
||||
),
|
||||
),
|
||||
isDisabled: control.pass === 0 && control.fail === 0 && control.manual === 0,
|
||||
});
|
||||
|
||||
export const toAccordionItems = (
|
||||
data: Framework[],
|
||||
scanId: string | undefined,
|
||||
): AccordionItemProps[] => {
|
||||
const safeId = scanId || "";
|
||||
|
||||
return data.flatMap((framework) =>
|
||||
framework.categories.map((category) => ({
|
||||
key: `${framework.name}-${category.name}`,
|
||||
title: (
|
||||
<ComplianceAccordionTitle
|
||||
label={category.name}
|
||||
pass={category.pass}
|
||||
fail={category.fail}
|
||||
manual={category.manual}
|
||||
isParentLevel={true}
|
||||
/>
|
||||
),
|
||||
content: "",
|
||||
items: category.controls.map((control, controlIndex) =>
|
||||
createControlItem(
|
||||
control,
|
||||
framework.name,
|
||||
category.name,
|
||||
controlIndex,
|
||||
safeId,
|
||||
),
|
||||
),
|
||||
})),
|
||||
);
|
||||
};
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
CISAttributesMetadata,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -79,9 +80,9 @@ export const mapComplianceData = (
|
||||
description: attrs.Description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
profile: attrs.Profile,
|
||||
subsection: attrs.SubSection || "",
|
||||
assessment_status: attrs.AssessmentStatus,
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
FailedSection,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementItemData,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
@@ -12,11 +13,11 @@ export const updateCounters = (
|
||||
target: { pass: number; fail: number; manual: number },
|
||||
status: RequirementStatus,
|
||||
) => {
|
||||
if (status === "MANUAL") {
|
||||
if (status === REQUIREMENT_STATUS.MANUAL) {
|
||||
target.manual++;
|
||||
} else if (status === "PASS") {
|
||||
} else if (status === REQUIREMENT_STATUS.PASS) {
|
||||
target.pass++;
|
||||
} else if (status === "FAIL") {
|
||||
} else if (status === REQUIREMENT_STATUS.FAIL) {
|
||||
target.fail++;
|
||||
}
|
||||
};
|
||||
@@ -30,7 +31,7 @@ export const getTopFailedSections = (
|
||||
framework.categories.forEach((category) => {
|
||||
category.controls.forEach((control) => {
|
||||
control.requirements.forEach((requirement) => {
|
||||
if (requirement.status === "FAIL") {
|
||||
if (requirement.status === REQUIREMENT_STATUS.FAIL) {
|
||||
const sectionName = category.name;
|
||||
|
||||
if (!failedSectionMap.has(sectionName)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import { AWSWellArchitectedCustomDetails } from "@/components/compliance/compliance-custom-details/aws-well-architected-details";
|
||||
import { C5CustomDetails } from "@/components/compliance/compliance-custom-details/c5-details";
|
||||
import { CISCustomDetails } from "@/components/compliance/compliance-custom-details/cis-details";
|
||||
import { ENSCustomDetails } from "@/components/compliance/compliance-custom-details/ens-details";
|
||||
import { GenericCustomDetails } from "@/components/compliance/compliance-custom-details/generic-details";
|
||||
@@ -22,6 +23,10 @@ import {
|
||||
mapComplianceData as mapAWSWellArchitectedComplianceData,
|
||||
toAccordionItems as toAWSWellArchitectedAccordionItems,
|
||||
} from "./aws-well-architected";
|
||||
import {
|
||||
mapComplianceData as mapC5ComplianceData,
|
||||
toAccordionItems as toC5AccordionItems,
|
||||
} from "./c5";
|
||||
import {
|
||||
mapComplianceData as mapCISComplianceData,
|
||||
toAccordionItems as toCISAccordionItems,
|
||||
@@ -80,6 +85,15 @@ const getDefaultMapper = (): ComplianceMapper => ({
|
||||
});
|
||||
|
||||
const getComplianceMappers = (): Record<string, ComplianceMapper> => ({
|
||||
C5: {
|
||||
mapComplianceData: mapC5ComplianceData,
|
||||
toAccordionItems: toC5AccordionItems,
|
||||
getTopFailedSections,
|
||||
calculateCategoryHeatmapData: (data: Framework[]) =>
|
||||
calculateCategoryHeatmapData(data),
|
||||
getDetailsComponent: (requirement: Requirement) =>
|
||||
React.createElement(C5CustomDetails, { requirement }),
|
||||
},
|
||||
ENS: {
|
||||
mapComplianceData: mapENSComplianceData,
|
||||
toAccordionItems: toENSAccordionItems,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
ENSAttributesMetadata,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -82,7 +83,7 @@ export const mapComplianceData = (
|
||||
|
||||
// Create requirement
|
||||
const finalStatus: RequirementStatus = isManual
|
||||
? "MANUAL"
|
||||
? REQUIREMENT_STATUS.MANUAL
|
||||
: (status as RequirementStatus);
|
||||
const requirement: Requirement = {
|
||||
name: requirementName,
|
||||
@@ -90,9 +91,9 @@ export const mapComplianceData = (
|
||||
status: finalStatus,
|
||||
type,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
nivel: attrs.Nivel || "",
|
||||
dimensiones: attrs.Dimensiones || [],
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Framework,
|
||||
GenericAttributesMetadata,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -41,9 +42,9 @@ const createRequirement = (itemData: ProcessedItem): Requirement => {
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
item_id: attrs.ItemId,
|
||||
subsection: attrs.SubSection,
|
||||
subgroup: attrs.SubGroup || undefined,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Framework,
|
||||
ISO27001AttributesMetadata,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -66,9 +67,9 @@ export const mapComplianceData = (
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
objetive_name: objetiveName,
|
||||
check_summary: checkSummary,
|
||||
control_label: controlLabel,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Framework,
|
||||
KISAAttributesMetadata,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -65,9 +66,9 @@ export const mapComplianceData = (
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
section: sectionName,
|
||||
audit_checklist: attrs.AuditChecklist,
|
||||
related_regulations: attrs.RelatedRegulations,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
Framework,
|
||||
MITREAttributesMetadata,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
@@ -62,9 +63,9 @@ export const mapComplianceData = (
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
// MITRE specific fields
|
||||
technique_id: id,
|
||||
technique_name: techniqueName,
|
||||
@@ -154,7 +155,7 @@ export const getTopFailedSections = (
|
||||
const requirements = (framework as any).requirements || [];
|
||||
|
||||
requirements.forEach((requirement: Requirement) => {
|
||||
if (requirement.status === "FAIL") {
|
||||
if (requirement.status === REQUIREMENT_STATUS.FAIL) {
|
||||
const tactics = (requirement.tactics as string[]) || [];
|
||||
|
||||
tactics.forEach((tactic) => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
AttributesData,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
ThreatAttributesMetadata,
|
||||
@@ -56,7 +57,7 @@ export const mapComplianceData = (
|
||||
const totalFindings = requirementData.attributes.total_findings || 0;
|
||||
|
||||
// Calculate score: if PASS = levelOfRisk * weight, if FAIL = 0
|
||||
const score = status === "PASS" ? levelOfRisk * weight : 0;
|
||||
const score = status === REQUIREMENT_STATUS.PASS ? levelOfRisk * weight : 0;
|
||||
|
||||
// Find or create framework using common helper
|
||||
const framework = findOrCreateFramework(frameworks, frameworkName);
|
||||
@@ -74,9 +75,9 @@ export const mapComplianceData = (
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === "PASS" ? 1 : 0,
|
||||
fail: finalStatus === "FAIL" ? 1 : 0,
|
||||
manual: finalStatus === "MANUAL" ? 1 : 0,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
title: title,
|
||||
levelOfRisk: levelOfRisk,
|
||||
weight: weight,
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
export type RequirementStatus = "PASS" | "FAIL" | "MANUAL" | "No findings";
|
||||
export const REQUIREMENT_STATUS = {
|
||||
PASS: "PASS",
|
||||
FAIL: "FAIL",
|
||||
MANUAL: "MANUAL",
|
||||
NO_FINDINGS: "No findings",
|
||||
} as const;
|
||||
|
||||
export type RequirementStatus =
|
||||
(typeof REQUIREMENT_STATUS)[keyof typeof REQUIREMENT_STATUS];
|
||||
|
||||
export interface CompliancesOverview {
|
||||
data: ComplianceOverviewData[];
|
||||
@@ -133,6 +141,14 @@ export interface KISAAttributesMetadata {
|
||||
NonComplianceCases: string[];
|
||||
}
|
||||
|
||||
export interface C5AttributesMetadata {
|
||||
Section: string;
|
||||
SubSection: string;
|
||||
Type: string;
|
||||
AboutCriteria: string;
|
||||
ComplementaryCriteria: string;
|
||||
}
|
||||
|
||||
export interface MITREAttributesMetadata {
|
||||
// Dynamic cloud service field - could be AWSService, GCPService, AzureService, etc.
|
||||
[key: string]: string;
|
||||
@@ -167,6 +183,7 @@ export interface AttributesItemData {
|
||||
| AWSWellArchitectedAttributesMetadata[]
|
||||
| ThreatAttributesMetadata[]
|
||||
| KISAAttributesMetadata[]
|
||||
| C5AttributesMetadata[]
|
||||
| MITREAttributesMetadata[]
|
||||
| GenericAttributesMetadata[];
|
||||
check_ids: string[];
|
||||
|
||||
Reference in New Issue
Block a user