mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
chore(compliance): add manual requirements to compliance output (#4449)
Co-authored-by: pedrooot <pedromarting3@gmail.com>
This commit is contained in:
@@ -1,16 +1,21 @@
|
||||
import sys
|
||||
|
||||
from pydantic import parse_obj_as
|
||||
|
||||
from prowler.lib.check.compliance_models import ComplianceBaseModel
|
||||
from prowler.lib.check.models import Check_Metadata_Model
|
||||
from prowler.lib.logger import logger
|
||||
|
||||
|
||||
def update_checks_metadata_with_compliance(
|
||||
bulk_compliance_frameworks: dict, bulk_checks_metadata: dict
|
||||
):
|
||||
"""Update the check metadata model with the compliance framework"""
|
||||
) -> dict:
|
||||
"""
|
||||
Update the check metadata model with the compliance framework
|
||||
Args:
|
||||
bulk_compliance_frameworks (dict): The compliance frameworks
|
||||
bulk_checks_metadata (dict): The checks metadata
|
||||
|
||||
Returns:
|
||||
dict: The checks metadata with the compliance frameworks
|
||||
"""
|
||||
try:
|
||||
for check in bulk_checks_metadata:
|
||||
check_compliance = []
|
||||
@@ -33,53 +38,6 @@ def update_checks_metadata_with_compliance(
|
||||
check_compliance.append(compliance)
|
||||
# Save it into the check's metadata
|
||||
bulk_checks_metadata[check].Compliance = check_compliance
|
||||
|
||||
check_compliance = []
|
||||
# Add requirements of Manual Controls
|
||||
for framework in bulk_compliance_frameworks.values():
|
||||
for requirement in framework.Requirements:
|
||||
compliance_requirements = []
|
||||
# Verify if requirement is Manual
|
||||
if not requirement.Checks:
|
||||
compliance_requirements.append(requirement)
|
||||
# Create the Compliance_Model
|
||||
compliance = ComplianceBaseModel(
|
||||
Framework=framework.Framework,
|
||||
Provider=framework.Provider,
|
||||
Version=framework.Version,
|
||||
Description=framework.Description,
|
||||
Requirements=compliance_requirements,
|
||||
)
|
||||
# Include the compliance framework for the check
|
||||
check_compliance.append(compliance)
|
||||
# Create metadata for Manual Control
|
||||
manual_check_metadata = {
|
||||
"Provider": framework.Provider.lower(),
|
||||
"CheckID": "manual_check",
|
||||
"CheckTitle": "Manual Check",
|
||||
"CheckType": [],
|
||||
"ServiceName": "",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "",
|
||||
"Description": "",
|
||||
"Risk": "",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
"Code": {"CLI": "", "NativeIaC": "", "Other": "", "Terraform": ""},
|
||||
"Recommendation": {"Text": "", "Url": ""},
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "",
|
||||
}
|
||||
manual_check = parse_obj_as(Check_Metadata_Model, manual_check_metadata)
|
||||
# Save it into the check's metadata
|
||||
bulk_checks_metadata["manual_check"] = manual_check
|
||||
bulk_checks_metadata["manual_check"].Compliance = check_compliance
|
||||
|
||||
return bulk_checks_metadata
|
||||
except Exception as e:
|
||||
logger.critical(f"{e.__class__.__name__}[{e.__traceback__.tb_lineno}] -- {e}")
|
||||
|
||||
@@ -70,6 +70,35 @@ class AWSWellArchitected(ComplianceOutput):
|
||||
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 = AWSWellArchitectedModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Name=attribute.Name,
|
||||
Requirements_Attributes_WellArchitectedQuestionId=attribute.WellArchitectedQuestionId,
|
||||
Requirements_Attributes_WellArchitectedPracticeId=attribute.WellArchitectedPracticeId,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_LevelOfRisk=attribute.LevelOfRisk,
|
||||
Requirements_Attributes_AssessmentMethod=attribute.AssessmentMethod,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_ImplementationGuidanceUrl=attribute.ImplementationGuidanceUrl,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -69,6 +69,36 @@ class AWSCIS(ComplianceOutput):
|
||||
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 = CISAWS(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -70,6 +70,37 @@ class AzureCIS(ComplianceOutput):
|
||||
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 = CISAzure(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
Subscription="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_DefaultValue=attribute.DefaultValue,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
try:
|
||||
|
||||
@@ -69,6 +69,36 @@ class GCPCIS(ComplianceOutput):
|
||||
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 = CISGCP(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
ProjectId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
try:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from csv import DictWriter
|
||||
from datetime import datetime
|
||||
from venv import logger
|
||||
|
||||
from prowler.lib.check.compliance_models import ComplianceBaseModel
|
||||
@@ -70,6 +71,37 @@ class KubernetesCIS(ComplianceOutput):
|
||||
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 = CISKubernetes(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
Context="",
|
||||
Namespace="",
|
||||
AssessmentDate=str(datetime.now()),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Requirements_Attributes_DefaultValue=attribute.DefaultValue,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
try:
|
||||
|
||||
@@ -12,102 +12,6 @@ from prowler.lib.outputs.compliance.mitre_attack.mitre_attack import (
|
||||
)
|
||||
|
||||
|
||||
def add_manual_controls(
|
||||
output_options, provider, file_descriptors, input_compliance_frameworks
|
||||
):
|
||||
try:
|
||||
# Check if MANUAL control was already added to output
|
||||
if "manual_check" in output_options.bulk_checks_metadata:
|
||||
manual_finding = Check_Report(
|
||||
output_options.bulk_checks_metadata["manual_check"].json()
|
||||
)
|
||||
manual_finding.status = "MANUAL"
|
||||
manual_finding.status_extended = "Manual check"
|
||||
manual_finding.resource_id = "manual_check"
|
||||
manual_finding.resource_name = "Manual check"
|
||||
manual_finding.region = ""
|
||||
manual_finding.location = ""
|
||||
manual_finding.project_id = ""
|
||||
manual_finding.subscription = ""
|
||||
manual_finding.namespace = ""
|
||||
fill_compliance(
|
||||
output_options,
|
||||
manual_finding,
|
||||
provider,
|
||||
file_descriptors,
|
||||
input_compliance_frameworks,
|
||||
)
|
||||
del output_options.bulk_checks_metadata["manual_check"]
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
def get_check_compliance_frameworks_in_input(
|
||||
check_id, bulk_checks_metadata, input_compliance_frameworks
|
||||
):
|
||||
"""get_check_compliance_frameworks_in_input returns a list of Compliance for the given check if the compliance framework is present in the input compliance to execute"""
|
||||
check_compliances = []
|
||||
try:
|
||||
if bulk_checks_metadata and bulk_checks_metadata.get(check_id):
|
||||
for compliance in bulk_checks_metadata[check_id].Compliance:
|
||||
compliance_name = ""
|
||||
if compliance.Version:
|
||||
compliance_name = (
|
||||
compliance.Framework.lower()
|
||||
+ "_"
|
||||
+ compliance.Version.lower()
|
||||
+ "_"
|
||||
+ compliance.Provider.lower()
|
||||
)
|
||||
else:
|
||||
compliance_name = (
|
||||
compliance.Framework.lower() + "_" + compliance.Provider.lower()
|
||||
)
|
||||
if compliance_name.replace("-", "_") in input_compliance_frameworks:
|
||||
check_compliances.append(compliance)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return check_compliances
|
||||
|
||||
|
||||
def fill_compliance(
|
||||
output_options, finding, provider, file_descriptors, input_compliance_frameworks
|
||||
):
|
||||
try:
|
||||
# We have to retrieve all the check's compliance requirements and get the ones matching with the input ones
|
||||
check_compliances = get_check_compliance_frameworks_in_input(
|
||||
finding.check_metadata.CheckID,
|
||||
output_options.bulk_checks_metadata,
|
||||
input_compliance_frameworks,
|
||||
)
|
||||
|
||||
for compliance in check_compliances:
|
||||
# FIXME: Remove this once we merge all the compliance frameworks
|
||||
if compliance.Framework == "CIS":
|
||||
continue
|
||||
elif compliance.Framework == "MITRE-ATTACK" and compliance.Version == "":
|
||||
continue
|
||||
elif compliance.Framework == "ENS":
|
||||
continue
|
||||
elif "AWS-Well-Architected-Framework" in compliance.Framework:
|
||||
continue
|
||||
elif (
|
||||
compliance.Framework == "ISO27001"
|
||||
and compliance.Version == "2013"
|
||||
and compliance.Provider == "AWS"
|
||||
):
|
||||
continue
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
def display_compliance_table(
|
||||
findings: list,
|
||||
bulk_checks_metadata: dict,
|
||||
@@ -115,7 +19,21 @@ def display_compliance_table(
|
||||
output_filename: str,
|
||||
output_directory: str,
|
||||
compliance_overview: bool,
|
||||
):
|
||||
) -> None:
|
||||
"""
|
||||
display_compliance_table generates the compliance table for the given compliance framework.
|
||||
|
||||
Args:
|
||||
findings (list): The list of findings
|
||||
bulk_checks_metadata (dict): The bulk checks metadata
|
||||
compliance_framework (str): The compliance framework to generate the table
|
||||
output_filename (str): The output filename
|
||||
output_directory (str): The output directory
|
||||
compliance_overview (bool): The compliance
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
try:
|
||||
if "ens_" in compliance_framework:
|
||||
get_ens_table(
|
||||
@@ -161,7 +79,9 @@ def display_compliance_table(
|
||||
|
||||
|
||||
# TODO: this should be in the Check class
|
||||
def get_check_compliance(finding, provider_type, output_options) -> dict:
|
||||
def get_check_compliance(
|
||||
finding: Check_Report, provider_type: str, bulk_checks_metadata: dict
|
||||
) -> dict:
|
||||
"""get_check_compliance returns a map with the compliance framework as key and the requirements where the finding's check is present.
|
||||
|
||||
Example:
|
||||
@@ -170,12 +90,20 @@ def get_check_compliance(finding, provider_type, output_options) -> dict:
|
||||
"CIS-1.4": ["2.1.3"],
|
||||
"CIS-1.5": ["2.1.3"],
|
||||
}
|
||||
|
||||
Args:
|
||||
finding (Any): The Check_Report finding
|
||||
provider_type (str): The provider type
|
||||
bulk_checks_metadata (dict): The bulk checks metadata
|
||||
|
||||
Returns:
|
||||
dict: The compliance framework as key and the requirements where the finding's check is present.
|
||||
"""
|
||||
try:
|
||||
check_compliance = {}
|
||||
# We have to retrieve all the check's compliance requirements
|
||||
if finding.check_metadata.CheckID in output_options.bulk_checks_metadata:
|
||||
for compliance in output_options.bulk_checks_metadata[
|
||||
if finding.check_metadata.CheckID in bulk_checks_metadata:
|
||||
for compliance in bulk_checks_metadata[
|
||||
finding.check_metadata.CheckID
|
||||
].Compliance:
|
||||
compliance_fw = compliance.Framework
|
||||
|
||||
@@ -67,11 +67,44 @@ class AWSENS(ComplianceOutput):
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
ResourceName=finding.resource_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 = ENSAWS(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl,
|
||||
Requirements_Attributes_Marco=attribute.Marco,
|
||||
Requirements_Attributes_Categoria=attribute.Categoria,
|
||||
Requirements_Attributes_DescripcionControl=attribute.DescripcionControl,
|
||||
Requirements_Attributes_Nivel=attribute.Nivel,
|
||||
Requirements_Attributes_Tipo=attribute.Tipo,
|
||||
Requirements_Attributes_Dimensiones=",".join(
|
||||
attribute.Dimensiones
|
||||
),
|
||||
Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion,
|
||||
Requirements_Attributes_Dependencias=",".join(
|
||||
attribute.Dependencias
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -59,11 +59,36 @@ class GenericCompliance(ComplianceOutput):
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
ResourceName=finding.resource_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 = Generic(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_SubGroup=attribute.SubGroup,
|
||||
Requirements_Attributes_Service=attribute.Service,
|
||||
Requirements_Attributes_Type=attribute.Type,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -61,6 +61,28 @@ class AWSISO27001(ComplianceOutput):
|
||||
ResourceName=finding.resource_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 = ISO27001AWS(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Attributes_Category=attribute.Category,
|
||||
Requirements_Attributes_Objetive_ID=attribute.Objetive_ID,
|
||||
Requirements_Attributes_Objetive_Name=attribute.Objetive_Name,
|
||||
Requirements_Attributes_Check_Summary=attribute.Check_Summary,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -78,6 +78,45 @@ class AWSMitreAttack(ComplianceOutput):
|
||||
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 = MitreAttackAWS(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Name=requirement.Name,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Tactics=unroll_list(requirement.Tactics),
|
||||
Requirements_SubTechniques=unroll_list(
|
||||
requirement.SubTechniques
|
||||
),
|
||||
Requirements_Platforms=unroll_list(requirement.Platforms),
|
||||
Requirements_TechniqueURL=requirement.TechniqueURL,
|
||||
Requirements_Attributes_Services=", ".join(
|
||||
attribute.AWSService for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Categories=", ".join(
|
||||
attribute.Category for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Values=", ".join(
|
||||
attribute.Value for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Comments=", ".join(
|
||||
attribute.Comment for attribute in requirement.Attributes
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -79,6 +79,46 @@ class AzureMitreAttack(ComplianceOutput):
|
||||
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 = MitreAttackAzure(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
SubscriptionId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Name=requirement.Name,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Tactics=unroll_list(requirement.Tactics),
|
||||
Requirements_SubTechniques=unroll_list(
|
||||
requirement.SubTechniques
|
||||
),
|
||||
Requirements_Platforms=unroll_list(requirement.Platforms),
|
||||
Requirements_TechniqueURL=requirement.TechniqueURL,
|
||||
Requirements_Attributes_Services=", ".join(
|
||||
attribute.AzureService
|
||||
for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Categories=", ".join(
|
||||
attribute.Category for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Values=", ".join(
|
||||
attribute.Value for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Comments=", ".join(
|
||||
attribute.Comment for attribute in requirement.Attributes
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -78,6 +78,45 @@ class GCPMitreAttack(ComplianceOutput):
|
||||
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 = MitreAttackGCP(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
ProjectId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Name=requirement.Name,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Tactics=unroll_list(requirement.Tactics),
|
||||
Requirements_SubTechniques=unroll_list(
|
||||
requirement.SubTechniques
|
||||
),
|
||||
Requirements_Platforms=unroll_list(requirement.Platforms),
|
||||
Requirements_TechniqueURL=requirement.TechniqueURL,
|
||||
Requirements_Attributes_Services=", ".join(
|
||||
attribute.GCPService for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Categories=", ".join(
|
||||
attribute.Category for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Values=", ".join(
|
||||
attribute.Value for attribute in requirement.Attributes
|
||||
),
|
||||
Requirements_Attributes_Comments=", ".join(
|
||||
attribute.Comment for attribute in requirement.Attributes
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
|
||||
def batch_write_data_to_file(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -5,12 +5,14 @@ from typing import Optional, Union
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.config.config import prowler_version
|
||||
from prowler.lib.check.models import Check_Report
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.outputs.common import (
|
||||
fill_common_finding_data,
|
||||
get_provider_data_mapping,
|
||||
)
|
||||
from prowler.lib.outputs.compliance.compliance import get_check_compliance
|
||||
from prowler.providers.common.provider import Provider
|
||||
|
||||
|
||||
class Status(str, Enum):
|
||||
@@ -85,13 +87,14 @@ class Finding(BaseModel):
|
||||
prowler_version: str = prowler_version
|
||||
|
||||
@classmethod
|
||||
def generate_output(cls, provider, check_output) -> "Finding":
|
||||
def generate_output(
|
||||
cls, provider: Provider, check_output: Check_Report
|
||||
) -> "Finding":
|
||||
"""Generates the output for a finding based on the provider and output options
|
||||
|
||||
Args:
|
||||
provider (Provider): the provider object
|
||||
finding (Finding): the finding object
|
||||
|
||||
check_output (Check_Report): the check output object
|
||||
Returns:
|
||||
finding_output (Finding): the finding output object
|
||||
|
||||
@@ -107,7 +110,7 @@ class Finding(BaseModel):
|
||||
output_data.update(provider_data_mapping)
|
||||
output_data.update(common_finding_data)
|
||||
output_data["compliance"] = get_check_compliance(
|
||||
check_output, provider.type, output_options
|
||||
check_output, provider.type, output_options.bulk_checks_metadata
|
||||
)
|
||||
try:
|
||||
if provider.type == "aws":
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from colorama import Fore, Style
|
||||
|
||||
from prowler.config.config import available_compliance_frameworks, orange_color
|
||||
from prowler.config.config import orange_color
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.outputs.compliance.compliance import (
|
||||
add_manual_controls,
|
||||
fill_compliance,
|
||||
)
|
||||
|
||||
|
||||
def stdout_report(finding, color, verbose, status, fix):
|
||||
@@ -52,33 +48,6 @@ def report(check_findings, provider):
|
||||
output_options.fixer,
|
||||
)
|
||||
|
||||
if file_descriptors:
|
||||
# Check if --status is enabled and if the filter applies
|
||||
if (
|
||||
not output_options.status
|
||||
or finding.status in output_options.status
|
||||
):
|
||||
input_compliance_frameworks = list(
|
||||
set(output_options.output_modes).intersection(
|
||||
available_compliance_frameworks
|
||||
)
|
||||
)
|
||||
|
||||
add_manual_controls(
|
||||
output_options,
|
||||
provider,
|
||||
file_descriptors,
|
||||
input_compliance_frameworks,
|
||||
)
|
||||
|
||||
fill_compliance(
|
||||
output_options,
|
||||
finding,
|
||||
provider,
|
||||
file_descriptors,
|
||||
input_compliance_frameworks,
|
||||
)
|
||||
|
||||
else: # No service resources in the whole account
|
||||
color = set_report_color("MANUAL")
|
||||
if output_options.verbose:
|
||||
|
||||
@@ -137,37 +137,9 @@ class TestCompliance:
|
||||
|
||||
assert "check1" in updated_metadata
|
||||
assert "check2" in updated_metadata
|
||||
assert "manual_check" in updated_metadata
|
||||
|
||||
manual_compliance = updated_metadata["manual_check"].Compliance[0]
|
||||
check1_compliance = updated_metadata["check1"].Compliance[0]
|
||||
|
||||
assert len(updated_metadata["manual_check"].Compliance) == 1
|
||||
assert len(updated_metadata["check1"].Compliance) == 1
|
||||
|
||||
assert manual_compliance.Framework == "Framework1"
|
||||
assert manual_compliance.Provider == "Provider1"
|
||||
assert manual_compliance.Version == "1.0"
|
||||
assert manual_compliance.Description == "Framework 1 Description"
|
||||
assert len(manual_compliance.Requirements) == 1
|
||||
|
||||
manual_requirement = manual_compliance.Requirements[0]
|
||||
assert manual_requirement.Id == "1.1.2"
|
||||
assert manual_requirement.Description == "description"
|
||||
assert len(manual_requirement.Attributes) == 1
|
||||
|
||||
manual_attribute = manual_requirement.Attributes[0]
|
||||
assert manual_attribute.Section == "1. Identity"
|
||||
assert manual_attribute.Profile == "Level 1"
|
||||
assert manual_attribute.AssessmentStatus == "Manual"
|
||||
assert manual_attribute.Description == "Description"
|
||||
assert manual_attribute.RationaleStatement == "Rationale"
|
||||
assert manual_attribute.ImpactStatement == "Impact"
|
||||
assert manual_attribute.RemediationProcedure == "Remediation"
|
||||
assert manual_attribute.AuditProcedure == "Audit"
|
||||
assert manual_attribute.AdditionalInformation == "Additional"
|
||||
assert manual_attribute.References == "References"
|
||||
|
||||
assert len(updated_metadata["check1"].Compliance) == 1
|
||||
assert check1_compliance.Framework == "Framework1"
|
||||
assert check1_compliance.Provider == "Provider1"
|
||||
|
||||
@@ -84,6 +84,67 @@ class TestAWSWellArchitected:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "aws"
|
||||
assert output_data_manual.AccountId == ""
|
||||
assert output_data_manual.Region == ""
|
||||
assert (
|
||||
output_data_manual.Requirements_Id
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Id
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Name
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].Name
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_WellArchitectedQuestionId
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1]
|
||||
.Attributes[0]
|
||||
.WellArchitectedQuestionId
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_WellArchitectedPracticeId
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1]
|
||||
.Attributes[0]
|
||||
.WellArchitectedPracticeId
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Section
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].Section
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_SubSection
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].SubSection
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_LevelOfRisk
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].LevelOfRisk
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AssessmentMethod
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].AssessmentMethod
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Description
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1].Attributes[0].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_ImplementationGuidanceUrl
|
||||
== AWS_WELL_ARCHITECTED.Requirements[1]
|
||||
.Attributes[0]
|
||||
.ImplementationGuidanceUrl
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -103,5 +164,5 @@ class TestAWSWellArchitected:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"""PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_NAME;REQUIREMENTS_ATTRIBUTES_WELLARCHITECTEDQUESTIONID;REQUIREMENTS_ATTRIBUTES_WELLARCHITECTEDPRACTICEID;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_SUBSECTION;REQUIREMENTS_ATTRIBUTES_LEVELOFRISK;REQUIREMENTS_ATTRIBUTES_ASSESSMENTMETHOD;REQUIREMENTS_ATTRIBUTES_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IMPLEMENTATIONGUIDANCEURL;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;Best Practices for AWS Well-Architected Framework Security Pillar. The focus of this framework is the security pillar of the AWS Well-Architected Framework. It provides guidance to help you apply best practices, current recommendations in the design, delivery, and maintenance of secure AWS workloads.;123456789012;eu-west-1;{datetime.now()};SEC01-BP01;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;SEC01-BP01 Separate workloads using accounts;securely-operate;sec_securely_operate_multi_accounts;Security foundations;AWS account management and separation;High;Automated;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_securely_operate_multi_accounts.html#implementation-guidance.;PASS;;;test-check-id;False;\r\n"""
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_NAME;REQUIREMENTS_ATTRIBUTES_WELLARCHITECTEDQUESTIONID;REQUIREMENTS_ATTRIBUTES_WELLARCHITECTEDPRACTICEID;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_SUBSECTION;REQUIREMENTS_ATTRIBUTES_LEVELOFRISK;REQUIREMENTS_ATTRIBUTES_ASSESSMENTMETHOD;REQUIREMENTS_ATTRIBUTES_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IMPLEMENTATIONGUIDANCEURL;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;Best Practices for AWS Well-Architected Framework Security Pillar. The focus of this framework is the security pillar of the AWS Well-Architected Framework. It provides guidance to help you apply best practices, current recommendations in the design, delivery, and maintenance of secure AWS workloads.;123456789012;eu-west-1;{datetime.now()};SEC01-BP01;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;SEC01-BP01 Separate workloads using accounts;securely-operate;sec_securely_operate_multi_accounts;Security foundations;AWS account management and separation;High;Automated;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_securely_operate_multi_accounts.html#implementation-guidance.;PASS;;;test-check-id;False;\r\naws;Best Practices for AWS Well-Architected Framework Security Pillar. The focus of this framework is the security pillar of the AWS Well-Architected Framework. It provides guidance to help you apply best practices, current recommendations in the design, delivery, and maintenance of secure AWS workloads.;;;{datetime.now()};SEC01-BP02;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;SEC01-BP01 Separate workloads using accounts;securely-operate;sec_securely_operate_multi_accounts;Security foundations;AWS account management and separation;High;Automated;Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.;https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_securely_operate_multi_accounts.html#implementation-guidance.;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -88,6 +88,69 @@ class TestKubernetesCIS:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "kubernetes"
|
||||
assert output_data_manual.Context == ""
|
||||
assert output_data_manual.Namespace == ""
|
||||
assert output_data_manual.Description == CIS_1_8_KUBERNETES.Description
|
||||
assert (
|
||||
output_data_manual.Requirements_Id == CIS_1_8_KUBERNETES.Requirements[1].Id
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Section
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].Section
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Profile
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].Profile
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AssessmentStatus
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].AssessmentStatus
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Description
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_RationaleStatement
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].RationaleStatement
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_ImpactStatement
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].ImpactStatement
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_RemediationProcedure
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].RemediationProcedure
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AuditProcedure
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].AuditProcedure
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AdditionalInformation
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].AdditionalInformation
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_References
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].References
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_DefaultValue
|
||||
== CIS_1_8_KUBERNETES.Requirements[1].Attributes[0].DefaultValue
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -110,5 +173,5 @@ class TestKubernetesCIS:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;CONTEXT;NAMESPACE;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_PROFILE;REQUIREMENTS_ATTRIBUTES_ASSESSMENTSTATUS;REQUIREMENTS_ATTRIBUTES_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_RATIONALESTATEMENT;REQUIREMENTS_ATTRIBUTES_IMPACTSTATEMENT;REQUIREMENTS_ATTRIBUTES_REMEDIATIONPROCEDURE;REQUIREMENTS_ATTRIBUTES_AUDITPROCEDURE;REQUIREMENTS_ATTRIBUTES_ADDITIONALINFORMATION;REQUIREMENTS_ATTRIBUTES_REFERENCES;REQUIREMENTS_ATTRIBUTES_DEFAULTVALUE;STATUS;STATUSEXTENDED;RESOURCEID;RESOURCENAME;CHECKID;MUTED\r\nkubernetes;This CIS Kubernetes Benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.27.;test-cluster;test-namespace;{datetime.now()};1.1.3;Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive;1.1 Control Plane Node Configuration Files;Level 1 - Master Node;Automated;Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.;The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.;;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.;;https://kubernetes.io/docs/admin/kube-apiserver/;By default, the `kube-controller-manager.yaml` file has permissions of `640`.;PASS;;;;test-check-id;False\r\n"
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;CONTEXT;NAMESPACE;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_PROFILE;REQUIREMENTS_ATTRIBUTES_ASSESSMENTSTATUS;REQUIREMENTS_ATTRIBUTES_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_RATIONALESTATEMENT;REQUIREMENTS_ATTRIBUTES_IMPACTSTATEMENT;REQUIREMENTS_ATTRIBUTES_REMEDIATIONPROCEDURE;REQUIREMENTS_ATTRIBUTES_AUDITPROCEDURE;REQUIREMENTS_ATTRIBUTES_ADDITIONALINFORMATION;REQUIREMENTS_ATTRIBUTES_REFERENCES;REQUIREMENTS_ATTRIBUTES_DEFAULTVALUE;STATUS;STATUSEXTENDED;RESOURCEID;RESOURCENAME;CHECKID;MUTED\r\nkubernetes;This CIS Kubernetes Benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.27.;test-cluster;test-namespace;{datetime.now()};1.1.3;Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive;1.1 Control Plane Node Configuration Files;Level 1 - Master Node;Automated;Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.;The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.;;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.;;https://kubernetes.io/docs/admin/kube-apiserver/;By default, the `kube-controller-manager.yaml` file has permissions of `640`.;PASS;;;;test-check-id;False\r\nkubernetes;This CIS Kubernetes Benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.27.;;;{datetime.now()};1.1.4;Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive;1.1 Control Plane Node Configuration Files;Level 1 - Master Node;Automated;Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.;The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.;;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.;;https://kubernetes.io/docs/admin/kube-apiserver/;By default, the `kube-controller-manager.yaml` file has permissions of `640`.;MANUAL;Manual check;manual_check;Manual check;manual;False\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -1,47 +1,329 @@
|
||||
from mock import MagicMock
|
||||
from os import path
|
||||
from unittest import mock
|
||||
|
||||
from prowler.lib.outputs.compliance.compliance import (
|
||||
get_check_compliance_frameworks_in_input,
|
||||
)
|
||||
from tests.lib.outputs.compliance.fixtures import (
|
||||
CIS_1_4_AWS,
|
||||
CIS_1_4_AWS_NAME,
|
||||
CIS_1_5_AWS,
|
||||
CIS_1_5_AWS_NAME,
|
||||
NOT_PRESENT_COMPLIANCE,
|
||||
from prowler.lib.check.compliance_models import (
|
||||
CIS_Requirement_Attribute,
|
||||
Compliance_Requirement,
|
||||
ComplianceBaseModel,
|
||||
)
|
||||
from prowler.lib.check.models import Check_Report, load_check_metadata
|
||||
from prowler.lib.outputs.compliance.compliance import get_check_compliance
|
||||
|
||||
|
||||
class TestCompliance:
|
||||
def test_get_check_compliance_frameworks_all_none(self):
|
||||
check_id = None
|
||||
bulk_checks_metadata = None
|
||||
input_compliance_frameworks = None
|
||||
assert (
|
||||
get_check_compliance_frameworks_in_input(
|
||||
check_id, bulk_checks_metadata, input_compliance_frameworks
|
||||
)
|
||||
== []
|
||||
def test_get_check_compliance_aws(self):
|
||||
check_compliance = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="AWS",
|
||||
Version="1.4",
|
||||
Description="The CIS Benchmark for CIS Amazon Web Services Foundations Benchmark, v1.4.0, Level 1 and 2 provides prescriptive guidance for configuring security options for a subset of Amazon Web Services. It has an emphasis on foundational, testable, and architecture agnostic settings",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.\n\nNote:\n-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.\n-You must use your 'root' account to enable MFA Delete on S3 buckets.\n\n**From Command line:**\n\n1. Run the s3api put-bucket-versioning command\n\n```\naws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa “arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode”\n```",
|
||||
AuditProcedure='Perform the steps below to confirm MFA delete is configured on an S3 Bucket\n\n**From Console:**\n\n1. Login to the S3 console at `https://console.aws.amazon.com/s3/`\n\n2. Click the `Check` box next to the Bucket name you want to confirm\n\n3. In the window under `Properties`\n\n4. Confirm that Versioning is `Enabled`\n\n5. Confirm that MFA Delete is `Enabled`\n\n**From Command Line:**\n\n1. Run the `get-bucket-versioning`\n```\naws s3api get-bucket-versioning --bucket my-bucket\n```\n\nOutput example:\n```\n<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> \n <Status>Enabled</Status>\n <MfaDelete>Enabled</MfaDelete> \n</VersioningConfiguration>\n```\n\nIf the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.',
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="AWS",
|
||||
Version="1.5",
|
||||
Description="The CIS Amazon Web Services Foundations Benchmark provides prescriptive guidance for configuring security options for a subset of Amazon Web Services with an emphasis on foundational, testable, and architecture agnostic settings.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.\n\nNote:\n-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.\n-You must use your 'root' account to enable MFA Delete on S3 buckets.\n\n**From Command line:**\n\n1. Run the s3api put-bucket-versioning command\n\n```\naws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa “arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode”\n```",
|
||||
AuditProcedure='Perform the steps below to confirm MFA delete is configured on an S3 Bucket\n\n**From Console:**\n\n1. Login to the S3 console at `https://console.aws.amazon.com/s3/`\n\n2. Click the `Check` box next to the Bucket name you want to confirm\n\n3. In the window under `Properties`\n\n4. Confirm that Versioning is `Enabled`\n\n5. Confirm that MFA Delete is `Enabled`\n\n**From Command Line:**\n\n1. Run the `get-bucket-versioning`\n```\naws s3api get-bucket-versioning --bucket my-bucket\n```\n\nOutput example:\n```\n<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> \n <Status>Enabled</Status>\n <MfaDelete>Enabled</MfaDelete> \n</VersioningConfiguration>\n```\n\nIf the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.',
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/../fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
def test_get_check_compliance_frameworks_all(self):
|
||||
check_id = "test-check"
|
||||
bulk_check_metadata = [CIS_1_4_AWS, CIS_1_5_AWS]
|
||||
bulk_checks_metadata = {}
|
||||
bulk_checks_metadata[check_id] = MagicMock()
|
||||
bulk_checks_metadata[check_id].Compliance = bulk_check_metadata
|
||||
input_compliance_frameworks = [CIS_1_4_AWS_NAME, CIS_1_5_AWS_NAME]
|
||||
assert get_check_compliance_frameworks_in_input(
|
||||
check_id, bulk_checks_metadata, input_compliance_frameworks
|
||||
) == [CIS_1_4_AWS, CIS_1_5_AWS]
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"] = mock.MagicMock()
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = check_compliance
|
||||
|
||||
assert get_check_compliance(finding, "aws", bulk_checks_metadata) == {
|
||||
"CIS-1.4": ["2.1.3"],
|
||||
"CIS-1.5": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_gcp(self):
|
||||
check_compliance = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="GCP",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Google Cloud Computing Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="GCP",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Google Cloud Computing Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/../fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
def test_get_check_compliance_frameworks_two_of_three(self):
|
||||
check_id = "test-check"
|
||||
bulk_check_metadata = [CIS_1_4_AWS, CIS_1_5_AWS, NOT_PRESENT_COMPLIANCE]
|
||||
bulk_checks_metadata = {}
|
||||
bulk_checks_metadata[check_id] = MagicMock()
|
||||
bulk_checks_metadata[check_id].Compliance = bulk_check_metadata
|
||||
input_compliance_frameworks = [CIS_1_4_AWS_NAME, CIS_1_5_AWS_NAME]
|
||||
assert get_check_compliance_frameworks_in_input(
|
||||
check_id, bulk_checks_metadata, input_compliance_frameworks
|
||||
) == [CIS_1_4_AWS, CIS_1_5_AWS]
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"] = mock.MagicMock()
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = check_compliance
|
||||
|
||||
assert get_check_compliance(finding, "gcp", bulk_checks_metadata) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_azure(self):
|
||||
check_compliance = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Azure",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Azuee Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Azure",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Azure Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/../fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
bulk_checks_metadata = {}
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"] = mock.MagicMock()
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = check_compliance
|
||||
|
||||
assert get_check_compliance(finding, "azure", bulk_checks_metadata) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_kubernetes(self):
|
||||
check_compliance = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Kubernetes",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Kubernetes Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Kubernetes",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Kubernetes Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/../fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
print(finding)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
bulk_checks_metadata = {}
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"] = mock.MagicMock()
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = check_compliance
|
||||
|
||||
assert get_check_compliance(finding, "kubernetes", bulk_checks_metadata) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
@@ -67,6 +67,53 @@ class TestAWSENS:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "aws"
|
||||
assert output_data_manual.AccountId == ""
|
||||
assert output_data_manual.Region == ""
|
||||
assert output_data_manual.Requirements_Id == ENS_RD2022_AWS.Requirements[1].Id
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== ENS_RD2022_AWS.Requirements[1].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_IdGrupoControl
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].IdGrupoControl
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Marco
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].Marco
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Categoria
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].Categoria
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_DescripcionControl
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].DescripcionControl
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Nivel
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].Nivel
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Tipo
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].Tipo
|
||||
)
|
||||
assert [
|
||||
output_data_manual.Requirements_Attributes_Dimensiones
|
||||
] == ENS_RD2022_AWS.Requirements[1].Attributes[0].Dimensiones
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_ModoEjecucion
|
||||
== ENS_RD2022_AWS.Requirements[1].Attributes[0].ModoEjecucion
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -82,5 +129,5 @@ class TestAWSENS:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"""PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;eu-west-1;{datetime.now()};op.exp.8.aws.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;test-check-id;False;\r\n"""
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;eu-west-1;{datetime.now()};op.exp.8.aws.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;test-check-id;False;\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.aws.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -22,7 +22,7 @@ CIS_1_4_AWS = ComplianceBaseModel(
|
||||
Description="The CIS Benchmark for CIS Amazon Web Services Foundations Benchmark, v1.4.0, Level 1 and 2 provides prescriptive guidance for configuring security options for a subset of Amazon Web Services. It has an emphasis on foundational, testable, and architecture agnostic settings",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Checks=["test-check-id"],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
@@ -39,7 +39,26 @@ CIS_1_4_AWS = ComplianceBaseModel(
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.4",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.\n\nNote:\n-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.\n-You must use your 'root' account to enable MFA Delete on S3 buckets.\n\n**From Command line:**\n\n1. Run the s3api put-bucket-versioning command\n\n```\naws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa “arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode”\n```",
|
||||
AuditProcedure='Perform the steps below to confirm MFA delete is configured on an S3 Bucket\n\n**From Console:**\n\n1. Login to the S3 console at `https://console.aws.amazon.com/s3/`\n\n2. Click the `Check` box next to the Bucket name you want to confirm\n\n3. In the window under `Properties`\n\n4. Confirm that Versioning is `Enabled`\n\n5. Confirm that MFA Delete is `Enabled`\n\n**From Command Line:**\n\n1. Run the `get-bucket-versioning`\n```\naws s3api get-bucket-versioning --bucket my-bucket\n```\n\nOutput example:\n```\n<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> \n <Status>Enabled</Status>\n <MfaDelete>Enabled</MfaDelete> \n</VersioningConfiguration>\n```\n\nIf the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.',
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
CIS_2_0_AZURE_NAME = "cis_2.0_azure"
|
||||
@@ -50,7 +69,7 @@ CIS_2_0_AZURE = ComplianceBaseModel(
|
||||
Description="The CIS Azure Foundations Benchmark provides prescriptive guidance for configuring security options for a subset of Azure with an emphasis on foundational, testable, and architecture agnostic settings.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Checks=["test-check-id"],
|
||||
Id="2.1.3",
|
||||
Description="Ensure That Microsoft Defender for Databases Is Set To 'On'",
|
||||
Attributes=[
|
||||
@@ -68,7 +87,27 @@ CIS_2_0_AZURE = ComplianceBaseModel(
|
||||
References="https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql?view=azuresql:https://docs.microsoft.com/en-us/azure/defender-for-cloud/quickstart-enable-database-protections:https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-databases-usage:https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities:https://docs.microsoft.com/en-us/rest/api/securitycenter/pricings/list:https://docs.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-logging-threat-detection#lt-1-enable-threat-detection-capabilities",
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.4",
|
||||
Description="Ensure That Microsoft Defender for Databases Is Set To 'On'",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1 Microsoft Defender for Cloud",
|
||||
Profile="Level 2",
|
||||
AssessmentStatus="Manual",
|
||||
Description="Turning on Microsoft Defender for Databases enables threat detection for the instances running your database software. This provides threat intelligence, anomaly detection, and behavior analytics in the Azure Microsoft Defender for Cloud. Instead of being enabled on services like Platform as a Service (PaaS), this implementation will run within your instances as Infrastructure as a Service (IaaS) on the Operating Systems hosting your databases.",
|
||||
RationaleStatement="Enabling Microsoft Defender for Azure SQL Databases allows your organization more granular control of the infrastructure running your database software. Instead of waiting on Microsoft release updates or other similar processes, you can manage them yourself. Threat detection is provided by the Microsoft Security Response Center (MSRC).",
|
||||
ImpactStatement="Running Defender on Infrastructure as a service (IaaS) may incur increased costs associated with running the service and the instance it is on. Similarly, you will need qualified personnel to maintain the operating system and software updates. If it is not maintained, security patches will not be applied and it may be open to vulnerabilities.",
|
||||
RemediationProcedure="From Azure Portal 1. Go to Microsoft Defender for Cloud 2. Select Environment Settings 3. Click on the subscription name 4. Select Defender plans 5. Set Databases Status to On 6. Select Save Review the chosen pricing tier. For the Azure Databases resource review the different plan information and choose one that fits the needs of your organization. From Azure CLI Run the following commands: az security pricing create -n 'SqlServers' --tier 'Standard' az security pricing create -n 'SqlServerVirtualMachines' --tier 'Standard' az security pricing create -n 'OpenSourceRelationalDatabases' --tier 'Standard' az security pricing create -n 'CosmosDbs' --tier 'Standard' From Azure PowerShell Run the following commands: Set-AzSecurityPricing -Name 'SqlServers' -PricingTier 'Standard' Set-AzSecurityPricing -Name 'SqlServerVirtualMachines' -PricingTier 'Standard' Set-AzSecurityPricing -Name 'OpenSourceRelationalDatabases' -PricingTier 'Standard' Set-AzSecurityPricing -Name 'CosmosDbs' -PricingTier 'Standard'",
|
||||
AuditProcedure="From Azure Portal 1. Go to Microsoft Defender for Cloud 2. Select Environment Settings 3. Click on the subscription name 4. Select Defender plans 5. Ensure Databases Status is set to On 6. Review the chosen pricing tier From Azure CLI Ensure the output of the below commands is Standard az security pricing show -n 'SqlServers' az security pricing show -n 'SqlServerVirtualMachines' az security pricing show -n 'OpenSourceRelationalDatabases' az security pricing show -n 'CosmosDbs' If the output of any of the above commands shows pricingTier with a value of Free, the setting is out of compliance. From PowerShell Connect-AzAccount Get-AzSecurityPricing |select-object Name,PricingTier |where-object {$_.Name -match 'Sql' -or $_.Name -match 'Cosmos' -or $_.Name -match 'OpenSource'} Ensure the output shows Standard for each database type under the PricingTier column. Any that show Free are considered out of compliance.",
|
||||
AdditionalInformation="",
|
||||
DefaultValue="By default, Microsoft Defender plan is off.",
|
||||
References="https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql?view=azuresql:https://docs.microsoft.com/en-us/azure/defender-for-cloud/quickstart-enable-database-protections:https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-databases-usage:https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities:https://docs.microsoft.com/en-us/rest/api/securitycenter/pricings/list:https://docs.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-logging-threat-detection#lt-1-enable-threat-detection-capabilities",
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
CIS_2_0_GCP_NAME = "cis_2.0_gcp"
|
||||
@@ -79,7 +118,7 @@ CIS_2_0_GCP = ComplianceBaseModel(
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Google Cloud Computing Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Checks=["apikeys_key_exits"],
|
||||
Id="2.13",
|
||||
Description="Ensure That Microsoft Defender for Databases Is Set To 'On'",
|
||||
Attributes=[
|
||||
@@ -96,7 +135,26 @@ CIS_2_0_GCP = ComplianceBaseModel(
|
||||
References="https://cloud.google.com/asset-inventory/docs",
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.14",
|
||||
Description="Ensure That Microsoft Defender for Databases Is Set To 'On'",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2. Logging and Monitoring",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="GCP Cloud Asset Inventory is services that provides a historical view of GCP resources and IAM policies through a time-series database. The information recorded includes metadata on Google Cloud resources, metadata on policies set on Google Cloud projects or resources, and runtime information gathered within a Google Cloud resource.",
|
||||
RationaleStatement="The GCP resources and IAM policies captured by GCP Cloud Asset Inventory enables security analysis, resource change tracking, and compliance auditing. It is recommended GCP Cloud Asset Inventory be enabled for all GCP projects.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="**From Google Cloud Console** Enable the Cloud Asset API: 1. Go to `API & Services/Library` by visiting https://console.cloud.google.com/apis/library(https://console.cloud.google.com/apis/library) 2. Search for `Cloud Asset API` and select the result for _Cloud Asset API_ 3. Click the `ENABLE` button. **From Google Cloud CLI** Enable the Cloud Asset API: 1. Enable the Cloud Asset API through the services interface: ``` gcloud services enable cloudasset.googleapis.com ```",
|
||||
AuditProcedure="**From Google Cloud Console** Ensure that the Cloud Asset API is enabled: 1. Go to `API & Services/Library` by visiting https://console.cloud.google.com/apis/library(https://console.cloud.google.com/apis/library) 2. Search for `Cloud Asset API` and select the result for _Cloud Asset API_ 3. Ensure that `API Enabled` is displayed. **From Google Cloud CLI** Ensure that the Cloud Asset API is enabled: 1. Query enabled services: ``` gcloud services list --enabled --filter=name:cloudasset.googleapis.com ``` If the API is listed, then it is enabled. If the response is `Listed 0 items` the API is not enabled.",
|
||||
AdditionalInformation="Additional info - Cloud Asset Inventory only keeps a five-week history of Google Cloud asset metadata. If a longer history is desired, automation to export the history to Cloud Storage or BigQuery should be evaluated.",
|
||||
References="https://cloud.google.com/asset-inventory/docs",
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
CIS_1_8_KUBERNETES_NAME = "cis_2.0_kubernetes"
|
||||
@@ -107,7 +165,7 @@ CIS_1_8_KUBERNETES = ComplianceBaseModel(
|
||||
Description="This CIS Kubernetes Benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.27.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Checks=["apiserver_always_pull_images_plugin"],
|
||||
Id="1.1.3",
|
||||
Description="Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive",
|
||||
Attributes=[
|
||||
@@ -125,7 +183,27 @@ CIS_1_8_KUBERNETES = ComplianceBaseModel(
|
||||
DefaultValue="By default, the `kube-controller-manager.yaml` file has permissions of `640`.",
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="1.1.4",
|
||||
Description="Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="1.1 Control Plane Node Configuration Files",
|
||||
Profile="Level 1 - Master Node",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.",
|
||||
RationaleStatement="The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```",
|
||||
AuditProcedure="Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.",
|
||||
AdditionalInformation="",
|
||||
References="https://kubernetes.io/docs/admin/kube-apiserver/",
|
||||
DefaultValue="By default, the `kube-controller-manager.yaml` file has permissions of `640`.",
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
CIS_1_5_AWS_NAME = "cis_1.5_aws"
|
||||
@@ -193,7 +271,25 @@ MITRE_ATTACK_AWS = ComplianceBaseModel(
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"ec2_instance_public_ip",
|
||||
],
|
||||
)
|
||||
),
|
||||
Mitre_Requirement(
|
||||
Name="Exploit Public-Facing Application",
|
||||
Id="T1193",
|
||||
Tactics=["Initial Access"],
|
||||
SubTechniques=[],
|
||||
Description="Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.",
|
||||
Platforms=["Containers", "IaaS", "Linux", "Network", "Windows", "macOS"],
|
||||
TechniqueURL="https://attack.mitre.org/techniques/T1190/",
|
||||
Attributes=[
|
||||
Mitre_Requirement_Attribute_AWS(
|
||||
AWSService="AWS CloudEndure Disaster Recovery",
|
||||
Category="Respond",
|
||||
Value="Significant",
|
||||
Comment="AWS CloudEndure Disaster Recovery enables the replication and recovery of servers into AWS Cloud. In the event that a public-facing application or server is compromised, AWS CloudEndure can be used to provision an instance of the server from a previous point in time within minutes. As a result, this mapping is given a score of Significant.",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
MITRE_ATTACK_AZURE_NAME = "mitre_attack_azure"
|
||||
@@ -250,7 +346,25 @@ MITRE_ATTACK_AZURE = ComplianceBaseModel(
|
||||
"defender_ensure_system_updates_are_applied",
|
||||
"defender_ensure_wdatp_is_enabled",
|
||||
],
|
||||
)
|
||||
),
|
||||
Mitre_Requirement(
|
||||
Name="Exploit Public-Facing Application",
|
||||
Id="T1191",
|
||||
Tactics=["Initial Access"],
|
||||
SubTechniques=[],
|
||||
Description="Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.",
|
||||
Platforms=["Containers", "IaaS", "Linux", "Network", "Windows", "macOS"],
|
||||
TechniqueURL="https://attack.mitre.org/techniques/T1190/",
|
||||
Attributes=[
|
||||
Mitre_Requirement_Attribute_Azure(
|
||||
AzureService="Azure SQL Database",
|
||||
Category="Detect",
|
||||
Value="Minimal",
|
||||
Comment="This control may alert on usage of faulty SQL statements. This generates an alert for a possible SQL injection by an application. Alerts may not be generated on usage of valid SQL statements by attackers for malicious purposes.",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
MITRE_ATTACK_GCP_NAME = "mitre_attack_gcp"
|
||||
@@ -286,7 +400,25 @@ MITRE_ATTACK_GCP = ComplianceBaseModel(
|
||||
"compute_public_address_shodan",
|
||||
"kms_key_not_publicly_accessible",
|
||||
],
|
||||
)
|
||||
),
|
||||
Mitre_Requirement(
|
||||
Name="Exploit Public-Facing Application",
|
||||
Id="T1191",
|
||||
Tactics=["Initial Access"],
|
||||
SubTechniques=[],
|
||||
Description="Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.",
|
||||
Platforms=["Containers", "IaaS", "Linux", "Network", "Windows", "macOS"],
|
||||
TechniqueURL="https://attack.mitre.org/techniques/T1190/",
|
||||
Attributes=[
|
||||
Mitre_Requirement_Attribute_GCP(
|
||||
GCPService="Artifact Registry",
|
||||
Category="Protect",
|
||||
Value="Partial",
|
||||
Comment="Once this control is deployed, it can detect known vulnerabilities in various Linux OS packages. This information can be used to patch, isolate, or remove vulnerable software and machines. This control does not directly protect against exploitation and is not effective against zero day attacks, vulnerabilities with no available patch, and other end-of-life packages.",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
ENS_RD2022_AWS_NAME = "ens_rd2022_aws"
|
||||
@@ -314,7 +446,26 @@ ENS_RD2022_AWS = ComplianceBaseModel(
|
||||
)
|
||||
],
|
||||
Checks=["cloudtrail_log_file_validation_enabled"],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Id="op.exp.8.aws.ct.4",
|
||||
Description="Registro de actividad",
|
||||
Name=None,
|
||||
Attributes=[
|
||||
ENS_Requirement_Attribute(
|
||||
IdGrupoControl="op.exp.8",
|
||||
Marco="operacional",
|
||||
Categoria="explotación",
|
||||
DescripcionControl="Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.",
|
||||
Tipo=ENS_Requirement_Attribute_Tipos.requisito,
|
||||
Nivel=ENS_Requirement_Attribute_Nivel.alto,
|
||||
Dimensiones=["trazabilidad"],
|
||||
ModoEjecucion="automático",
|
||||
Dependencias=[],
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
NOT_PRESENT_COMPLIANCE_NAME = "not_present_compliance_name"
|
||||
@@ -351,6 +502,25 @@ AWS_WELL_ARCHITECTED = ComplianceBaseModel(
|
||||
],
|
||||
Checks=["organizations_account_part_of_organizations"],
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Id="SEC01-BP02",
|
||||
Description="Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.",
|
||||
Name=None,
|
||||
Attributes=[
|
||||
AWS_Well_Architected_Requirement_Attribute(
|
||||
Name="SEC01-BP01 Separate workloads using accounts",
|
||||
WellArchitectedQuestionId="securely-operate",
|
||||
WellArchitectedPracticeId="sec_securely_operate_multi_accounts",
|
||||
Section="Security foundations",
|
||||
SubSection="AWS account management and separation",
|
||||
LevelOfRisk="High",
|
||||
AssessmentMethod="Automated",
|
||||
Description="Establish common guardrails and isolation between environments (such as production, development, and test) and workloads through a multi-account strategy. Account-level separation is strongly recommended, as it provides a strong isolation boundary for security, billing, and access.",
|
||||
ImplementationGuidanceUrl="https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_securely_operate_multi_accounts.html#implementation-guidance.",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
AWISO27001_2013_AWS_NAME = "iso27001_2013_aws"
|
||||
@@ -397,6 +567,20 @@ ISO27001_2013_AWS = ComplianceBaseModel(
|
||||
],
|
||||
Checks=["rds_instance_storage_encrypted"],
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Id="A.10.2",
|
||||
Description="Setup Encryption at rest for RDS instances",
|
||||
Name="Cryptographic Controls",
|
||||
Attributes=[
|
||||
ISO27001_2013_Requirement_Attribute(
|
||||
Category="A.10 Cryptography",
|
||||
Objetive_ID="A.10.1",
|
||||
Objetive_Name="Cryptographic Controls",
|
||||
Check_Summary="Setup Encryption at rest for RDS instances",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
NIST_800_53_REVISION_4_AWS_NAME = "nist_800_53_revision_4_aws"
|
||||
@@ -431,6 +615,20 @@ NIST_800_53_REVISION_4_AWS = ComplianceBaseModel(
|
||||
"redshift_cluster_audit_logging",
|
||||
"securityhub_enabled",
|
||||
],
|
||||
)
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Id="ac_2_5",
|
||||
Description="Account Management",
|
||||
Name="The information system automatically audits account creation, modification, enabling, disabling, and removal actions, and notifies [Assignment: organization-defined personnel or roles].",
|
||||
Attributes=[
|
||||
Generic_Compliance_Requirement_Attribute(
|
||||
ItemId="ac_2_4",
|
||||
Section="Access Control (AC)",
|
||||
SubSection="Account Management (AC-2)",
|
||||
Service="aws",
|
||||
)
|
||||
],
|
||||
Checks=[],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -57,6 +57,46 @@ class TestAWSGenericCompliance:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "aws"
|
||||
assert output_data_manual.AccountId == ""
|
||||
assert output_data_manual.Region == ""
|
||||
assert output_data_manual.Description == NIST_800_53_REVISION_4_AWS.Description
|
||||
assert (
|
||||
output_data_manual.Requirements_Id
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Id
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Section
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Attributes[0].Section
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_SubSection
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Attributes[0].SubSection
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_SubGroup
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Attributes[0].SubGroup
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Service
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Attributes[0].Service
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Type
|
||||
== NIST_800_53_REVISION_4_AWS.Requirements[1].Attributes[0].Type
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -72,5 +112,5 @@ class TestAWSGenericCompliance:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"""PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_SUBSECTION;REQUIREMENTS_ATTRIBUTES_SUBGROUP;REQUIREMENTS_ATTRIBUTES_SERVICE;REQUIREMENTS_ATTRIBUTES_TYPE;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;NIST 800-53 is a regulatory standard that defines the minimum baseline of security controls for all U.S. federal information systems except those related to national security. The controls defined in this standard are customizable and address a diverse set of security and privacy requirements.;123456789012;eu-west-1;{datetime.now()};ac_2_4;Account Management;Access Control (AC);Account Management (AC-2);;aws;;PASS;;;test-check-id;False;\r\n"""
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_SUBSECTION;REQUIREMENTS_ATTRIBUTES_SUBGROUP;REQUIREMENTS_ATTRIBUTES_SERVICE;REQUIREMENTS_ATTRIBUTES_TYPE;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;NIST 800-53 is a regulatory standard that defines the minimum baseline of security controls for all U.S. federal information systems except those related to national security. The controls defined in this standard are customizable and address a diverse set of security and privacy requirements.;123456789012;eu-west-1;{datetime.now()};ac_2_4;Account Management;Access Control (AC);Account Management (AC-2);;aws;;PASS;;;test-check-id;False;\r\naws;NIST 800-53 is a regulatory standard that defines the minimum baseline of security controls for all U.S. federal information systems except those related to national security. The controls defined in this standard are customizable and address a diverse set of security and privacy requirements.;;;{datetime.now()};ac_2_5;Account Management;Access Control (AC);Account Management (AC-2);;aws;;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -44,6 +44,34 @@ class TestAWSISO27001:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "aws"
|
||||
assert output_data_manual.AccountId == ""
|
||||
assert output_data_manual.Region == ""
|
||||
assert output_data_manual.Description == ISO27001_2013_AWS.Description
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Category
|
||||
== ISO27001_2013_AWS.Requirements[1].Attributes[0].Category
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Objetive_ID
|
||||
== ISO27001_2013_AWS.Requirements[1].Attributes[0].Objetive_ID
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Objetive_Name
|
||||
== ISO27001_2013_AWS.Requirements[1].Attributes[0].Objetive_Name
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Check_Summary
|
||||
== ISO27001_2013_AWS.Requirements[1].Attributes[0].Check_Summary
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -57,5 +85,5 @@ class TestAWSISO27001:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"""PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ATTRIBUTES_CATEGORY;REQUIREMENTS_ATTRIBUTES_OBJETIVE_ID;REQUIREMENTS_ATTRIBUTES_OBJETIVE_NAME;REQUIREMENTS_ATTRIBUTES_CHECK_SUMMARY;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work.;123456789012;eu-west-1;{datetime.now()};A.10 Cryptography;A.10.1;Cryptographic Controls;Setup Encryption at rest for RDS instances;PASS;;;test-check-id;False;\r\n"""
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ATTRIBUTES_CATEGORY;REQUIREMENTS_ATTRIBUTES_OBJETIVE_ID;REQUIREMENTS_ATTRIBUTES_OBJETIVE_NAME;REQUIREMENTS_ATTRIBUTES_CHECK_SUMMARY;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work.;123456789012;eu-west-1;{datetime.now()};A.10 Cryptography;A.10.1;Cryptographic Controls;Setup Encryption at rest for RDS instances;PASS;;;test-check-id;False;\r\naws;ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work.;;;{datetime.now()};A.10 Cryptography;A.10.1;Cryptographic Controls;Setup Encryption at rest for RDS instances;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -63,6 +63,54 @@ class TestAWSMITREAttack:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert not output_data.Muted
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "aws"
|
||||
assert output_data_manual.AccountId == ""
|
||||
assert output_data_manual.Region == ""
|
||||
assert output_data_manual.Requirements_Id == MITRE_ATTACK_AWS.Requirements[1].Id
|
||||
assert (
|
||||
output_data_manual.Requirements_Name
|
||||
== MITRE_ATTACK_AWS.Requirements[1].Name
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== MITRE_ATTACK_AWS.Requirements[1].Description
|
||||
)
|
||||
assert output_data_manual.Requirements_Tactics == unroll_list(
|
||||
MITRE_ATTACK_AWS.Requirements[1].Tactics
|
||||
)
|
||||
assert output_data_manual.Requirements_SubTechniques == unroll_list(
|
||||
MITRE_ATTACK_AWS.Requirements[1].SubTechniques
|
||||
)
|
||||
assert output_data_manual.Requirements_Platforms == unroll_list(
|
||||
MITRE_ATTACK_AWS.Requirements[1].Platforms
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_TechniqueURL
|
||||
== MITRE_ATTACK_AWS.Requirements[1].TechniqueURL
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Services == ", ".join(
|
||||
attribute.AWSService
|
||||
for attribute in MITRE_ATTACK_AWS.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Categories == ", ".join(
|
||||
attribute.Category
|
||||
for attribute in MITRE_ATTACK_AWS.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Values == ", ".join(
|
||||
attribute.Value for attribute in MITRE_ATTACK_AWS.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Comments == ", ".join(
|
||||
attribute.Comment
|
||||
for attribute in MITRE_ATTACK_AWS.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -76,6 +124,5 @@ class TestAWSMITREAttack:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
print(repr(content) + "\n")
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;123456789012;eu-west-1;{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;AWS CloudEndure Disaster Recovery;Respond;Significant;AWS CloudEndure Disaster Recovery enables the replication and recovery of servers into AWS Cloud. In the event that a public-facing application or server is compromised, AWS CloudEndure can be used to provision an instance of the server from a previous point in time within minutes. As a result, this mapping is given a score of Significant.;PASS;;;test-check-id;False;\r\n"
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\naws;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;123456789012;eu-west-1;{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;AWS CloudEndure Disaster Recovery;Respond;Significant;AWS CloudEndure Disaster Recovery enables the replication and recovery of servers into AWS Cloud. In the event that a public-facing application or server is compromised, AWS CloudEndure can be used to provision an instance of the server from a previous point in time within minutes. As a result, this mapping is given a score of Significant.;PASS;;;test-check-id;False;\r\naws;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;;;{datetime.now()};T1193;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;AWS CloudEndure Disaster Recovery;Respond;Significant;AWS CloudEndure Disaster Recovery enables the replication and recovery of servers into AWS Cloud. In the event that a public-facing application or server is compromised, AWS CloudEndure can be used to provision an instance of the server from a previous point in time within minutes. As a result, this mapping is given a score of Significant.;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -77,6 +77,57 @@ class TestAzureMITREAttack:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert not output_data.Muted
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "azure"
|
||||
assert output_data_manual.SubscriptionId == ""
|
||||
assert output_data_manual.Location == ""
|
||||
assert (
|
||||
output_data_manual.Requirements_Id == MITRE_ATTACK_AZURE.Requirements[1].Id
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Name
|
||||
== MITRE_ATTACK_AZURE.Requirements[1].Name
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== MITRE_ATTACK_AZURE.Requirements[1].Description
|
||||
)
|
||||
assert output_data_manual.Requirements_Tactics == unroll_list(
|
||||
MITRE_ATTACK_AZURE.Requirements[1].Tactics
|
||||
)
|
||||
assert output_data_manual.Requirements_SubTechniques == unroll_list(
|
||||
MITRE_ATTACK_AZURE.Requirements[1].SubTechniques
|
||||
)
|
||||
assert output_data_manual.Requirements_Platforms == unroll_list(
|
||||
MITRE_ATTACK_AZURE.Requirements[1].Platforms
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_TechniqueURL
|
||||
== MITRE_ATTACK_AZURE.Requirements[1].TechniqueURL
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Services == ", ".join(
|
||||
attribute.AzureService
|
||||
for attribute in MITRE_ATTACK_AZURE.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Categories == ", ".join(
|
||||
attribute.Category
|
||||
for attribute in MITRE_ATTACK_AZURE.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Values == ", ".join(
|
||||
attribute.Value
|
||||
for attribute in MITRE_ATTACK_AZURE.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Comments == ", ".join(
|
||||
attribute.Comment
|
||||
for attribute in MITRE_ATTACK_AZURE.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -98,5 +149,5 @@ class TestAzureMITREAttack:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;SUBSCRIPTIONID;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;LOCATION\r\nazure;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;{AZURE_SUBSCRIPTION_ID};{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Azure SQL Database;Detect;Minimal;This control may alert on usage of faulty SQL statements. This generates an alert for a possible SQL injection by an application. Alerts may not be generated on usage of valid SQL statements by attackers for malicious purposes.;PASS;;;test-check-id;False;;\r\n"
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;SUBSCRIPTIONID;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;LOCATION\r\nazure;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;{AZURE_SUBSCRIPTION_ID};{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Azure SQL Database;Detect;Minimal;This control may alert on usage of faulty SQL statements. This generates an alert for a possible SQL injection by an application. Alerts may not be generated on usage of valid SQL statements by attackers for malicious purposes.;PASS;;;test-check-id;False;;\r\nazure;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;;{datetime.now()};T1191;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Azure SQL Database;Detect;Minimal;This control may alert on usage of faulty SQL statements. This generates an alert for a possible SQL injection by an application. Alerts may not be generated on usage of valid SQL statements by attackers for malicious purposes.;MANUAL;Manual check;manual_check;manual;False;Manual check;\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -71,6 +71,54 @@ class TestGCPMITREAttack:
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert not output_data.Muted
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "gcp"
|
||||
assert output_data_manual.ProjectId == ""
|
||||
assert output_data_manual.Location == ""
|
||||
assert output_data_manual.Requirements_Id == MITRE_ATTACK_GCP.Requirements[1].Id
|
||||
assert (
|
||||
output_data_manual.Requirements_Name
|
||||
== MITRE_ATTACK_GCP.Requirements[1].Name
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== MITRE_ATTACK_GCP.Requirements[1].Description
|
||||
)
|
||||
assert output_data_manual.Requirements_Tactics == unroll_list(
|
||||
MITRE_ATTACK_GCP.Requirements[1].Tactics
|
||||
)
|
||||
assert output_data_manual.Requirements_SubTechniques == unroll_list(
|
||||
MITRE_ATTACK_GCP.Requirements[1].SubTechniques
|
||||
)
|
||||
assert output_data_manual.Requirements_Platforms == unroll_list(
|
||||
MITRE_ATTACK_GCP.Requirements[1].Platforms
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_TechniqueURL
|
||||
== MITRE_ATTACK_GCP.Requirements[1].TechniqueURL
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Services == ", ".join(
|
||||
attribute.GCPService
|
||||
for attribute in MITRE_ATTACK_GCP.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Categories == ", ".join(
|
||||
attribute.Category
|
||||
for attribute in MITRE_ATTACK_GCP.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Values == ", ".join(
|
||||
attribute.Value for attribute in MITRE_ATTACK_GCP.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Requirements_Attributes_Comments == ", ".join(
|
||||
attribute.Comment
|
||||
for attribute in MITRE_ATTACK_GCP.Requirements[1].Attributes
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
@@ -92,5 +140,5 @@ class TestGCPMITREAttack:
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;PROJECTID;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;LOCATION\r\ngcp;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;{GCP_PROJECT_ID};{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Artifact Registry;Protect;Partial;Once this control is deployed, it can detect known vulnerabilities in various Linux OS packages. This information can be used to patch, isolate, or remove vulnerable software and machines. This control does not directly protect against exploitation and is not effective against zero day attacks, vulnerabilities with no available patch, and other end-of-life packages.;PASS;;;test-check-id;False;;\r\n"
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;PROJECTID;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_NAME;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_TACTICS;REQUIREMENTS_SUBTECHNIQUES;REQUIREMENTS_PLATFORMS;REQUIREMENTS_TECHNIQUEURL;REQUIREMENTS_ATTRIBUTES_SERVICES;REQUIREMENTS_ATTRIBUTES_CATEGORIES;REQUIREMENTS_ATTRIBUTES_VALUES;REQUIREMENTS_ATTRIBUTES_COMMENTS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;LOCATION\r\ngcp;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;123456789012;{datetime.now()};T1190;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Artifact Registry;Protect;Partial;Once this control is deployed, it can detect known vulnerabilities in various Linux OS packages. This information can be used to patch, isolate, or remove vulnerable software and machines. This control does not directly protect against exploitation and is not effective against zero day attacks, vulnerabilities with no available patch, and other end-of-life packages.;PASS;;;test-check-id;False;;\r\ngcp;MITRE ATT&CK® is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.;;{datetime.now()};T1191;Exploit Public-Facing Application;Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network. The weakness in the system can be a software bug, a temporary glitch, or a misconfiguration.;Initial Access;;Containers | IaaS | Linux | Network | Windows | macOS;https://attack.mitre.org/techniques/T1190/;Artifact Registry;Protect;Partial;Once this control is deployed, it can detect known vulnerabilities in various Linux OS packages. This information can be used to patch, isolate, or remove vulnerable software and machines. This control does not directly protect against exploitation and is not effective against zero day attacks, vulnerabilities with no available patch, and other end-of-life packages.;MANUAL;Manual check;manual_check;manual;False;Manual check;\r\n"
|
||||
assert content == expected_csv
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
from os import path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from colorama import Fore
|
||||
|
||||
from prowler.lib.check.compliance_models import (
|
||||
CIS_Requirement_Attribute,
|
||||
Compliance_Requirement,
|
||||
ComplianceBaseModel,
|
||||
)
|
||||
from prowler.lib.check.models import Check_Report, load_check_metadata
|
||||
from prowler.lib.outputs.compliance.compliance import get_check_compliance
|
||||
from prowler.lib.outputs.csv.csv import generate_csv_fields
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
from prowler.lib.outputs.outputs import extract_findings_statistics, set_report_color
|
||||
@@ -326,339 +318,3 @@ class TestOutputs:
|
||||
assert stats["resources_count"] == 1
|
||||
assert stats["findings_count"] == 2
|
||||
assert not stats["all_fails_are_muted"]
|
||||
|
||||
def test_get_check_compliance_aws(self):
|
||||
bulk_check_metadata = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="AWS",
|
||||
Version="1.4",
|
||||
Description="The CIS Benchmark for CIS Amazon Web Services Foundations Benchmark, v1.4.0, Level 1 and 2 provides prescriptive guidance for configuring security options for a subset of Amazon Web Services. It has an emphasis on foundational, testable, and architecture agnostic settings",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.\n\nNote:\n-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.\n-You must use your 'root' account to enable MFA Delete on S3 buckets.\n\n**From Command line:**\n\n1. Run the s3api put-bucket-versioning command\n\n```\naws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa “arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode”\n```",
|
||||
AuditProcedure='Perform the steps below to confirm MFA delete is configured on an S3 Bucket\n\n**From Console:**\n\n1. Login to the S3 console at `https://console.aws.amazon.com/s3/`\n\n2. Click the `Check` box next to the Bucket name you want to confirm\n\n3. In the window under `Properties`\n\n4. Confirm that Versioning is `Enabled`\n\n5. Confirm that MFA Delete is `Enabled`\n\n**From Command Line:**\n\n1. Run the `get-bucket-versioning`\n```\naws s3api get-bucket-versioning --bucket my-bucket\n```\n\nOutput example:\n```\n<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> \n <Status>Enabled</Status>\n <MfaDelete>Enabled</MfaDelete> \n</VersioningConfiguration>\n```\n\nIf the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.',
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="AWS",
|
||||
Version="1.5",
|
||||
Description="The CIS Amazon Web Services Foundations Benchmark provides prescriptive guidance for configuring security options for a subset of Amazon Web Services with an emphasis on foundational, testable, and architecture agnostic settings.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.\n\nNote:\n-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.\n-You must use your 'root' account to enable MFA Delete on S3 buckets.\n\n**From Command line:**\n\n1. Run the s3api put-bucket-versioning command\n\n```\naws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa “arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode”\n```",
|
||||
AuditProcedure='Perform the steps below to confirm MFA delete is configured on an S3 Bucket\n\n**From Console:**\n\n1. Login to the S3 console at `https://console.aws.amazon.com/s3/`\n\n2. Click the `Check` box next to the Bucket name you want to confirm\n\n3. In the window under `Properties`\n\n4. Confirm that Versioning is `Enabled`\n\n5. Confirm that MFA Delete is `Enabled`\n\n**From Command Line:**\n\n1. Run the `get-bucket-versioning`\n```\naws s3api get-bucket-versioning --bucket my-bucket\n```\n\nOutput example:\n```\n<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> \n <Status>Enabled</Status>\n <MfaDelete>Enabled</MfaDelete> \n</VersioningConfiguration>\n```\n\nIf the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.',
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
output_options = mock.MagicMock()
|
||||
output_options.bulk_checks_metadata = {}
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"] = (
|
||||
mock.MagicMock()
|
||||
)
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = (
|
||||
bulk_check_metadata
|
||||
)
|
||||
|
||||
assert get_check_compliance(finding, "aws", output_options) == {
|
||||
"CIS-1.4": ["2.1.3"],
|
||||
"CIS-1.5": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_gcp(self):
|
||||
bulk_check_metadata = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="GCP",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Google Cloud Computing Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="GCP",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Google Cloud Computing Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
output_options = mock.MagicMock()
|
||||
output_options.bulk_checks_metadata = {}
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"] = (
|
||||
mock.MagicMock()
|
||||
)
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = (
|
||||
bulk_check_metadata
|
||||
)
|
||||
|
||||
assert get_check_compliance(finding, "gcp", output_options) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_azure(self):
|
||||
bulk_check_metadata = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Azure",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Azuee Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Azure",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Azure Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
output_options = mock.MagicMock()
|
||||
output_options.bulk_checks_metadata = {}
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"] = (
|
||||
mock.MagicMock()
|
||||
)
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = (
|
||||
bulk_check_metadata
|
||||
)
|
||||
|
||||
assert get_check_compliance(finding, "azure", output_options) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_kubernetes(self):
|
||||
bulk_check_metadata = [
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Kubernetes",
|
||||
Version="2.0",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Kubernetes Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
ComplianceBaseModel(
|
||||
Framework="CIS",
|
||||
Provider="Kubernetes",
|
||||
Version="2.1",
|
||||
Description="This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Kubernetes Platform",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.3",
|
||||
Description="Ensure compute instances do not use the default service account with full access to all Cloud APIs",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Compute Engine",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="The default service account should not be used for compute instances as it has full access to all Cloud APIs.",
|
||||
RationaleStatement="The default service account has full access to all Cloud APIs and should not be used for compute instances.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the 'Compute Engine' section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be modified\n3. Click the 'Edit' button\n4. In the 'Service account' section, select a service account that has the least privilege necessary for the instance\n5. Click 'Save' to apply the changes",
|
||||
AuditProcedure="Perform the following to ensure compute instances do not use the default service account with full access to all Cloud APIs:\n\n1. Navigate to the section of the Google Cloud Console at `https://console.cloud.google.com/compute/instances`\n2. Click on the instance to be audited\n3. In the section, verify that the service account selected has the least privilege necessary for the instance",
|
||||
AdditionalInformation="",
|
||||
References="https://cloud.google.com/compute/docs/access/service-accounts#default_service_account",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/fixtures/metadata.json"
|
||||
).json()
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
output_options = mock.MagicMock()
|
||||
output_options.bulk_checks_metadata = {}
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"] = (
|
||||
mock.MagicMock()
|
||||
)
|
||||
output_options.bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = (
|
||||
bulk_check_metadata
|
||||
)
|
||||
|
||||
assert get_check_compliance(finding, "kubernetes", output_options) == {
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user