Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dbbf75b
chore(aws/neptune): adapt some metadata fields to new format
puchy22 Aug 8, 2025
0b32a73
chore(changelog): add new changes
puchy22 Aug 8, 2025
7fcdae0
fix: general quality review
puchy22 Aug 19, 2025
efb26b0
chore(neptune): change RelatedUrl format to continue being a str
puchy22 Aug 19, 2025
1d0be26
Merge branch 'master' into review-metadata-aws-neptune
puchy22 Aug 19, 2025
5f83beb
chore(changelog): update changes to newer unreleased version
puchy22 Aug 19, 2025
2b2a3ea
fix: split the links with commas instead semicolons
puchy22 Aug 20, 2025
589f651
chore: change the reference URLs ti new field called AdditionalURLs
puchy22 Aug 25, 2025
0cc063d
chore: change the Prowler Hub holder link from RelatedUrl to Remediat…
puchy22 Aug 25, 2025
bcbc187
feat: add new validators
HugoPBrito Aug 25, 2025
2609f04
feat: add new tests
HugoPBrito Aug 25, 2025
48dd042
Revert "feat: add new tests"
HugoPBrito Aug 27, 2025
f0ec0e4
chore: add to changelog
HugoPBrito Aug 27, 2025
2fa8b63
chore: move check_types to provider config file
HugoPBrito Aug 27, 2025
3d19a49
fix: lib/check tests
HugoPBrito Aug 27, 2025
e41a8a8
fix: lib/output tests
HugoPBrito Aug 27, 2025
52d5d7e
chore: change validation error message
HugoPBrito Aug 27, 2025
90016a9
Merge branch 'master' of https://github.com/prowler-cloud/prowler int…
HugoPBrito Aug 27, 2025
162be32
Merge branch 'master' of https://github.com/prowler-cloud/prowler int…
HugoPBrito Aug 27, 2025
a3e0b36
Merge branch 'review-metadata-aws-neptune' into PRWLR-7706-add-pydant…
HugoPBrito Aug 27, 2025
64064a1
fix: incorrect checktypes
HugoPBrito Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions prowler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ All notable changes to the **Prowler SDK** are documented in this file.

### Changed
- Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479)
- Update AWS Neptune service metadata to new format [(#8494)](https://github.com/prowler-cloud/prowler/pull/8494)
- CheckMetadata Pydantic validators [(#8584)](https://github.com/prowler-cloud/prowler/pull/8584)
- Improve AWS Security Hub region check using multiple threads [(#8365)](https://github.com/prowler-cloud/prowler/pull/8365)

### Fixed
Expand Down
100 changes: 99 additions & 1 deletion prowler/lib/check/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,54 @@
from prowler.lib.logger import logger


def _validate_aws_check_type_in_config(check_type: str) -> bool:
"""
Validate if a CheckType exists in the AWS config using direct lookups.
Supports partial paths: namespace, namespace/category, namespace/category/classifier

Args:
check_type: The CheckType string to validate (e.g., "TTPs/Initial Access")

Returns:
bool: True if the CheckType path exists in the config hierarchy
"""
try:
import json
import os

if not check_type:
return False

# Get the path to the AWS CheckTypes configuration
current_dir = os.path.dirname(os.path.abspath(__file__))
check_types_file = os.path.join(
current_dir, "..", "..", "providers", "aws", "config", "check_types.json"
)
check_types_file = os.path.normpath(check_types_file)

# Load the CheckTypes hierarchy from JSON file
if not os.path.exists(check_types_file):
return False

with open(check_types_file, "r") as f:
hierarchy = json.load(f)

# Split the path by '/' to get each level
path_parts = check_type.split("/")

# Navigate through the hierarchy using direct lookups
current_level = hierarchy
for part in path_parts:
if not isinstance(current_level, dict) or part not in current_level:
return False
current_level = current_level[part]

return True

except (KeyError, AttributeError, FileNotFoundError, json.JSONDecodeError):
return False


class Code(BaseModel):
"""
Represents the remediation code using IaC like CloudFormation, Terraform or the native CLI.
Expand Down Expand Up @@ -94,9 +142,14 @@ class CheckMetadata(BaseModel):
Validators:
valid_category(value): Validator function to validate the categories of the check.
severity_to_lower(severity): Validator function to convert the severity to lowercase.
valid_severity(severity): Validator function to validate the severity of the check.
valid_cli_command(remediation): Validator function to validate the CLI command is not an URL.
valid_resource_type(resource_type): Validator function to validate the resource type is not empty.
validate_service_name(service_name, values): Validator function to validate the service name matches CheckID.
valid_check_id(check_id): Validator function to validate the CheckID format.
validate_check_title(check_title): Validator function to validate CheckTitle max length (150 chars).
validate_check_type(check_type, values): Validator function to validate CheckType - no empty strings for all providers, plus predefined types validation for AWS (loaded from config file).
validate_description(description): Validator function to validate Description max length (400 chars).
validate_risk(risk): Validator function to validate Risk max length (400 chars).
"""

Provider: str
Expand Down Expand Up @@ -178,6 +231,51 @@ def valid_check_id(cls, check_id, values):

return check_id

@validator("CheckTitle", pre=True, always=True)
def validate_check_title(cls, check_title):
if len(check_title) > 150:
raise ValueError(
f"CheckTitle must not exceed 150 characters, got {len(check_title)} characters"
)
return check_title

@validator("CheckType", pre=True, always=True)
def validate_check_type(cls, check_type, values):
# Check for empty strings in the list - applies to ALL providers
for i, check_type_item in enumerate(check_type):
if not check_type_item or check_type_item.strip() == "":
raise ValueError(
f"CheckType list cannot contain empty strings. Found empty string at index {i}."
)

provider = values.get("Provider", "").lower()

# For AWS provider, also validate against config hierarchy (like custom checks)
if provider == "aws":
for check_type_item in check_type:
if not _validate_aws_check_type_in_config(check_type_item):
raise ValueError(
f"Invalid CheckType: '{check_type_item}'. Must be a valid path in the AWS CheckType hierarchy. See prowler/providers/aws/config/check_types.json for valid values."
)

return check_type

@validator("Description", pre=True, always=True)
def validate_description(cls, description):
if len(description) > 400:
raise ValueError(
f"Description must not exceed 400 characters, got {len(description)} characters"
)
return description

@validator("Risk", pre=True, always=True)
def validate_risk(cls, risk):
if len(risk) > 400:
raise ValueError(
f"Risk must not exceed 400 characters, got {len(risk)} characters"
)
return risk

@staticmethod
def get_bulk(provider: str) -> dict[str, "CheckMetadata"]:
"""
Expand Down
79 changes: 79 additions & 0 deletions prowler/providers/aws/config/check_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"Software and Configuration Checks": {
"Vulnerabilities": {
"CVE": {}
},
"AWS Security Best Practices": {
"Network Reachability": {},
"Runtime Behavior Analysis": {}
},
"Industry and Regulatory Standards": {
"AWS Foundational Security Best Practices": {},
"CIS Host Hardening Benchmarks": {},
"CIS AWS Foundations Benchmark": {},
"PCI-DSS": {},
"Cloud Security Alliance Controls": {},
"ISO 90001 Controls": {},
"ISO 27001 Controls": {},
"ISO 27017 Controls": {},
"ISO 27018 Controls": {},
"SOC 1": {},
"SOC 2": {},
"HIPAA Controls (USA)": {},
"NIST 800-53 Controls (USA)": {},
"NIST CSF Controls (USA)": {},
"IRAP Controls (Australia)": {},
"K-ISMS Controls (Korea)": {},
"MTCS Controls (Singapore)": {},
"FISC Controls (Japan)": {},
"My Number Act Controls (Japan)": {},
"ENS Controls (Spain)": {},
"Cyber Essentials Plus Controls (UK)": {},
"G-Cloud Controls (UK)": {},
"C5 Controls (Germany)": {},
"IT-Grundschutz Controls (Germany)": {},
"GDPR Controls (Europe)": {},
"TISAX Controls (Europe)": {}
},
"Patch Management": {}
},
"TTPs": {
"Initial Access": {},
"Execution": {},
"Persistence": {},
"Privilege Escalation": {},
"Defense Evasion": {},
"Credential Access": {},
"Discovery": {},
"Lateral Movement": {},
"Collection": {},
"Command and Control": {}
},
"Effects": {
"Data Exposure": {},
"Data Exfiltration": {},
"Data Destruction": {},
"Denial of Service": {},
"Resource Consumption": {}
},
"Unusual Behaviors": {
"Application": {},
"Network Flow": {},
"IP address": {},
"User": {},
"VM": {},
"Container": {},
"Serverless": {},
"Process": {},
"Database": {},
"Data": {}
},
"Sensitive Data Identifications": {
"PII": {},
"Passwords": {},
"Legal": {},
"Financial": {},
"Security": {},
"Business": {}
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_backup_enabled",
"CheckTitle": "Check for Neptune Clusters Backup Retention Period.",
"CheckType": [],
"CheckTitle": "Neptune cluster has automated backups enabled with retention period equal to or greater than the configured minimum",
"CheckType": [
"Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices"
],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-instance",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters have backup enabled.",
"Risk": "Ensure that your Amazon Neptune graph database clusters have set a minimum backup retention period of 7 days or greater in order to achieve your organization compliance requirements. The retention period represents the number of days to retain automated snapshots.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-5",
"Description": "*Neptune DB cluster* automated backup is enabled and retention days are more than the required minimum retention period (default to 7 days).",
"Risk": "**Insufficient backup retention** reduces the ability to recover from data corruption, accidental deletion, or ransomware, impacting **availability** and **integrity**.\n\n- Prevents point-in-time recovery to required dates\n- Increases downtime, irreversible data loss, and compliance violations",
"RelatedUrl": "",
"AdditionalURLs": [
"https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-5",
"https://trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html",
"https://support.icompaas.com/support/solutions/articles/62000233327-check-for-neptune-clusters-backup-retention-period",
"https://asecure.cloud/a/p_configrule_neptune_cluster_backup_retention_check/"
],
"Remediation": {
"Code": {
"CLI": "aws neptune modify-db-cluster --db-cluster-identifier <DB_CLUSTER_ID> --backup-retention-period 7",
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#",
"Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#"
"CLI": "aws neptune modify-db-cluster --db-cluster-identifier <DB_CLUSTER_ID> --backup-retention-period 7 --apply-immediately",
"NativeIaC": "```yaml\nParameters:\n DBClusterId:\n Type: String\nResources:\n NeptuneCluster:\n Type: AWS::Neptune::DBCluster\n Properties:\n DBClusterIdentifier: !Ref DBClusterId\n BackupRetentionPeriod: 7\n```",
"Terraform": "```hcl\nresource \"aws_neptune_cluster\" \"example_resource\" {\n cluster_identifier = var.cluster_id\n backup_retention_period = 7\n}\n```",
"Other": "1. Sign in to the AWS Management Console\n2. Services → Amazon Neptune → Databases\n3. Select the DB cluster and click Modify\n4. In Backup retention period set the value to 7 (or higher)\n5. Choose Apply immediately and click Modify cluster"
},
"Recommendation": {
"Text": "Enable automated backup for production data. Define a retention period and periodically test backup restoration. A Disaster Recovery process should be in place to govern Data Protection approach.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-5"
"Text": "Ensure automated backups are enabled and retention aligns with your **RPO/RTO** and regulatory requirements (at least `7` days).\n\n- Define backup lifecycle and storage retention policies\n- Regularly test restore procedures and monitor backup health\n- Incorporate backups into Disaster Recovery and retention governance",
"Url": "https://hub.prowler.com/check/neptune_cluster_backup_enabled"
}
},
"Categories": [],
"Categories": [
"resilience"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_copy_tags_to_snapshots",
"CheckTitle": "Check if Neptune DB clusters are configured to copy tags to snapshots.",
"CheckTitle": "Neptune DB cluster is configured to copy tags to snapshots.",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:cluster:db-cluster-identifier",
"ResourceIdTemplate": "",
"Severity": "low",
"ResourceType": "AwsRdsDbCluster",
"Description": "This check ensures that Neptune DB clusters are configured to copy all tags to snapshots when the snapshots are created.",
"Risk": "If tags are not copied to snapshots, the snapshots may lack necessary metadata for identification, governance, and access control, leading to potential mismanagement and security risks.",
"RelatedUrl": "https://docs.aws.amazon.com/neptune/latest/userguide/tagging.html#tagging-overview",
"Description": "*Neptune DB cluster* is configured to copy all tags to snapshots when snapshots are created.",
"Risk": "**Missing snapshot tags** weakens governance across confidentiality, integrity, and availability.\n\n- **Access control**: tag-based IAM conditions may not apply to snapshots, enabling unauthorized restore or copy\n- **Operational**: recovery, retention, and cost tracking can fail due to unidentifiable or orphaned snapshots",
"RelatedUrl": "",
"AdditionalURLs": [
"https://docs.aws.amazon.com/neptune/latest/userguide/tagging.html#tagging-overview",
"https://www.cloudanix.com/docs/aws/audit/rdsmonitoring/rules/neptune_cluster_copy_tags_to_snapshot_enabled",
"https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-8",
"https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/aws-general-policies/bc-aws-2-60"
],
"Remediation": {
"Code": {
"CLI": "aws neptune modify-db-cluster --db-cluster-identifier <db-cluster-identifier> --copy-tags-to-snapshot --apply-immediately",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-8",
"Terraform": ""
"CLI": "aws neptune modify-db-cluster --db-cluster-identifier <DB_CLUSTER_ID> --copy-tags-to-snapshot --apply-immediately",
"NativeIaC": "```yaml\nResources:\n NeptuneCluster:\n Type: AWS::RDS::DBCluster\n Properties:\n DBClusterIdentifier: <DB_CLUSTER_ID>\n Engine: neptune\n CopyTagsToSnapshot: true\n```",
"Terraform": "```hcl\nresource \"aws_neptune_cluster\" \"example_resource\" {\n cluster_identifier = \"<DB_CLUSTER_ID>\"\n copy_tags_to_snapshot = true\n}\n```",
"Other": "1. Sign in to the AWS Management Console and open Amazon Neptune\n2. Click Clusters and select the cluster\n3. Click Modify\n4. In Backup, enable \"Copy tags to snapshots\"\n5. Check \"Apply immediately\"\n6. Click Modify Cluster"
},
"Recommendation": {
"Text": "Configure your Neptune DB clusters to copy tags to snapshots when the snapshots are created.",
"Url": "https://docs.aws.amazon.com/neptune/latest/userguide/tagging.html#tagging-overview"
"Text": "Preserve metadata by enabling tag inheritance for snapshots and enforcing a consistent tagging strategy.\n\n- Adopt a standardized tag taxonomy\n- Use tag-based access controls and apply least privilege\n- Automate tagging and policy checks in provisioning to prevent untagged snapshots",
"Url": "https://hub.prowler.com/check/neptune_cluster_copy_tags_to_snapshots"
}
},
"Categories": [
"trustboundaries"
],
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_deletion_protection",
"CheckTitle": "Check if Neptune Clusters storage has deletion protection enabled.",
"CheckType": [],
"CheckTitle": "Neptune cluster has deletion protection enabled",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices",
"Industry and Regulatory Standards/AWS Foundational Security Best Practices",
"Effects/Data Destruction"
],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters storage has deletion protection enabled.",
"Risk": "Enabling cluster deletion protection offers an additional layer of protection against accidental database deletion or deletion by an unauthorized user. A Neptune DB cluster can't be deleted while deletion protection is enabled. You must first disable deletion protection before a delete request can succeed.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-4",
"ResourceType": "Other",
"Description": "*Neptune DB cluster* has **deletion protection** enabled.",
"Risk": "Absence of **deletion protection** weakens *availability* and *integrity*: clusters can be removed by accidental admin actions, rogue automation, or compromised credentials.\n\nCluster deletion causes immediate service outage, potential permanent data loss, and extended recovery time if backups or restores are insufficient.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-4"
],
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
"CLI": "aws neptune modify-db-cluster --db-cluster-identifier <DB_CLUSTER_IDENTIFIER> --deletion-protection --apply-immediately",
"NativeIaC": "```yaml\nResources:\n NeptuneCluster:\n Type: AWS::Neptune::DBCluster\n Properties:\n DBClusterIdentifier: <CLUSTER_ID>\n DeletionProtection: true\n```",
"Terraform": "```hcl\nresource \"aws_neptune_cluster\" \"example_resource\" {\n cluster_identifier = \"<CLUSTER_ID>\"\n deletion_protection = true\n}\n```",
"Other": "1. Sign in to the AWS Management Console and open Amazon Neptune\n2. In the navigation pane, choose Databases\n3. Select the DB cluster and choose Modify\n4. Enable Deletion protection\n5. Choose Apply immediately (if shown) and then Modify DB cluster"
},
"Recommendation": {
"Text": "Enable deletion protection for production Neptune Clusters.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-4"
"Text": "Enable **deletion protection** for production *Neptune* clusters and apply the principles of **least privilege** and *separation of duties* for delete operations.\n\nEnforce change-control approvals, restrict delete permissions to audited roles, and limit automated workflows that can perform destructive actions to prevent accidental or malicious deletions.",
"Url": "https://hub.prowler.com/check/neptune_cluster_deletion_protection"
}
},
"Categories": [],
"Categories": [
"resilience"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
Expand Down
Loading
Loading