From 9fb26643ba680b726e165983f8b869e67f2e7705 Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:32:37 +0200 Subject: [PATCH] feat(dynamodb): add new check `dynamodb_accelerator_cluster_in_transit_encryption_enabled` (#5173) Co-authored-by: Sergio --- ..._accelerator_cluster_encryption_enabled.py | 6 +- .../__init__.py | 0 ...n_transit_encryption_enabled.metadata.json | 34 +++++ ...r_cluster_in_transit_encryption_enabled.py | 22 ++++ .../aws/services/dynamodb/dynamodb_service.py | 8 +- ...ster_in_transit_encryption_enabled_test.py | 123 ++++++++++++++++++ .../dynamodb/dynamodb_service_test.py | 3 + 7 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/__init__.py create mode 100644 prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json create mode 100644 prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.py create mode 100644 tests/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled_test.py diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.py b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.py index 2961c83993..9fda39d391 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.py +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.py @@ -12,11 +12,13 @@ class dynamodb_accelerator_cluster_encryption_enabled(Check): report.region = cluster.region report.resource_tags = cluster.tags report.status = "FAIL" - report.status_extended = f"DynamoDB cluster {cluster.name} does not have encryption at rest enabled." + report.status_extended = ( + f"DAX cluster {cluster.name} does not have encryption at rest enabled." + ) if cluster.encryption: report.status = "PASS" report.status_extended = ( - f"DynamoDB cluster {cluster.name} has encryption at rest enabled." + f"DAX cluster {cluster.name} has encryption at rest enabled." ) findings.append(report) return findings diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/__init__.py b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json new file mode 100644 index 0000000000..50741ae1c2 --- /dev/null +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json @@ -0,0 +1,34 @@ +{ + "Provider": "aws", + "CheckID": "dynamodb_accelerator_cluster_in_transit_encryption_enabled", + "CheckTitle": "Check if DynamoDB Accelerator (DAX) clusters are encrypted in transit.", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "dynamodb", + "SubServiceName": "", + "ResourceIdTemplate": "arn:aws:dynamodb:region:account-id:table/table-name", + "Severity": "medium", + "ResourceType": "Other", + "Description": "This control checks whether an Amazon DynamoDB Accelerator (DAX) cluster is encrypted in transit, with the endpoint encryption type set to TLS. The control fails if the DAX cluster isn't encrypted in transit.", + "Risk": "Without encryption in transit, DAX clusters are vulnerable to person-in-the-middle attacks or eavesdropping on network traffic, which could lead to unauthorized access or manipulation of sensitive data.", + "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionInTransit.html", + "Remediation": { + "Code": { + "CLI": "aws dax create-cluster --cluster-name --node-type --replication-factor --cluster-endpoint-encryption-type TLS", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-7", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure that DynamoDB Accelerator (DAX) clusters are encrypted in transit by enabling TLS during cluster creation.", + "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionInTransit.html" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.py b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.py new file mode 100644 index 0000000000..c509f3645d --- /dev/null +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.py @@ -0,0 +1,22 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.dynamodb.dax_client import dax_client + + +class dynamodb_accelerator_cluster_in_transit_encryption_enabled(Check): + def execute(self): + findings = [] + for cluster in dax_client.clusters: + report = Check_Report_AWS(self.metadata()) + report.resource_id = cluster.name + report.resource_arn = cluster.arn + report.region = cluster.region + report.resource_tags = cluster.tags + report.status = "FAIL" + report.status_extended = f"DAX cluster {cluster.name} does not have encryption in transit enabled." + if cluster.tls_encryption: + report.status = "PASS" + report.status_extended = ( + f"DAX cluster {cluster.name} has encryption in transit enabled." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_service.py b/prowler/providers/aws/services/dynamodb/dynamodb_service.py index a1e8481d27..ba40f87a5c 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_service.py +++ b/prowler/providers/aws/services/dynamodb/dynamodb_service.py @@ -9,7 +9,6 @@ from prowler.lib.scan_filters.scan_filters import is_resource_filtered from prowler.providers.aws.lib.service.service import AWSService -################## DynamoDB class DynamoDB(AWSService): def __init__(self, provider): # Call AWSService's __init__ @@ -147,7 +146,6 @@ class DynamoDB(AWSService): ) -################## DynamoDB DAX class DAX(AWSService): def __init__(self, provider): # Call AWSService's __init__ @@ -170,15 +168,20 @@ class DAX(AWSService): ) ): encryption = False + tls_encryption = False if "SSEDescription" in cluster: if cluster["SSEDescription"]["Status"] == "ENABLED": encryption = True + if "ClusterEndpointEncryptionType" in cluster: + if cluster["ClusterEndpointEncryptionType"] == "TLS": + tls_encryption = True self.clusters.append( Cluster( arn=cluster["ClusterArn"], name=cluster["ClusterName"], encryption=encryption, region=regional_client.region, + tls_encryption=tls_encryption, ) ) except Exception as error: @@ -224,3 +227,4 @@ class Cluster(BaseModel): encryption: bool region: str tags: Optional[list] = [] + tls_encryption: bool diff --git a/tests/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled_test.py b/tests/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled_test.py new file mode 100644 index 0000000000..512ce2b93d --- /dev/null +++ b/tests/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled_test.py @@ -0,0 +1,123 @@ +from unittest import mock + +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + AWS_REGION_US_EAST_1, + set_mocked_aws_provider, +) + + +class Test_dynamodb_accelerator_cluster_in_transit_encryption_enabled: + @mock_aws + def test_dax_no_clusters(self): + from prowler.providers.aws.services.dynamodb.dynamodb_service import DAX + + aws_provider = set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1] + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dax_client", + new=DAX(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled import ( + dynamodb_accelerator_cluster_in_transit_encryption_enabled, + ) + + check = dynamodb_accelerator_cluster_in_transit_encryption_enabled() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_dax_cluster_no_encryption(self): + dax_client = client("dax", region_name=AWS_REGION_US_EAST_1) + iam_role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/aws-service-role/dax.amazonaws.com/AWSServiceRoleForDAX" + cluster = dax_client.create_cluster( + ClusterName="daxcluster", + NodeType="dax.t3.small", + ReplicationFactor=3, + IamRoleArn=iam_role_arn, + )["Cluster"] + from prowler.providers.aws.services.dynamodb.dynamodb_service import DAX + + aws_provider = set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1] + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dax_client", + new=DAX(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled import ( + dynamodb_accelerator_cluster_in_transit_encryption_enabled, + ) + + check = dynamodb_accelerator_cluster_in_transit_encryption_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == "DAX cluster daxcluster does not have encryption in transit enabled." + ) + assert result[0].resource_id == cluster["ClusterName"] + assert result[0].resource_arn == cluster["ClusterArn"] + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] + + @mock_aws + def test_dax_cluster_with_encryption(self): + dax_client = client("dax", region_name=AWS_REGION_US_EAST_1) + iam_role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/aws-service-role/dax.amazonaws.com/AWSServiceRoleForDAX" + cluster = dax_client.create_cluster( + ClusterName="daxcluster", + NodeType="dax.t3.small", + ReplicationFactor=3, + IamRoleArn=iam_role_arn, + ClusterEndpointEncryptionType="TLS", + )["Cluster"] + from prowler.providers.aws.services.dynamodb.dynamodb_service import DAX + + aws_provider = set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1] + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dax_client", + new=DAX(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.dynamodb.dynamodb_accelerator_cluster_in_transit_encryption_enabled.dynamodb_accelerator_cluster_in_transit_encryption_enabled import ( + dynamodb_accelerator_cluster_in_transit_encryption_enabled, + ) + + check = dynamodb_accelerator_cluster_in_transit_encryption_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "DAX cluster daxcluster has encryption in transit enabled." + ) + assert result[0].resource_id == cluster["ClusterName"] + assert result[0].resource_arn == cluster["ClusterArn"] + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/dynamodb/dynamodb_service_test.py b/tests/providers/aws/services/dynamodb/dynamodb_service_test.py index 31ca4b1bf8..a2ef7d0eae 100644 --- a/tests/providers/aws/services/dynamodb/dynamodb_service_test.py +++ b/tests/providers/aws/services/dynamodb/dynamodb_service_test.py @@ -164,6 +164,7 @@ class Test_DynamoDB_Service: Tags=[ {"Key": "test", "Value": "test"}, ], + ClusterEndpointEncryptionType="TLS", ) dax_client.create_cluster( ClusterName="daxcluster2", @@ -186,6 +187,7 @@ class Test_DynamoDB_Service: assert dax.clusters[0].tags == [ {"Key": "test", "Value": "test"}, ] + assert dax.clusters[0].tls_encryption assert dax.clusters[1].name == "daxcluster2" assert dax.clusters[1].region == AWS_REGION_US_EAST_1 @@ -193,3 +195,4 @@ class Test_DynamoDB_Service: assert dax.clusters[1].tags == [ {"Key": "test", "Value": "test"}, ] + assert not dax.clusters[1].tls_encryption