diff --git a/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/__init__.py b/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.metadata.json b/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.metadata.json new file mode 100644 index 0000000000..efd3dd70b2 --- /dev/null +++ b/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.metadata.json @@ -0,0 +1,34 @@ +{ + "Provider": "aws", + "CheckID": "neptune_cluster_snapshot_encrypted", + "CheckTitle": "Check if Neptune DB cluster snapshots are encrypted at rest.", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "neptune", + "SubServiceName": "", + "ResourceIdTemplate": "arn:aws:rds:region:account-id:cluster-snapshot:db-cluster-snapshot-identifier", + "Severity": "medium", + "ResourceType": "AwsRdsDbClusterSnapshot", + "Description": "This check ensures that Neptune DB cluster snapshots are encrypted at rest to protect sensitive data from unauthorized access.", + "Risk": "If Neptune DB cluster snapshots are not encrypted, sensitive data might be exposed in case of unauthorized access, leading to potential data breaches and non-compliance with data protection regulations.", + "RelatedUrl": "https://docs.aws.amazon.com/neptune/latest/userguide/backup-restore-create-snapshot.html", + "Remediation": { + "Code": { + "CLI": "aws rds copy-db-cluster-snapshot --source-db-cluster-snapshot-identifier --target-db-cluster-snapshot-identifier --kms-key-id ", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-6", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure that all Neptune DB cluster snapshots are encrypted at rest by enabling encryption on the cluster before creating snapshots or by copying unencrypted snapshots to encrypted ones.", + "Url": "https://docs.aws.amazon.com/neptune/latest/userguide/backup-restore-create-snapshot.html" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.py b/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.py new file mode 100644 index 0000000000..20d6dde603 --- /dev/null +++ b/prowler/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted.py @@ -0,0 +1,26 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.neptune.neptune_client import neptune_client + + +class neptune_cluster_snapshot_encrypted(Check): + def execute(self): + findings = [] + for snapshot in neptune_client.db_cluster_snapshots: + report = Check_Report_AWS(self.metadata()) + report.region = snapshot.region + report.resource_id = snapshot.id + report.resource_arn = snapshot.arn + report.resource_tags = snapshot.tags + report.status = "FAIL" + report.status_extended = ( + f"Neptune Cluster Snapshot {snapshot.id} is not encrypted at rest." + ) + if snapshot.encrypted: + report.status = "PASS" + report.status_extended = ( + f"Neptune Cluster Snapshot {snapshot.id} is encrypted at rest." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted_test.py b/tests/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted_test.py new file mode 100644 index 0000000000..0bf8747fd0 --- /dev/null +++ b/tests/providers/aws/services/neptune/neptune_cluster_snapshot_encrypted/neptune_cluster_snapshot_encrypted_test.py @@ -0,0 +1,107 @@ +from unittest import mock + +from prowler.providers.aws.services.neptune.neptune_service import ClusterSnapshot +from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1 + + +class Test_neptune_cluster_snapshot_encrypted: + def test_neptune_no_snapshots(self): + neptune_client = mock.MagicMock() + neptune_client.db_cluster_snapshots = [] + + with mock.patch( + "prowler.providers.aws.services.neptune.neptune_service.Neptune", + new=neptune_client, + ), mock.patch( + "prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted.neptune_client", + new=neptune_client, + ): + # Test Check + from prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted import ( + neptune_cluster_snapshot_encrypted, + ) + + check = neptune_cluster_snapshot_encrypted() + result = check.execute() + + assert len(result) == 0 + + def test_neptune_snapshot_not_encrypted(self): + neptune_client = mock.MagicMock + snapshot_arn = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster-snapshot:snapshot-1" + neptune_client.db_cluster_snapshots = [ + ClusterSnapshot( + arn=snapshot_arn, + id="snapshot-1", + cluster_id="cluster-1", + region=AWS_REGION_US_EAST_1, + encrypted=False, + tags=[], + ) + ] + + with mock.patch( + "prowler.providers.aws.services.neptune.neptune_service.Neptune", + new=neptune_client, + ), mock.patch( + "prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted.neptune_client", + new=neptune_client, + ): + # Test Check + from prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted import ( + neptune_cluster_snapshot_encrypted, + ) + + check = neptune_cluster_snapshot_encrypted() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == "Neptune Cluster Snapshot snapshot-1 is not encrypted at rest." + ) + assert result[0].resource_id == "snapshot-1" + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_arn == snapshot_arn + assert result[0].resource_tags == [] + + def test_neptune_snapshot_encrypted(self): + neptune_client = mock.MagicMock + snapshot_arn = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster-snapshot:snapshot-1" + neptune_client.db_cluster_snapshots = [ + ClusterSnapshot( + arn=snapshot_arn, + id="snapshot-1", + cluster_id="cluster-1", + region=AWS_REGION_US_EAST_1, + encrypted=True, + tags=[], + ) + ] + + with mock.patch( + "prowler.providers.aws.services.neptune.neptune_service.Neptune", + new=neptune_client, + ), mock.patch( + "prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted.neptune_client", + new=neptune_client, + ): + # Test Check + from prowler.providers.aws.services.neptune.neptune_cluster_snapshot_encrypted.neptune_cluster_snapshot_encrypted import ( + neptune_cluster_snapshot_encrypted, + ) + + check = neptune_cluster_snapshot_encrypted() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Neptune Cluster Snapshot snapshot-1 is encrypted at rest." + ) + assert result[0].resource_id == "snapshot-1" + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_arn == snapshot_arn + assert result[0].resource_tags == []