diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json index 054cdf948cb..362f7e0a01d 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json @@ -1,14 +1,14 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_multi_az_enabled", - "CheckTitle": "Ensure Elasticache Elasticache Redis cache cluster has Multi-AZ enabled.", + "CheckTitle": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", "CheckType": [], "ServiceName": "elasticache", "SubServiceName": "", "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", - "ResourceType": "Other", - "Description": "Ensure Elasticache Elasticache Redis cache cluster has Multi-AZ enabled.", + "ResourceType": "AWSElastiCacheClusters", + "Description": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", "Risk": "Ensure that your Amazon ElastiCache Redis cache clusters has Multi-AZ enabled.", "RelatedUrl": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#", "Remediation": { @@ -19,7 +19,7 @@ "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": "Ensure Elasticache Elasticache Redis cache cluster has Multi-AZ enabled.", + "Text": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", "Url": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#" } }, diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/__init__.py b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json new file mode 100644 index 00000000000..941799aa18e --- /dev/null +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "elasticache_redis_replication_group_auth_enabled", + "CheckTitle": "Ensure Elasticache Elasticache Redis replication groups of earlier versions should have Redis OSS AUTH enabled.", + "CheckType": [ + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls" + ], + "ServiceName": "elasticache", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "medium", + "ResourceType": "Other", + "Description": "Ensure Elasticache Redis replication groups of earlier versions use Redis OSS AUTH.", + "Risk": "Without Redis AUTH enabled, your ElastiCache (Redis) instance is vulnerable to unauthorized access and potential data breaches.", + "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-6", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable Redis AUTH to require authentication before accessing your Redis instance, and for Redis 6.0 and later, consider implementing Role-Based Access Control (RBAC) for enhanced security.", + "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html#auth-modifyng-token" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.py b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.py new file mode 100644 index 00000000000..6bdaa1170bd --- /dev/null +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.py @@ -0,0 +1,33 @@ +from packaging import version + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.elasticache.elasticache_client import ( + elasticache_client, +) + + +class elasticache_redis_replication_group_auth_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 + + if version.parse(repl_group.engine_version) < version.parse("6.0"): + if not repl_group.auth_token_enabled: + report.status = "FAIL" + report.status_extended = f"Elasticache Redis replication group {repl_group.id}(v{repl_group.engine_version}) does not have AUTH enabled." + + else: + report.status = "PASS" + report.status_extended = f"Elasticache Redis replication group {repl_group.id}(v{repl_group.engine_version}) does have AUTH enabled." + else: + report.status = "MANUAL" + report.status_extended = f"Elasticache Redis replication group {repl_group.id} has version {repl_group.engine_version} which supports Redis ACLs. Please review the ACL configuration." + + 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 81aab80980d..f19c57ecf6a 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_service.py +++ b/prowler/providers/aws/services/elasticache/elasticache_service.py @@ -41,6 +41,10 @@ def _describe_cache_clusters(self, regional_client): auto_minor_version_upgrade=cache_cluster.get( "AutoMinorVersionUpgrade", False ), + engine_version=cache_cluster.get("EngineVersion", "0.0"), + auth_token_enabled=cache_cluster.get( + "AuthTokenEnabled", False + ), ) except Exception as error: logger.error( @@ -90,6 +94,13 @@ def _describe_replication_groups(self, regional_client): if not self.audit_resources or ( is_resource_filtered(replication_arn, self.audit_resources) ): + # Get first cluster version as they all have the same unless an upgrade is being made + member_clusters = repl_group.get("MemberClusters", []) + engine_version = "0.0" + if member_clusters: + cluster_arn = f"arn:aws:elasticache:{regional_client.region}:{self.audited_account}:cluster:{member_clusters[0]}" + engine_version = self.clusters[cluster_arn].engine_version + self.replication_groups[replication_arn] = ReplicationGroup( id=repl_group["ReplicationGroupId"], arn=replication_arn, @@ -107,8 +118,12 @@ def _describe_replication_groups(self, regional_client): "AutoMinorVersionUpgrade", False ), automatic_failover=repl_group.get( - "AutomaticFailoverStatus", "disabled" + "AutomaticFailover", "disabled" + ), + auth_token_enabled=repl_group.get( + "AuthTokenEnabled", False ), + engine_version=engine_version, ) except Exception as error: logger.error( @@ -167,6 +182,8 @@ class Cluster(BaseModel): subnets: list = [] tags: Optional[list] auto_minor_version_upgrade: bool = False + engine_version: Optional[str] + auth_token_enabled: Optional[bool] class ReplicationGroup(BaseModel): @@ -179,5 +196,7 @@ class ReplicationGroup(BaseModel): transit_encryption: bool multi_az: str tags: Optional[list] + auth_token_enabled: bool auto_minor_version_upgrade: bool automatic_failover: str + engine_version: 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 152ba48a600..553b3788205 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 @@ -70,6 +70,8 @@ def test_elasticache_clusters_auto_minor_version_upgrades_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) @@ -115,6 +117,8 @@ def test_elasticache_clusters_auto_minor_version_upgrades_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=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 index 5fd03015ab9..a9863be9076 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 @@ -70,6 +70,8 @@ def test_elasticache_clusters_automatic_failover_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover="disabled", + engine_version="6.0", + auth_token_enabled=False, ) ) @@ -115,6 +117,8 @@ def test_elasticache_clusters_automatic_failover_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) 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 7f5f49c27e3..a2806ad0172 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 @@ -71,6 +71,8 @@ def test_elasticache_cluster_backup_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7} @@ -116,6 +118,8 @@ def test_elasticache_redis_cluster_backup_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7} @@ -162,6 +166,8 @@ def test_elasticache_redis_cluster_backup_enabled_modified_retention(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) elasticache_client.audit_config = {"minimum_snapshot_retention_period": 1} @@ -207,6 +213,8 @@ def test_elasticache_redis_cluster_backup_enabled_low_retention(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=not AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) 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 acb63bec339..e6db0f4997a 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 @@ -74,6 +74,8 @@ def test_elasticache_replication_groups_in_transit_encryption_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) @@ -120,6 +122,8 @@ def test_elasticache_replication_groups_in_transit_encryption_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) 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 8a0c6423003..c82679ccd0b 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 @@ -74,6 +74,8 @@ def test_elasticache_cluster_multi_az_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) @@ -120,6 +122,8 @@ def test_elasticache_redis_cluster_multi_az_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) 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 a413a207056..913f5f89485 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 @@ -73,6 +73,8 @@ def test_elasticache_replication_groups_at_rest_encryption_disabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) @@ -119,6 +121,8 @@ def test_elasticache_replication_groups_at_rest_encryption_enabled(self): tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, automatic_failover=AUTOMATIC_FAILOVER, + engine_version="6.0", + auth_token_enabled=False, ) ) diff --git a/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled_test.py b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled_test.py new file mode 100644 index 00000000000..f7425d53985 --- /dev/null +++ b/tests/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled_test.py @@ -0,0 +1,227 @@ +from unittest import mock + +from mock import MagicMock, patch +from moto import mock_aws + +from prowler.providers.aws.services.elasticache.elasticache_service import ( + ReplicationGroup, +) +from tests.providers.aws.services.elasticache.elasticache_service_test import ( + 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, + mock_make_api_call, +) +from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider + +VPC_ID = "vpc-12345678901234567" + + +# Patch every AWS call using Boto3 +@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) +class Test_elasticache_redis_replication_group_auth_enabled: + @mock_aws + def test_elasticache_no_replication_groups(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_replication_group_auth_enabled.elasticache_redis_replication_group_auth_enabled import ( + elasticache_redis_replication_group_auth_enabled, + ) + + check = elasticache_redis_replication_group_auth_enabled() + result = check.execute() + assert len(result) == 0 + + def test_elasticache_no_old_redis_replication_groups(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + engine_version = "6.0" + 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, + automatic_failover="enabled", + auto_minor_version_upgrade=False, + engine_version=engine_version, + auth_token_enabled=False, + ) + } + + # Mock VPC Service + vpc_client = MagicMock + vpc_client.vpc_subnets = {} + + 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_replication_group_auth_enabled.elasticache_redis_replication_group_auth_enabled import ( + elasticache_redis_replication_group_auth_enabled, + ) + + check = elasticache_redis_replication_group_auth_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Elasticache Redis replication group {REPLICATION_GROUP_ID} has version {engine_version} which supports Redis ACLs. Please review the ACL configuration." + ) + 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_redis_replication_group_auth_enabled(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + engine_version = "5.0" + 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, + automatic_failover="enabled", + auto_minor_version_upgrade=False, + engine_version=engine_version, + auth_token_enabled=True, + ) + } + + # Mock VPC Service + vpc_client = MagicMock + vpc_client.vpc_subnets = {} + + 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_replication_group_auth_enabled.elasticache_redis_replication_group_auth_enabled import ( + elasticache_redis_replication_group_auth_enabled, + ) + + check = elasticache_redis_replication_group_auth_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}(v{engine_version}) does have AUTH 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_redis_cluster_auth_disabled(self): + # Mock ElastiCache Service + elasticache_service = MagicMock + engine_version = "4.2" + 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, + automatic_failover="enabled", + auto_minor_version_upgrade=False, + engine_version=engine_version, + auth_token_enabled=False, + ) + } + + # Mock VPC Service + vpc_client = MagicMock + vpc_client.vpc_subnets = {} + + 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_replication_group_auth_enabled.elasticache_redis_replication_group_auth_enabled import ( + elasticache_redis_replication_group_auth_enabled, + ) + + check = elasticache_redis_replication_group_auth_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}(v{engine_version}) does not have AUTH 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 c0324b7fe96..1c5bbba6610 100644 --- a/tests/providers/aws/services/elasticache/elasticache_service_test.py +++ b/tests/providers/aws/services/elasticache/elasticache_service_test.py @@ -19,7 +19,7 @@ SUBNET_2 = "subnet-2" ELASTICACHE_CLUSTER_NAME = "test-cluster" -ELASTICACHE_CLUSTER_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:{ELASTICACHE_CLUSTER_NAME}" +ELASTICACHE_CLUSTER_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:{ELASTICACHE_CLUSTER_NAME}" ELASTICACHE_ENGINE = "redis" ELASTICACHE_ENGINE_MEMCACHED = "memcached" @@ -63,6 +63,8 @@ def mock_make_api_call(self, operation_name, kwargs): "Engine": ELASTICACHE_ENGINE, "SecurityGroups": [], "AutoMinorVersionUpgrade": AUTO_MINOR_VERSION_UPGRADE, + "EngineVersion": "6.0", + "AuthTokenEnabled": False, }, ] } @@ -108,6 +110,8 @@ def mock_make_api_call(self, operation_name, kwargs): "AtRestEncryptionEnabled": REPLICATION_GROUP_ENCRYPTION, "ARN": REPLICATION_GROUP_ARN, "AutoMinorVersionUpgrade": AUTO_MINOR_VERSION_UPGRADE, + "Memberclusters": [ELASTICACHE_CLUSTER_NAME], + "AuthTokenEnabled": False, }, ] } @@ -162,7 +166,6 @@ def test_describe_cache_clusters(self): assert elasticache.clusters[ELASTICACHE_CLUSTER_ARN] assert elasticache.clusters[ELASTICACHE_CLUSTER_ARN] == Cluster( arn=ELASTICACHE_CLUSTER_ARN, - name=ELASTICACHE_CLUSTER_NAME, id=ELASTICACHE_CLUSTER_NAME, engine=ELASTICACHE_ENGINE, region=AWS_REGION_US_EAST_1, @@ -171,9 +174,11 @@ def test_describe_cache_clusters(self): subnets=[SUBNET_1, SUBNET_2], tags=ELASTICACHE_CLUSTER_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + engine_version=6.0, + auth_token_enabled=False, ) - # Test Elasticache Redis cache clusters + # Test Elasticache Redis replication_groups def test_describe_replication_groups(self): aws_provider = set_mocked_aws_provider() elasticache = ElastiCache(aws_provider) @@ -193,5 +198,7 @@ def test_describe_replication_groups(self): multi_az=REPLICATION_GROUP_MULTI_AZ, tags=REPLICATION_GROUP_TAGS, auto_minor_version_upgrade=AUTO_MINOR_VERSION_UPGRADE, + auth_token_enabled=False, automatic_failover="disabled", + engine_version="0.0", )