mirror of
https://github.com/prowler-cloud/prowler.git
synced 2025-12-19 05:17:47 +00:00
feat(compliance): add CCC catalogs for AWS, Azure and GCP (#8000)
Co-authored-by: Alan Buscaglia <gentlemanprogramming@gmail.com>
This commit is contained in:
@@ -13,6 +13,7 @@ All notable changes to the **Prowler API** are documented in this file.
|
||||
- SAML role mapping protection for single-admin tenants to prevent accidental lockout [(#8882)](https://github.com/prowler-cloud/prowler/pull/8882)
|
||||
- Support for `passed_findings` and `total_findings` fields in compliance requirement overview for accurate Prowler ThreatScore calculation [(#8582)](https://github.com/prowler-cloud/prowler/pull/8582)
|
||||
- Database read replica support [(#8869)](https://github.com/prowler-cloud/prowler/pull/8869)
|
||||
- Support Common Cloud Controls for AWS, Azure and GCP [(#8000)](https://github.com/prowler-cloud/prowler/pull/8000)
|
||||
|
||||
### Changed
|
||||
- Now the MANAGE_ACCOUNT permission is required to modify or read user permissions instead of MANAGE_USERS [(#8281)](https://github.com/prowler-cloud/prowler/pull/8281)
|
||||
|
||||
@@ -20,6 +20,9 @@ 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.ccc.ccc_aws import CCC_AWS
|
||||
from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure
|
||||
from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP
|
||||
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
|
||||
@@ -74,6 +77,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 == "ccc_aws", CCC_AWS),
|
||||
(lambda name: name.startswith("c5_"), AWSC5),
|
||||
],
|
||||
"azure": [
|
||||
@@ -81,6 +85,7 @@ COMPLIANCE_CLASS_MAP = {
|
||||
(lambda name: name == "mitre_attack_azure", AzureMitreAttack),
|
||||
(lambda name: name.startswith("ens_"), AzureENS),
|
||||
(lambda name: name.startswith("iso27001_"), AzureISO27001),
|
||||
(lambda name: name == "ccc_azure", CCC_Azure),
|
||||
(lambda name: name == "prowler_threatscore_azure", ProwlerThreatScoreAzure),
|
||||
],
|
||||
"gcp": [
|
||||
@@ -89,6 +94,7 @@ COMPLIANCE_CLASS_MAP = {
|
||||
(lambda name: name.startswith("ens_"), GCPENS),
|
||||
(lambda name: name.startswith("iso27001_"), GCPISO27001),
|
||||
(lambda name: name == "prowler_threatscore_gcp", ProwlerThreatScoreGCP),
|
||||
(lambda name: name == "ccc_gcp", CCC_GCP),
|
||||
],
|
||||
"kubernetes": [
|
||||
(lambda name: name.startswith("cis_"), KubernetesCIS),
|
||||
|
||||
36
dashboard/compliance/ccc_aws.py
Normal file
36
dashboard/compliance/ccc_aws.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_3_levels
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
|
||||
data["REQUIREMENTS_ID"] = (
|
||||
data["REQUIREMENTS_ID"] + " - " + data["REQUIREMENTS_DESCRIPTION"]
|
||||
)
|
||||
|
||||
data["REQUIREMENTS_ID"] = data["REQUIREMENTS_ID"].apply(
|
||||
lambda x: x[:150] + "..." if len(str(x)) > 150 else x
|
||||
)
|
||||
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"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_ID",
|
||||
)
|
||||
36
dashboard/compliance/ccc_azure.py
Normal file
36
dashboard/compliance/ccc_azure.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_3_levels
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
|
||||
data["REQUIREMENTS_ID"] = (
|
||||
data["REQUIREMENTS_ID"] + " - " + data["REQUIREMENTS_DESCRIPTION"]
|
||||
)
|
||||
|
||||
data["REQUIREMENTS_ID"] = data["REQUIREMENTS_ID"].apply(
|
||||
lambda x: x[:150] + "..." if len(str(x)) > 150 else x
|
||||
)
|
||||
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"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_ID",
|
||||
)
|
||||
36
dashboard/compliance/ccc_gcp.py
Normal file
36
dashboard/compliance/ccc_gcp.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_3_levels
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
|
||||
data["REQUIREMENTS_ID"] = (
|
||||
data["REQUIREMENTS_ID"] + " - " + data["REQUIREMENTS_DESCRIPTION"]
|
||||
)
|
||||
|
||||
data["REQUIREMENTS_ID"] = data["REQUIREMENTS_ID"].apply(
|
||||
lambda x: x[:150] + "..." if len(str(x)) > 150 else x
|
||||
)
|
||||
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"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_ID",
|
||||
)
|
||||
@@ -15,6 +15,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- 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)
|
||||
- Add Common Cloud Controls for AWS, Azure and GCP [(#8000)](https://github.com/prowler-cloud/prowler/pull/8000)
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ 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.ccc.ccc_aws import CCC_AWS
|
||||
from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure
|
||||
from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP
|
||||
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
|
||||
@@ -555,6 +558,21 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(prowler_threatscore)
|
||||
prowler_threatscore.batch_write_data_to_file()
|
||||
elif compliance_name.startswith("ccc_"):
|
||||
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
|
||||
ccc_aws = CCC_AWS(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
file_path=filename,
|
||||
)
|
||||
|
||||
generated_outputs["compliance"].append(ccc_aws)
|
||||
ccc_aws.batch_write_data_to_file()
|
||||
elif compliance_name == "c5_aws":
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
@@ -646,6 +664,18 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(prowler_threatscore)
|
||||
prowler_threatscore.batch_write_data_to_file()
|
||||
elif compliance_name.startswith("ccc_"):
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
ccc_azure = CCC_Azure(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(ccc_azure)
|
||||
ccc_azure.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
@@ -725,6 +755,18 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(prowler_threatscore)
|
||||
prowler_threatscore.batch_write_data_to_file()
|
||||
elif compliance_name.startswith("ccc_"):
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
ccc_gcp = CCC_GCP(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(ccc_gcp)
|
||||
ccc_gcp.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
|
||||
8172
prowler/compliance/aws/ccc_aws.json
Normal file
8172
prowler/compliance/aws/ccc_aws.json
Normal file
File diff suppressed because it is too large
Load Diff
8144
prowler/compliance/azure/ccc_azure.json
Normal file
8144
prowler/compliance/azure/ccc_azure.json
Normal file
File diff suppressed because it is too large
Load Diff
8059
prowler/compliance/gcp/ccc_gcp.json
Normal file
8059
prowler/compliance/gcp/ccc_gcp.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -200,6 +200,21 @@ class Prowler_ThreatScore_Requirement_Attribute(BaseModel):
|
||||
Weight: int
|
||||
|
||||
|
||||
# CCC Requirement Attribute
|
||||
class CCC_Requirement_Attribute(BaseModel):
|
||||
"""CCC Requirement Attribute"""
|
||||
|
||||
FamilyName: str
|
||||
FamilyDescription: str
|
||||
Section: str
|
||||
SubSection: str
|
||||
SubSectionObjective: str
|
||||
Applicability: list[str]
|
||||
Recommendation: str
|
||||
SectionThreatMappings: list[dict]
|
||||
SectionGuidelineMappings: list[dict]
|
||||
|
||||
|
||||
# C5 Germany Requirement Attribute
|
||||
class C5Germany_Requirement_Attribute(BaseModel):
|
||||
"""C5 Germany Requirement Attribute"""
|
||||
@@ -227,6 +242,7 @@ class Compliance_Requirement(BaseModel):
|
||||
AWS_Well_Architected_Requirement_Attribute,
|
||||
KISA_ISMSP_Requirement_Attribute,
|
||||
Prowler_ThreatScore_Requirement_Attribute,
|
||||
CCC_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/ccc/__init__.py
Normal file
0
prowler/lib/outputs/compliance/ccc/__init__.py
Normal file
95
prowler/lib/outputs/compliance/ccc/ccc_aws.py
Normal file
95
prowler/lib/outputs/compliance/ccc/ccc_aws.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.ccc.models import CCC_AWSModel
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class CCC_AWS(ComplianceOutput):
|
||||
"""
|
||||
This class represents the AWS CCC 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 CCC compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into AWS CCC 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 = CCC_AWSModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
AccountId=finding.account_uid,
|
||||
Region=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
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 = CCC_AWSModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
95
prowler/lib/outputs/compliance/ccc/ccc_azure.py
Normal file
95
prowler/lib/outputs/compliance/ccc/ccc_azure.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.ccc.models import CCC_AzureModel
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class CCC_Azure(ComplianceOutput):
|
||||
"""
|
||||
This class represents the Azure CCC 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 Azure CCC compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into Azure CCC 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 = CCC_AzureModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
SubscriptionId=finding.account_uid,
|
||||
Location=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
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 = CCC_AzureModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
SubscriptionId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
95
prowler/lib/outputs/compliance/ccc/ccc_gcp.py
Normal file
95
prowler/lib/outputs/compliance/ccc/ccc_gcp.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.ccc.models import CCC_GCPModel
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class CCC_GCP(ComplianceOutput):
|
||||
"""
|
||||
This class represents the GCP CCC 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 GCP CCC compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into GCP CCC 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 = CCC_GCPModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
ProjectId=finding.account_uid,
|
||||
Location=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
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 = CCC_GCPModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
ProjectId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_FamilyName=attribute.FamilyName,
|
||||
Requirements_Attributes_FamilyDescription=attribute.FamilyDescription,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubSectionObjective=attribute.SubSectionObjective,
|
||||
Requirements_Attributes_Applicability=attribute.Applicability,
|
||||
Requirements_Attributes_Recommendation=attribute.Recommendation,
|
||||
Requirements_Attributes_SectionThreatMappings=attribute.SectionThreatMappings,
|
||||
Requirements_Attributes_SectionGuidelineMappings=attribute.SectionGuidelineMappings,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
90
prowler/lib/outputs/compliance/ccc/models.py
Normal file
90
prowler/lib/outputs/compliance/ccc/models.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CCC_AWSModel(BaseModel):
|
||||
"""
|
||||
CCC_AWSModel generates a finding's output in AWS CCC Compliance format.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
AccountId: str
|
||||
Region: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_FamilyName: str
|
||||
Requirements_Attributes_FamilyDescription: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_SubSectionObjective: str
|
||||
Requirements_Attributes_Applicability: list[str]
|
||||
Requirements_Attributes_Recommendation: str
|
||||
Requirements_Attributes_SectionThreatMappings: list[dict]
|
||||
Requirements_Attributes_SectionGuidelineMappings: list[dict]
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
ResourceName: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
|
||||
|
||||
class CCC_AzureModel(BaseModel):
|
||||
"""
|
||||
CCC_AzureModel generates a finding's output in Azure CCC Compliance format.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
SubscriptionId: str
|
||||
Location: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_FamilyName: str
|
||||
Requirements_Attributes_FamilyDescription: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_SubSectionObjective: str
|
||||
Requirements_Attributes_Applicability: list[str]
|
||||
Requirements_Attributes_Recommendation: str
|
||||
Requirements_Attributes_SectionThreatMappings: list[dict]
|
||||
Requirements_Attributes_SectionGuidelineMappings: list[dict]
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
ResourceName: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
|
||||
|
||||
class CCC_GCPModel(BaseModel):
|
||||
"""
|
||||
CCC_GCPModel generates a finding's output in GCP CCC Compliance format.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
ProjectId: str
|
||||
Location: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_FamilyName: str
|
||||
Requirements_Attributes_FamilyDescription: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_SubSectionObjective: str
|
||||
Requirements_Attributes_Applicability: list[str]
|
||||
Requirements_Attributes_Recommendation: str
|
||||
Requirements_Attributes_SectionThreatMappings: list[dict]
|
||||
Requirements_Attributes_SectionGuidelineMappings: list[dict]
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
ResourceName: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
@@ -15,6 +15,7 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
- 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)
|
||||
- Support Common Cloud Controls for AWS, Azure and GCP [(#8000)](https://github.com/prowler-cloud/prowler/pull/8000)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { cn } from "@/lib";
|
||||
import { CCC_MAPPING_SECTIONS, CCC_TEXT_SECTIONS } from "@/lib/compliance/ccc";
|
||||
import { Requirement } from "@/types/compliance";
|
||||
|
||||
import {
|
||||
ComplianceBadge,
|
||||
ComplianceBadgeContainer,
|
||||
ComplianceChipContainer,
|
||||
ComplianceDetailContainer,
|
||||
ComplianceDetailSection,
|
||||
ComplianceDetailText,
|
||||
} from "./shared-components";
|
||||
|
||||
interface CCCDetailsProps {
|
||||
requirement: Requirement;
|
||||
}
|
||||
|
||||
export const CCCCustomDetails = ({ requirement }: CCCDetailsProps) => {
|
||||
// Map text sections with requirement data
|
||||
const textSections = CCC_TEXT_SECTIONS.map((section) => ({
|
||||
...section,
|
||||
content: requirement[section.key] as string | undefined,
|
||||
})).filter((section) => section.content);
|
||||
|
||||
// Map mapping sections with requirement data
|
||||
const mappingSections = CCC_MAPPING_SECTIONS.map((section) => ({
|
||||
...section,
|
||||
data: requirement[section.key] as Array<{
|
||||
ReferenceId: string;
|
||||
Identifiers: string[];
|
||||
}>,
|
||||
})).filter((section) => section.data);
|
||||
|
||||
return (
|
||||
<ComplianceDetailContainer>
|
||||
{textSections.map((section) => (
|
||||
<ComplianceDetailSection key={section.title} title={section.title}>
|
||||
<ComplianceDetailText className={section.className}>
|
||||
{section.content}
|
||||
</ComplianceDetailText>
|
||||
</ComplianceDetailSection>
|
||||
))}
|
||||
|
||||
{requirement.family_name && (
|
||||
<ComplianceBadgeContainer>
|
||||
<ComplianceBadge
|
||||
label="Family"
|
||||
value={requirement.family_name as string}
|
||||
color="purple"
|
||||
/>
|
||||
</ComplianceBadgeContainer>
|
||||
)}
|
||||
|
||||
{requirement.applicability && (
|
||||
<ComplianceChipContainer
|
||||
title="Applicability"
|
||||
items={requirement.applicability as string[]}
|
||||
/>
|
||||
)}
|
||||
|
||||
{mappingSections.map((section) => (
|
||||
<ComplianceDetailSection key={section.title} title={section.title}>
|
||||
<div className="flex flex-col gap-3">
|
||||
{section.data.map((mapping, index) => (
|
||||
<div key={index} className="flex flex-col gap-1">
|
||||
<span className="text-muted-foreground text-xs font-medium">
|
||||
{mapping.ReferenceId}
|
||||
</span>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{mapping.Identifiers.map((identifier, idx) => (
|
||||
<span
|
||||
key={idx}
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset",
|
||||
section.colorClasses,
|
||||
)}
|
||||
>
|
||||
{identifier}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ComplianceDetailSection>
|
||||
))}
|
||||
</ComplianceDetailContainer>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import AWSLogo from "./aws.svg";
|
||||
import C5Logo from "./c5.svg";
|
||||
import CCCLogo from "./ccc.svg";
|
||||
import CISLogo from "./cis.svg";
|
||||
import CISALogo from "./cisa.svg";
|
||||
import ENSLogo from "./ens.png";
|
||||
@@ -38,6 +39,7 @@ const COMPLIANCE_LOGOS = {
|
||||
prowlerthreatscore: PROWLERTHREATLogo,
|
||||
nis2: NIS2Logo,
|
||||
c5: C5Logo,
|
||||
ccc: CCCLogo,
|
||||
} as const;
|
||||
|
||||
export const getComplianceIcon = (complianceTitle: string) => {
|
||||
|
||||
32
ui/components/icons/compliance/ccc.svg
Normal file
32
ui/components/icons/compliance/ccc.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 170" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="cccGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#0586BF"/>
|
||||
<stop offset="100%" style="stop-color:#00BCE7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Left C -->
|
||||
<g>
|
||||
<circle cx="81" cy="85" r="75" fill="url(#cccGradient)"/>
|
||||
<circle cx="81" cy="85" r="45" fill="white"/>
|
||||
</g>
|
||||
|
||||
<!-- Connecting pill 1 -->
|
||||
<ellipse cx="140" cy="85" rx="35" ry="16" fill="url(#cccGradient)"/>
|
||||
|
||||
<!-- Middle C -->
|
||||
<g>
|
||||
<circle cx="200" cy="85" r="75" fill="url(#cccGradient)"/>
|
||||
<circle cx="200" cy="85" r="45" fill="white"/>
|
||||
</g>
|
||||
|
||||
<!-- Connecting pill 2 -->
|
||||
<ellipse cx="260" cy="85" rx="35" ry="16" fill="url(#cccGradient)"/>
|
||||
|
||||
<!-- Right C -->
|
||||
<g>
|
||||
<circle cx="319" cy="85" r="75" fill="url(#cccGradient)"/>
|
||||
<circle cx="319" cy="85" r="45" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 944 B |
243
ui/lib/compliance/ccc.tsx
Normal file
243
ui/lib/compliance/ccc.tsx
Normal file
@@ -0,0 +1,243 @@
|
||||
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,
|
||||
CCCAttributesMetadata,
|
||||
Framework,
|
||||
Requirement,
|
||||
REQUIREMENT_STATUS,
|
||||
RequirementsData,
|
||||
RequirementStatus,
|
||||
} from "@/types/compliance";
|
||||
|
||||
import {
|
||||
calculateFrameworkCounters,
|
||||
createRequirementsMap,
|
||||
findOrCreateCategory,
|
||||
findOrCreateControl,
|
||||
findOrCreateFramework,
|
||||
updateCounters,
|
||||
} from "./commons";
|
||||
|
||||
interface ProcessedItem {
|
||||
id: string;
|
||||
attrs: CCCAttributesMetadata;
|
||||
attributeItem: any;
|
||||
requirementData: any;
|
||||
}
|
||||
|
||||
// CCC-specific section configuration
|
||||
export interface CCCTextSection {
|
||||
title: string;
|
||||
key: keyof Requirement;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface CCCMappingSection {
|
||||
title: string;
|
||||
key: keyof Requirement;
|
||||
colorClasses: string;
|
||||
}
|
||||
|
||||
export const CCC_TEXT_SECTIONS: CCCTextSection[] = [
|
||||
{
|
||||
title: "Description",
|
||||
key: "description",
|
||||
},
|
||||
{
|
||||
title: "Family Description",
|
||||
key: "family_description",
|
||||
},
|
||||
{
|
||||
title: "SubSection",
|
||||
key: "subsection",
|
||||
},
|
||||
{
|
||||
title: "SubSection Objective",
|
||||
key: "subsection_objective",
|
||||
className: "whitespace-pre-wrap",
|
||||
},
|
||||
{
|
||||
title: "Recommendation",
|
||||
key: "recommendation",
|
||||
className: "whitespace-pre-wrap",
|
||||
},
|
||||
];
|
||||
|
||||
export const CCC_MAPPING_SECTIONS: CCCMappingSection[] = [
|
||||
{
|
||||
title: "Threat Mappings",
|
||||
key: "section_threat_mappings",
|
||||
colorClasses:
|
||||
"bg-red-50 text-red-700 ring-red-600/10 dark:bg-red-400/10 dark:text-red-400 dark:ring-red-400/20",
|
||||
},
|
||||
{
|
||||
title: "Guideline Mappings",
|
||||
key: "section_guideline_mappings",
|
||||
colorClasses:
|
||||
"bg-blue-50 text-blue-700 ring-blue-600/10 dark:bg-blue-400/10 dark:text-blue-400 dark:ring-blue-400/20",
|
||||
},
|
||||
];
|
||||
|
||||
const createRequirement = (itemData: ProcessedItem): Requirement => {
|
||||
const { id, attrs, attributeItem, requirementData } = itemData;
|
||||
const description = attributeItem.attributes.description;
|
||||
const status = requirementData.attributes.status || "";
|
||||
const checks = attributeItem.attributes.attributes.check_ids || [];
|
||||
const finalStatus: RequirementStatus = status as RequirementStatus;
|
||||
|
||||
return {
|
||||
name: id,
|
||||
description: description,
|
||||
status: finalStatus,
|
||||
check_ids: checks,
|
||||
pass: finalStatus === REQUIREMENT_STATUS.PASS ? 1 : 0,
|
||||
fail: finalStatus === REQUIREMENT_STATUS.FAIL ? 1 : 0,
|
||||
manual: finalStatus === REQUIREMENT_STATUS.MANUAL ? 1 : 0,
|
||||
family_name: attrs.FamilyName,
|
||||
family_description: attrs.FamilyDescription,
|
||||
subsection: attrs.SubSection,
|
||||
subsection_objective: attrs.SubSectionObjective,
|
||||
applicability: attrs.Applicability,
|
||||
recommendation: attrs.Recommendation,
|
||||
section_threat_mappings: attrs.SectionThreatMappings,
|
||||
section_guideline_mappings: attrs.SectionGuidelineMappings,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapComplianceData = (
|
||||
attributesData: AttributesData,
|
||||
requirementsData: RequirementsData,
|
||||
): Framework[] => {
|
||||
const attributes = attributesData?.data || [];
|
||||
const requirementsMap = createRequirementsMap(requirementsData);
|
||||
const frameworks: Framework[] = [];
|
||||
const itemsByFramework = new Map<string, ProcessedItem[]>();
|
||||
|
||||
// First pass: collect all data
|
||||
for (const attributeItem of attributes) {
|
||||
const id = attributeItem.id;
|
||||
const metadataArray = attributeItem.attributes?.attributes
|
||||
?.metadata as unknown as CCCAttributesMetadata[];
|
||||
const attrs = metadataArray?.[0];
|
||||
if (!attrs) continue;
|
||||
|
||||
const requirementData = requirementsMap.get(id);
|
||||
if (!requirementData) continue;
|
||||
|
||||
const frameworkName = attributeItem.attributes.framework;
|
||||
|
||||
if (!itemsByFramework.has(frameworkName)) {
|
||||
itemsByFramework.set(frameworkName, []);
|
||||
}
|
||||
|
||||
itemsByFramework.get(frameworkName)!.push({
|
||||
id,
|
||||
attrs,
|
||||
attributeItem,
|
||||
requirementData,
|
||||
});
|
||||
}
|
||||
|
||||
// Process each framework
|
||||
for (const [frameworkName, items] of Array.from(itemsByFramework.entries())) {
|
||||
const framework = findOrCreateFramework(frameworks, frameworkName);
|
||||
|
||||
// Group by FamilyName (Category) -> Section (Control) -> Requirements
|
||||
for (const itemData of items) {
|
||||
const requirement = createRequirement(itemData);
|
||||
const familyName = itemData.attrs.FamilyName;
|
||||
const sectionName = itemData.attrs.Section;
|
||||
|
||||
// Create 3-level hierarchy: FamilyName -> Section -> Requirements
|
||||
const category = findOrCreateCategory(framework.categories, familyName);
|
||||
const control = findOrCreateControl(category.controls, sectionName);
|
||||
|
||||
control.requirements.push(requirement);
|
||||
updateCounters(control, requirement.status);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate counters using common helper
|
||||
calculateFrameworkCounters(frameworks);
|
||||
|
||||
return frameworks;
|
||||
};
|
||||
|
||||
// Helper function to create accordion item for requirement
|
||||
const createRequirementAccordionItem = (
|
||||
requirement: Requirement,
|
||||
itemKey: string,
|
||||
scanId: string,
|
||||
frameworkName: string,
|
||||
): AccordionItemProps => ({
|
||||
key: itemKey,
|
||||
title: (
|
||||
<ComplianceAccordionRequirementTitle
|
||||
type=""
|
||||
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: [],
|
||||
});
|
||||
|
||||
export const toAccordionItems = (
|
||||
data: Framework[],
|
||||
scanId: string | undefined,
|
||||
): AccordionItemProps[] => {
|
||||
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, i: number) => {
|
||||
const baseKey = `${framework.name}-${category.name}-control-${i}`;
|
||||
|
||||
return {
|
||||
key: baseKey,
|
||||
title: (
|
||||
<ComplianceAccordionTitle
|
||||
label={control.label}
|
||||
pass={control.pass}
|
||||
fail={control.fail}
|
||||
manual={control.manual}
|
||||
/>
|
||||
),
|
||||
content: "",
|
||||
items: control.requirements.map((requirement, j: number) =>
|
||||
createRequirementAccordionItem(
|
||||
requirement,
|
||||
`${baseKey}-req-${j}`,
|
||||
scanId || "",
|
||||
framework.name,
|
||||
),
|
||||
),
|
||||
isDisabled:
|
||||
control.pass === 0 && control.fail === 0 && control.manual === 0,
|
||||
};
|
||||
}),
|
||||
})),
|
||||
);
|
||||
};
|
||||
@@ -2,6 +2,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 { CCCCustomDetails } from "@/components/compliance/compliance-custom-details/ccc-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";
|
||||
@@ -27,6 +28,10 @@ import {
|
||||
mapComplianceData as mapC5ComplianceData,
|
||||
toAccordionItems as toC5AccordionItems,
|
||||
} from "./c5";
|
||||
import {
|
||||
mapComplianceData as mapCCCComplianceData,
|
||||
toAccordionItems as toCCCAccordionItems,
|
||||
} from "./ccc";
|
||||
import {
|
||||
mapComplianceData as mapCISComplianceData,
|
||||
toAccordionItems as toCISAccordionItems,
|
||||
@@ -165,6 +170,15 @@ const getComplianceMappers = (): Record<string, ComplianceMapper> => ({
|
||||
getDetailsComponent: (requirement: Requirement) =>
|
||||
React.createElement(ThreatCustomDetails, { requirement }),
|
||||
},
|
||||
CCC: {
|
||||
mapComplianceData: mapCCCComplianceData,
|
||||
toAccordionItems: toCCCAccordionItems,
|
||||
getTopFailedSections,
|
||||
calculateCategoryHeatmapData: (data: Framework[]) =>
|
||||
calculateCategoryHeatmapData(data),
|
||||
getDetailsComponent: (requirement: Requirement) =>
|
||||
React.createElement(CCCCustomDetails, { requirement }),
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -166,6 +166,24 @@ export interface GenericAttributesMetadata {
|
||||
Type: string | null;
|
||||
}
|
||||
|
||||
export interface CCCAttributesMetadata {
|
||||
FamilyName: string;
|
||||
FamilyDescription: string;
|
||||
Section: string;
|
||||
SubSection: string;
|
||||
SubSectionObjective: string;
|
||||
Applicability: string[];
|
||||
Recommendation: string;
|
||||
SectionThreatMappings: Array<{
|
||||
ReferenceId: string;
|
||||
Identifiers: string[];
|
||||
}>;
|
||||
SectionGuidelineMappings: Array<{
|
||||
ReferenceId: string;
|
||||
Identifiers: string[];
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface AttributesItemData {
|
||||
type: "compliance-requirements-attributes";
|
||||
id: string;
|
||||
@@ -185,6 +203,7 @@ export interface AttributesItemData {
|
||||
| KISAAttributesMetadata[]
|
||||
| C5AttributesMetadata[]
|
||||
| MITREAttributesMetadata[]
|
||||
| CCCAttributesMetadata[]
|
||||
| GenericAttributesMetadata[];
|
||||
check_ids: string[];
|
||||
// MITRE structure
|
||||
|
||||
Reference in New Issue
Block a user