From d431ea17fd1114b58231e9d32a607cd3e588763a Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Thu, 22 Aug 2024 15:47:16 +0200 Subject: [PATCH 1/8] feat(elasticache): Ensure Redis cache clusters have automatic failover enabled --- .../__init__.py | 0 ...r_automatic_failover_enabled.metadata.json | 32 +++ ...edis_cluster_automatic_failover_enabled.py | 25 +++ .../elasticache/elasticache_service.py | 4 + ...cluster_automatic_failover_enabled_test.py | 188 ++++++++++++++++++ .../elasticache/elasticache_service_test.py | 2 + 6 files changed, 251 insertions(+) create mode 100644 prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py create mode 100644 prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json create mode 100644 prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py create mode 100644 tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json new file mode 100644 index 00000000000..40ca509df54 --- /dev/null +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "elasticache_redis_cluster_automatic_failover_enabled", + "CheckTitle": "Ensure Elasticache Redis clusters have automatic failover enabled.", + "CheckType": [ + "AWS Foundational Security Best Practices" + ], + "ServiceName": "elasticache", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "medium", + "ResourceType": "AWSElastiCacheClusters", + "Description": "Ensure Elasticache Redis OSS cache clusters use automatic failover.", + "Risk": "If automatic failover is not enabled, a failure in the primary node could result in significant downtime, impacting the availability and resilience of your application.", + "RelatedUrl": "https://redis.io/docs/latest/commands/failover/", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-3", + "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-aws-elasticache-redis-cluster-with-multi-az-automatic-failover-feature-set-to-enabled/" + }, + "Recommendation": { + "Text": "Enable automatic failover for ElastiCache (Redis OSS) clusters to ensure high availability and minimize downtime during failures.", + "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Clusters.Modify.html#Clusters.Modify.CON" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py new file mode 100644 index 00000000000..90481ab8941 --- /dev/null +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py @@ -0,0 +1,25 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.elasticache.elasticache_client import ( + elasticache_client, +) + + +class elasticache_redis_cluster_automatic_failover_enabled(Check): + def execute(self): + findings = [] + for repl_group in elasticache_client.replication_groups.values(): + report = Check_Report_AWS(self.metadata()) + report.region = repl_group.region + report.resource_id = repl_group.id + report.resource_arn = repl_group.arn + report.resource_tags = repl_group.tags + report.status = "PASS" + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does have automatic failover enabled." + + if not repl_group.automatic_failover: + report.status = "FAIL" + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does not have automatic failover enabled." + + findings.append(report) + + return findings diff --git a/prowler/providers/aws/services/elasticache/elasticache_service.py b/prowler/providers/aws/services/elasticache/elasticache_service.py index f594c93da0b..4f998e2e046 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -41,6 +41,9 @@ def _describe_cache_clusters(self, regional_client): auto_minor_version_upgrade=cache_cluster.get( "AutoMinorVersionUpgrade", False ), + automatic_failover=cache_cluster.get( + "AutomaticFailover", False + ), ) except Exception as error: logger.error( @@ -177,3 +180,4 @@ class ReplicationGroup(BaseModel): multi_az: str tags: Optional[list] auto_minor_version_upgrade: bool = False + automatic_failover: bool = False diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py new file mode 100644 index 00000000000..cb28d2d0637 --- /dev/null +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py @@ -0,0 +1,188 @@ +from unittest import mock + +from mock import MagicMock + +from prowler.providers.aws.services.elasticache.elasticache_service import ( + ReplicationGroup, +) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, + REPLICATION_GROUP_ARN, + REPLICATION_GROUP_ENCRYPTION, + REPLICATION_GROUP_ID, + REPLICATION_GROUP_MULTI_AZ, + REPLICATION_GROUP_SNAPSHOT_RETENTION, + REPLICATION_GROUP_STATUS, + REPLICATION_GROUP_TAGS, + REPLICATION_GROUP_TRANSIT_ENCRYPTION, +) +from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider + +VPC_ID = "vpc-12345678901234567" + + +class Test_elasticache_redis_cluster_automatic_failover_enabled: + def test_elasticache_no_clusters(self): + # Mock VPC Service + vpc_client = MagicMock + vpc_client.vpc_subnets = {} + + # Mock ElastiCache Service + elasticache_service = MagicMock + elasticache_service.replication_groups = {} + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + ), mock.patch( + "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", + new=elasticache_service, + ), mock.patch( + "prowler.providers.aws.services.vpc.vpc_service.VPC", + new=vpc_client, + ), mock.patch( + "prowler.providers.aws.services.vpc.vpc_client.vpc_client", + new=vpc_client, + ): + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, + ) + + check = elasticache_redis_cluster_automatic_failover_enabled() + result = check.execute() + assert len(result) == 0 + + def test_elasticache_clusters_automatic_failover_undefined(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + elasticache_service.replication_groups = {} + + elasticache_service.replication_groups[REPLICATION_GROUP_ARN] = ( + ReplicationGroup( + arn=REPLICATION_GROUP_ARN, + id=REPLICATION_GROUP_ID, + region=AWS_REGION_US_EAST_1, + status=REPLICATION_GROUP_STATUS, + snapshot_retention=REPLICATION_GROUP_SNAPSHOT_RETENTION, + encrypted=REPLICATION_GROUP_ENCRYPTION, + transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, + multi_az=REPLICATION_GROUP_MULTI_AZ, + tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + ) + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + ), mock.patch( + "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", + new=elasticache_service, + ): + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, + ) + + check = elasticache_redis_cluster_automatic_failover_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automatic failover enabled." + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_id == REPLICATION_GROUP_ID + assert result[0].resource_arn == REPLICATION_GROUP_ARN + assert result[0].resource_tags == REPLICATION_GROUP_TAGS + + def test_elasticache_clusters_automatic_failover_disabled(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + elasticache_service.replication_groups = {} + + elasticache_service.replication_groups[REPLICATION_GROUP_ARN] = ( + ReplicationGroup( + arn=REPLICATION_GROUP_ARN, + id=REPLICATION_GROUP_ID, + region=AWS_REGION_US_EAST_1, + status=REPLICATION_GROUP_STATUS, + snapshot_retention=REPLICATION_GROUP_SNAPSHOT_RETENTION, + encrypted=REPLICATION_GROUP_ENCRYPTION, + transit_encryption=False, + multi_az=REPLICATION_GROUP_MULTI_AZ, + tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=not AUTOMATIC_FAILOVER, + ) + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + ), mock.patch( + "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", + new=elasticache_service, + ): + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, + ) + + check = elasticache_redis_cluster_automatic_failover_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automatic failover enabled." + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_id == REPLICATION_GROUP_ID + assert result[0].resource_arn == REPLICATION_GROUP_ARN + assert result[0].resource_tags == REPLICATION_GROUP_TAGS + + def test_elasticache_clusters_automatic_failover_enabled(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + elasticache_service.replication_groups = {} + + elasticache_service.replication_groups[REPLICATION_GROUP_ARN] = ( + ReplicationGroup( + arn=REPLICATION_GROUP_ARN, + id=REPLICATION_GROUP_ID, + region=AWS_REGION_US_EAST_1, + status=REPLICATION_GROUP_STATUS, + snapshot_retention=REPLICATION_GROUP_SNAPSHOT_RETENTION, + encrypted=REPLICATION_GROUP_ENCRYPTION, + transit_encryption=False, + multi_az=REPLICATION_GROUP_MULTI_AZ, + tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, + ) + ) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + ), mock.patch( + "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", + new=elasticache_service, + ): + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, + ) + + check = elasticache_redis_cluster_automatic_failover_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does have automatic failover enabled." + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_id == REPLICATION_GROUP_ID + assert result[0].resource_arn == REPLICATION_GROUP_ARN + assert result[0].resource_tags == REPLICATION_GROUP_TAGS diff --git a/tests/providers/aws/services/elasticache/elasticache_service_test.py b/tests/providers/aws/services/elasticache/elasticache_service_test.py index bbebc7925b8..c69c6ab841b 100644 --- a/tests/providers/aws/services/elasticache/elasticache_service_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_service_test.py @@ -38,6 +38,7 @@ {"Key": "environment", "Value": "test"}, ] AUTO_MINOR_VERSION_UPGRADE = True +AUTOMATIC_FAILOVER = True # Mocking Access Analyzer Calls @@ -192,4 +193,5 @@ def test_describe_replication_groups(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=not AUTOMATIC_FAILOVER, ) From f7593c2ca3a55f5ed84bcce8430f9cd2be31c163 Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Fri, 23 Aug 2024 12:01:32 +0200 Subject: [PATCH 2/8] feat(elasticache): changed automatic_failover type from bool to str --- ...ticache_redis_cluster_automatic_failover_enabled.py | 10 +++++----- .../aws/services/elasticache/elasticache_service.py | 8 ++++---- ...he_redis_cluster_automatic_failover_enabled_test.py | 5 ++--- .../services/elasticache/elasticache_service_test.py | 3 +-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py index 90481ab8941..e3dd36fc334 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py @@ -13,12 +13,12 @@ def execute(self): report.resource_id = repl_group.id report.resource_arn = repl_group.arn report.resource_tags = repl_group.tags - report.status = "PASS" - report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does have automatic failover enabled." + report.status = "FAIL" + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does not have automatic failover enabled." - if not repl_group.automatic_failover: - report.status = "FAIL" - report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does not have automatic failover enabled." + if repl_group.automatic_failover == "enabled": + report.status = "PASS" + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does have automatic failover enabled." findings.append(report) diff --git a/prowler/providers/aws/services/elasticache/elasticache_service.py b/prowler/providers/aws/services/elasticache/elasticache_service.py index 4f998e2e046..3ca2b9d7f7c 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -41,9 +41,6 @@ def _describe_cache_clusters(self, regional_client): auto_minor_version_upgrade=cache_cluster.get( "AutoMinorVersionUpgrade", False ), - automatic_failover=cache_cluster.get( - "AutomaticFailover", False - ), ) except Exception as error: logger.error( @@ -109,6 +106,9 @@ def _describe_replication_groups(self, regional_client): auto_minor_version_upgrade=repl_group.get( "AutoMinorVersionUpgrade", False ), + automatic_failover=repl_group.get( + "AutomaticFailover", None + ), ) except Exception as error: logger.error( @@ -180,4 +180,4 @@ class ReplicationGroup(BaseModel): multi_az: str tags: Optional[list] auto_minor_version_upgrade: bool = False - automatic_failover: bool = False + automatic_failover: Optional[str] diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py index cb28d2d0637..a7ce0cefeb5 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py @@ -7,7 +7,6 @@ ) from tests.providers.aws.services.elasticache.elasticache_service_test import ( AUTO_MINOR_VERSION_UPGRADE, - AUTOMATIC_FAILOVER, REPLICATION_GROUP_ARN, REPLICATION_GROUP_ENCRYPTION, REPLICATION_GROUP_ID, @@ -114,7 +113,7 @@ def test_elasticache_clusters_automatic_failover_disabled(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, - automatic_failover=not AUTOMATIC_FAILOVER, + automatic_failover="disabled", ) ) @@ -159,7 +158,7 @@ def test_elasticache_clusters_automatic_failover_enabled(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, - automatic_failover=AUTOMATIC_FAILOVER, + automatic_failover="enabled", ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_service_test.py b/tests/providers/aws/services/elasticache/elasticache_service_test.py index c69c6ab841b..51ec5caf5e0 100644 --- a/tests/providers/aws/services/elasticache/elasticache_service_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_service_test.py @@ -38,7 +38,6 @@ {"Key": "environment", "Value": "test"}, ] AUTO_MINOR_VERSION_UPGRADE = True -AUTOMATIC_FAILOVER = True # Mocking Access Analyzer Calls @@ -193,5 +192,5 @@ def test_describe_replication_groups(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, - automatic_failover=not AUTOMATIC_FAILOVER, + automatic_failover=None, ) From b6826f85e0958ec5a1c240fe8f69486289e4d99b Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Fri, 23 Aug 2024 17:35:56 +0200 Subject: [PATCH 3/8] fix(elasticache): Try to fix codecov --- .../providers/aws/services/elasticache/elasticache_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/elasticache/elasticache_service.py b/prowler/providers/aws/services/elasticache/elasticache_service.py index 3ca2b9d7f7c..50ff131c2ad 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -180,4 +180,4 @@ class ReplicationGroup(BaseModel): multi_az: str tags: Optional[list] auto_minor_version_upgrade: bool = False - automatic_failover: Optional[str] + automatic_failover: Optional[str] = None From c86d9b13dc328da55d5f8b3b1d1390177a884d1d Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Mon, 26 Aug 2024 15:58:54 +0100 Subject: [PATCH 4/8] feat(elasticache): resolved comments and updated mocking --- ...r_automatic_failover_enabled.metadata.json | 2 +- .../elasticache/elasticache_service.py | 6 +-- ...luster_auto_minor_version_upgrades_test.py | 47 ++---------------- ...cluster_automatic_failover_enabled_test.py | 48 +------------------ ...cache_redis_cluster_backup_enabled_test.py | 13 ++++- ...ster_in_transit_encryption_enabled_test.py | 8 ++++ ...che_redis_cluster_multi_az_enabled_test.py | 8 ++++ ...is_cluster_rest_encryption_enabled_test.py | 8 ++++ .../elasticache/elasticache_service_test.py | 3 +- 9 files changed, 47 insertions(+), 96 deletions(-) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json index 40ca509df54..b98e5d76f85 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json @@ -3,7 +3,7 @@ "CheckID": "elasticache_redis_cluster_automatic_failover_enabled", "CheckTitle": "Ensure Elasticache Redis clusters have automatic failover enabled.", "CheckType": [ - "AWS Foundational Security Best Practices" + "NIST 800-53 Controls" ], "ServiceName": "elasticache", "SubServiceName": "", diff --git a/prowler/providers/aws/services/elasticache/elasticache_service.py b/prowler/providers/aws/services/elasticache/elasticache_service.py index 50ff131c2ad..23a46b55597 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -107,7 +107,7 @@ def _describe_replication_groups(self, regional_client): "AutoMinorVersionUpgrade", False ), automatic_failover=repl_group.get( - "AutomaticFailover", None + "AutomaticFailover", "disabled" ), ) except Exception as error: @@ -179,5 +179,5 @@ class ReplicationGroup(BaseModel): transit_encryption: bool multi_az: str tags: Optional[list] - auto_minor_version_upgrade: bool = False - automatic_failover: Optional[str] = None + auto_minor_version_upgrade: bool + automatic_failover: str diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades_test.py index 5193d81aa26..152ba48a600 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades_test.py @@ -7,6 +7,7 @@ ) from tests.providers.aws.services.elasticache.elasticache_service_test import ( AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, REPLICATION_GROUP_ARN, REPLICATION_GROUP_ENCRYPTION, REPLICATION_GROUP_ID, @@ -14,7 +15,6 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION, REPLICATION_GROUP_STATUS, REPLICATION_GROUP_TAGS, - REPLICATION_GROUP_TRANSIT_ENCRYPTION, ) from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider @@ -52,49 +52,6 @@ def test_elasticache_no_clusters(self): result = check.execute() assert len(result) == 0 - def test_elasticache_clusters_auto_minor_version_upgrades_undefined(self): - # Mock ElastiCache Service - elasticache_service = MagicMock - elasticache_service.replication_groups = {} - - elasticache_service.replication_groups[REPLICATION_GROUP_ARN] = ( - ReplicationGroup( - arn=REPLICATION_GROUP_ARN, - id=REPLICATION_GROUP_ID, - region=AWS_REGION_US_EAST_1, - status=REPLICATION_GROUP_STATUS, - snapshot_retention=REPLICATION_GROUP_SNAPSHOT_RETENTION, - encrypted=REPLICATION_GROUP_ENCRYPTION, - transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, - multi_az=REPLICATION_GROUP_MULTI_AZ, - tags=REPLICATION_GROUP_TAGS, - ) - ) - - with mock.patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), - ), mock.patch( - "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", - new=elasticache_service, - ): - from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_auto_minor_version_upgrades.elasticache_redis_cluster_auto_minor_version_upgrades import ( - elasticache_redis_cluster_auto_minor_version_upgrades, - ) - - check = elasticache_redis_cluster_auto_minor_version_upgrades() - result = check.execute() - assert len(result) == 1 - assert result[0].status == "FAIL" - assert ( - result[0].status_extended - == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automated minor version upgrades enabled." - ) - assert result[0].region == AWS_REGION_US_EAST_1 - assert result[0].resource_id == REPLICATION_GROUP_ID - assert result[0].resource_arn == REPLICATION_GROUP_ARN - assert result[0].resource_tags == REPLICATION_GROUP_TAGS - def test_elasticache_clusters_auto_minor_version_upgrades_disabled(self): # Mock ElastiCache Service elasticache_service = MagicMock @@ -112,6 +69,7 @@ def test_elasticache_clusters_auto_minor_version_upgrades_disabled(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) @@ -156,6 +114,7 @@ def test_elasticache_clusters_auto_minor_version_upgrades_enabled(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py index a7ce0cefeb5..5fd03015ab9 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py @@ -7,6 +7,7 @@ ) from tests.providers.aws.services.elasticache.elasticache_service_test import ( AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, REPLICATION_GROUP_ARN, REPLICATION_GROUP_ENCRYPTION, REPLICATION_GROUP_ID, @@ -14,7 +15,6 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION, REPLICATION_GROUP_STATUS, REPLICATION_GROUP_TAGS, - REPLICATION_GROUP_TRANSIT_ENCRYPTION, ) from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider @@ -52,50 +52,6 @@ def test_elasticache_no_clusters(self): result = check.execute() assert len(result) == 0 - def test_elasticache_clusters_automatic_failover_undefined(self): - # Mock ElastiCache Service - elasticache_service = MagicMock - elasticache_service.replication_groups = {} - - elasticache_service.replication_groups[REPLICATION_GROUP_ARN] = ( - ReplicationGroup( - arn=REPLICATION_GROUP_ARN, - id=REPLICATION_GROUP_ID, - region=AWS_REGION_US_EAST_1, - status=REPLICATION_GROUP_STATUS, - snapshot_retention=REPLICATION_GROUP_SNAPSHOT_RETENTION, - encrypted=REPLICATION_GROUP_ENCRYPTION, - transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, - multi_az=REPLICATION_GROUP_MULTI_AZ, - tags=REPLICATION_GROUP_TAGS, - auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, - ) - ) - - with mock.patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), - ), mock.patch( - "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", - new=elasticache_service, - ): - from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( - elasticache_redis_cluster_automatic_failover_enabled, - ) - - check = elasticache_redis_cluster_automatic_failover_enabled() - result = check.execute() - assert len(result) == 1 - assert result[0].status == "FAIL" - assert ( - result[0].status_extended - == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automatic failover enabled." - ) - assert result[0].region == AWS_REGION_US_EAST_1 - assert result[0].resource_id == REPLICATION_GROUP_ID - assert result[0].resource_arn == REPLICATION_GROUP_ARN - assert result[0].resource_tags == REPLICATION_GROUP_TAGS - def test_elasticache_clusters_automatic_failover_disabled(self): # Mock ElastiCache Service elasticache_service = MagicMock @@ -158,7 +114,7 @@ def test_elasticache_clusters_automatic_failover_enabled(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, - automatic_failover="enabled", + automatic_failover=AUTOMATIC_FAILOVER, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled_test.py index ab69a9c8449..7f5f49c27e3 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled_test.py @@ -7,6 +7,10 @@ from prowler.providers.aws.services.elasticache.elasticache_service import ( ReplicationGroup, ) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1, @@ -23,7 +27,6 @@ REPLICATION_GROUP_TAGS = [ {"Key": "environment", "Value": "test"}, ] - # Patch every AWS call using Boto3 make_api_call = botocore.client.BaseClient._make_api_call @@ -66,6 +69,8 @@ def test_elasticache_cluster_backup_disabled(self): transit_encryption=False, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7} @@ -109,6 +114,8 @@ def test_elasticache_redis_cluster_backup_enabled(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7} @@ -153,6 +160,8 @@ def test_elasticache_redis_cluster_backup_enabled_modified_retention(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 1} @@ -196,6 +205,8 @@ def test_elasticache_redis_cluster_backup_enabled_low_retention(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 3} diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled_test.py index 25c025902a8..acb63bec339 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled_test.py @@ -7,6 +7,10 @@ from prowler.providers.aws.services.elasticache.elasticache_service import ( ReplicationGroup, ) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1, @@ -68,6 +72,8 @@ def test_elasticache_replication_groups_in_transit_encryption_disabled(self): transit_encryption=False, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) @@ -112,6 +118,8 @@ def test_elasticache_replication_groups_in_transit_encryption_enabled(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled_test.py index b0f4bd4b422..8a0c6423003 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled_test.py @@ -7,6 +7,10 @@ from prowler.providers.aws.services.elasticache.elasticache_service import ( ReplicationGroup, ) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1, @@ -68,6 +72,8 @@ def test_elasticache_cluster_multi_az_disabled(self): transit_encryption=False, multi_az="disabled", tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) @@ -112,6 +118,8 @@ def test_elasticache_redis_cluster_multi_az_enabled(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled_test.py index 9c0a371701b..a413a207056 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled_test.py @@ -7,6 +7,10 @@ from prowler.providers.aws.services.elasticache.elasticache_service import ( ReplicationGroup, ) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + AUTO_MINOR_VERSION_UPGRADE, + AUTOMATIC_FAILOVER, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1, @@ -67,6 +71,8 @@ def test_elasticache_replication_groups_at_rest_encryption_disabled(self): transit_encryption=False, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) @@ -111,6 +117,8 @@ def test_elasticache_replication_groups_at_rest_encryption_enabled(self): transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION, multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, + auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + automatic_failover=AUTOMATIC_FAILOVER, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_service_test.py b/tests/providers/aws/services/elasticache/elasticache_service_test.py index 51ec5caf5e0..c0324b7fe96 100644 --- a/tests/providers/aws/services/elasticache/elasticache_service_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_service_test.py @@ -38,6 +38,7 @@ {"Key": "environment", "Value": "test"}, ] AUTO_MINOR_VERSION_UPGRADE = True +AUTOMATIC_FAILOVER = "enabled" # Mocking Access Analyzer Calls @@ -192,5 +193,5 @@ def test_describe_replication_groups(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, - automatic_failover=None, + automatic_failover="disabled", ) From 2aced89f95294c344f3d25d57712be08da59320a Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Thu, 29 Aug 2024 10:26:42 +0100 Subject: [PATCH 5/8] feat(elaticache): resolved comments --- .../__init__.py | 0 ...roup_has_automatic_failover.metadata.json} | 4 ++-- ...plication_group_has_automatic_failover.py} | 6 ++--- ...plication_group_has_automatic_failover.py} | 24 +++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) rename prowler/providers/aws/services/elasticache/{elasticache_redis_cluster_automatic_failover_enabled => elasticache_redis_replication_group_has_automatic_failover}/__init__.py (100%) rename prowler/providers/aws/services/elasticache/{elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json => elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json} (91%) rename prowler/providers/aws/services/elasticache/{elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py => elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py} (68%) rename tests/providers/aws/services/elasticache/{elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py => elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py} (81%) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/__init__.py similarity index 100% rename from prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py rename to prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/__init__.py diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json similarity index 91% rename from prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json rename to prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json index b98e5d76f85..144a4dc0957 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json @@ -1,6 +1,6 @@ { "Provider": "aws", - "CheckID": "elasticache_redis_cluster_automatic_failover_enabled", + "CheckID": "elasticache_redis_replication_group_has_automatic_failover", "CheckTitle": "Ensure Elasticache Redis clusters have automatic failover enabled.", "CheckType": [ "NIST 800-53 Controls" @@ -9,7 +9,7 @@ "SubServiceName": "", "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", - "ResourceType": "AWSElastiCacheClusters", + "ResourceType": "AWSElastiCacheReplicationGroup", "Description": "Ensure Elasticache Redis OSS cache clusters use automatic failover.", "Risk": "If automatic failover is not enabled, a failure in the primary node could result in significant downtime, impacting the availability and resilience of your application.", "RelatedUrl": "https://redis.io/docs/latest/commands/failover/", diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py similarity index 68% rename from prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py rename to prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py index e3dd36fc334..b6b67f55493 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py @@ -4,7 +4,7 @@ ) -class elasticache_redis_cluster_automatic_failover_enabled(Check): +class elasticache_redis_replication_group_has_automatic_failover(Check): def execute(self): findings = [] for repl_group in elasticache_client.replication_groups.values(): @@ -14,11 +14,11 @@ def execute(self): report.resource_arn = repl_group.arn report.resource_tags = repl_group.tags report.status = "FAIL" - report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does not have automatic failover enabled." + report.status_extended = f"Elasticache Redis replication group {repl_group.id} does not have automatic failover enabled." if repl_group.automatic_failover == "enabled": report.status = "PASS" - report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does have automatic failover enabled." + report.status_extended = f"Elasticache Redis replication group {repl_group.id} does have automatic failover enabled." findings.append(report) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py similarity index 81% rename from tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py rename to tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py index 5fd03015ab9..895468240b8 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py @@ -21,7 +21,7 @@ VPC_ID = "vpc-12345678901234567" -class Test_elasticache_redis_cluster_automatic_failover_enabled: +class Test_elasticache_redis_replication_group_has_automatic_failover: def test_elasticache_no_clusters(self): # Mock VPC Service vpc_client = MagicMock @@ -44,11 +44,11 @@ def test_elasticache_no_clusters(self): "prowler.providers.aws.services.vpc.vpc_client.vpc_client", new=vpc_client, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( - elasticache_redis_cluster_automatic_failover_enabled, + from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( + elasticache_redis_replication_group_has_automatic_failover, ) - check = elasticache_redis_cluster_automatic_failover_enabled() + check = elasticache_redis_replication_group_has_automatic_failover() result = check.execute() assert len(result) == 0 @@ -80,17 +80,17 @@ def test_elasticache_clusters_automatic_failover_disabled(self): "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", new=elasticache_service, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( - elasticache_redis_cluster_automatic_failover_enabled, + from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( + elasticache_redis_replication_group_has_automatic_failover, ) - check = elasticache_redis_cluster_automatic_failover_enabled() + check = elasticache_redis_replication_group_has_automatic_failover() result = check.execute() assert len(result) == 1 assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automatic failover enabled." + == f"Elasticache Redis replication group {REPLICATION_GROUP_ID} does not have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID @@ -125,17 +125,17 @@ def test_elasticache_clusters_automatic_failover_enabled(self): "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", new=elasticache_service, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( - elasticache_redis_cluster_automatic_failover_enabled, + from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( + elasticache_redis_replication_group_has_automatic_failover, ) - check = elasticache_redis_cluster_automatic_failover_enabled() + check = elasticache_redis_replication_group_has_automatic_failover() result = check.execute() assert len(result) == 1 assert result[0].status == "PASS" assert ( result[0].status_extended - == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does have automatic failover enabled." + == f"Elasticache Redis replication group {REPLICATION_GROUP_ID} does have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID From 61a15c69b673c15968522f6f8845841a3b750b44 Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Thu, 29 Aug 2024 10:30:18 +0100 Subject: [PATCH 6/8] chore(elasticache): put caps in ElastiCache check output --- ...sticache_redis_replication_group_has_automatic_failover.py | 4 ++-- ...sticache_redis_replication_group_has_automatic_failover.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py index b6b67f55493..57d4bcec7f0 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py @@ -14,11 +14,11 @@ def execute(self): report.resource_arn = repl_group.arn report.resource_tags = repl_group.tags report.status = "FAIL" - report.status_extended = f"Elasticache Redis replication group {repl_group.id} does not have automatic failover enabled." + report.status_extended = f"ElastiCache Redis replication group {repl_group.id} does not have automatic failover enabled." if repl_group.automatic_failover == "enabled": report.status = "PASS" - report.status_extended = f"Elasticache Redis replication group {repl_group.id} does have automatic failover enabled." + report.status_extended = f"ElastiCache Redis replication group {repl_group.id} does have automatic failover enabled." findings.append(report) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py index 895468240b8..c604b5102a5 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py @@ -90,7 +90,7 @@ def test_elasticache_clusters_automatic_failover_disabled(self): assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Elasticache Redis replication group {REPLICATION_GROUP_ID} does not have automatic failover enabled." + == f"ElastiCache Redis replication group {REPLICATION_GROUP_ID} does not have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID @@ -135,7 +135,7 @@ def test_elasticache_clusters_automatic_failover_enabled(self): assert result[0].status == "PASS" assert ( result[0].status_extended - == f"Elasticache Redis replication group {REPLICATION_GROUP_ID} does have automatic failover enabled." + == f"ElastiCache Redis replication group {REPLICATION_GROUP_ID} does have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID From 4c0faeea27b798757e0a9e31aa97eb9379282de5 Mon Sep 17 00:00:00 2001 From: HugoPBrito Date: Wed, 11 Sep 2024 12:02:07 +0200 Subject: [PATCH 7/8] feat(elasticache): improved links in metadata --- ...dis_replication_group_has_automatic_failover.metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json index 144a4dc0957..34097cc1716 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json @@ -12,7 +12,7 @@ "ResourceType": "AWSElastiCacheReplicationGroup", "Description": "Ensure Elasticache Redis OSS cache clusters use automatic failover.", "Risk": "If automatic failover is not enabled, a failure in the primary node could result in significant downtime, impacting the availability and resilience of your application.", - "RelatedUrl": "https://redis.io/docs/latest/commands/failover/", + "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/AutoFailover.html", "Remediation": { "Code": { "CLI": "", @@ -22,7 +22,7 @@ }, "Recommendation": { "Text": "Enable automatic failover for ElastiCache (Redis OSS) clusters to ensure high availability and minimize downtime during failures.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Clusters.Modify.html#Clusters.Modify.CON" + "Url": "https://redis.io/blog/highly-available-in-memory-cloud-datastores/" } }, "Categories": [], From 7b62c9c98ef63665578f1f656a802fa40acf15fb Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 12 Sep 2024 11:43:58 -0400 Subject: [PATCH 8/8] chore: enhance check --- .../__init__.py | 0 ..._automatic_failover_enabled.metadata.json} | 6 ++--- ...dis_cluster_automatic_failover_enabled.py} | 6 ++--- .../elasticache/elasticache_service.py | 2 +- ...luster_automatic_failover_enabled_test.py} | 24 +++++++++---------- 5 files changed, 18 insertions(+), 20 deletions(-) rename prowler/providers/aws/services/elasticache/{elasticache_redis_replication_group_has_automatic_failover => elasticache_redis_cluster_automatic_failover_enabled}/__init__.py (100%) rename prowler/providers/aws/services/elasticache/{elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json => elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json} (91%) rename prowler/providers/aws/services/elasticache/{elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py => elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py} (68%) rename tests/providers/aws/services/elasticache/{elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py => elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py} (81%) diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/__init__.py b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py similarity index 100% rename from prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/__init__.py rename to prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/__init__.py diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json similarity index 91% rename from prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json rename to prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json index 34097cc1716..e24abe225eb 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json @@ -1,10 +1,8 @@ { "Provider": "aws", - "CheckID": "elasticache_redis_replication_group_has_automatic_failover", + "CheckID": "elasticache_redis_cluster_automatic_failover_enabled", "CheckTitle": "Ensure Elasticache Redis clusters have automatic failover enabled.", - "CheckType": [ - "NIST 800-53 Controls" - ], + "CheckType": [], "ServiceName": "elasticache", "SubServiceName": "", "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py similarity index 68% rename from prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py rename to prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py index 57d4bcec7f0..e3dd36fc334 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.py @@ -4,7 +4,7 @@ ) -class elasticache_redis_replication_group_has_automatic_failover(Check): +class elasticache_redis_cluster_automatic_failover_enabled(Check): def execute(self): findings = [] for repl_group in elasticache_client.replication_groups.values(): @@ -14,11 +14,11 @@ def execute(self): report.resource_arn = repl_group.arn report.resource_tags = repl_group.tags report.status = "FAIL" - report.status_extended = f"ElastiCache Redis replication group {repl_group.id} does not have automatic failover enabled." + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does not have automatic failover enabled." if repl_group.automatic_failover == "enabled": report.status = "PASS" - report.status_extended = f"ElastiCache Redis replication group {repl_group.id} does have automatic failover enabled." + report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} does have automatic failover enabled." findings.append(report) diff --git a/prowler/providers/aws/services/elasticache/elasticache_service.py b/prowler/providers/aws/services/elasticache/elasticache_service.py index 23a46b55597..81aab80980d 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -107,7 +107,7 @@ def _describe_replication_groups(self, regional_client): "AutoMinorVersionUpgrade", False ), automatic_failover=repl_group.get( - "AutomaticFailover", "disabled" + "AutomaticFailoverStatus", "disabled" ), ) except Exception as error: diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py similarity index 81% rename from tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py rename to tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py index c604b5102a5..5fd03015ab9 100644 --- a/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_has_automatic_failover/elasticache_redis_replication_group_has_automatic_failover.py +++ b/tests/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled_test.py @@ -21,7 +21,7 @@ VPC_ID = "vpc-12345678901234567" -class Test_elasticache_redis_replication_group_has_automatic_failover: +class Test_elasticache_redis_cluster_automatic_failover_enabled: def test_elasticache_no_clusters(self): # Mock VPC Service vpc_client = MagicMock @@ -44,11 +44,11 @@ def test_elasticache_no_clusters(self): "prowler.providers.aws.services.vpc.vpc_client.vpc_client", new=vpc_client, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( - elasticache_redis_replication_group_has_automatic_failover, + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, ) - check = elasticache_redis_replication_group_has_automatic_failover() + check = elasticache_redis_cluster_automatic_failover_enabled() result = check.execute() assert len(result) == 0 @@ -80,17 +80,17 @@ def test_elasticache_clusters_automatic_failover_disabled(self): "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", new=elasticache_service, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( - elasticache_redis_replication_group_has_automatic_failover, + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, ) - check = elasticache_redis_replication_group_has_automatic_failover() + check = elasticache_redis_cluster_automatic_failover_enabled() result = check.execute() assert len(result) == 1 assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"ElastiCache Redis replication group {REPLICATION_GROUP_ID} does not have automatic failover enabled." + == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does not have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID @@ -125,17 +125,17 @@ def test_elasticache_clusters_automatic_failover_enabled(self): "prowler.providers.aws.services.elasticache.elasticache_service.ElastiCache", new=elasticache_service, ): - from prowler.providers.aws.services.elasticache.elasticache_redis_replication_group_has_automatic_failover.elasticache_redis_replication_group_has_automatic_failover import ( - elasticache_redis_replication_group_has_automatic_failover, + from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_automatic_failover_enabled.elasticache_redis_cluster_automatic_failover_enabled import ( + elasticache_redis_cluster_automatic_failover_enabled, ) - check = elasticache_redis_replication_group_has_automatic_failover() + check = elasticache_redis_cluster_automatic_failover_enabled() result = check.execute() assert len(result) == 1 assert result[0].status == "PASS" assert ( result[0].status_extended - == f"ElastiCache Redis replication group {REPLICATION_GROUP_ID} does have automatic failover enabled." + == f"Elasticache Redis cache cluster {REPLICATION_GROUP_ID} does have automatic failover enabled." ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == REPLICATION_GROUP_ID