mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
feat(Elasticache): Additional Elasticache checks (#4317)
Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_cluster_backup_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Cluster has automatic backups enabled.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "elasticache",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "high",
|
||||
"ResourceType": "AWSElastiCacheClusters",
|
||||
"Description": "Ensure Elasticache Cluster has automatic backups enabled.",
|
||||
"Risk": "Ensure that your Amazon ElastiCache Redis cache clusters have a sufficient backup retention period set in order to fulfill your organization's compliance requirements. The retention period represents the number of days for which Amazon ElastiCache service retains automatic Redis cluster backups before deleting them.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-1",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws elasticache modify-replication-group --region <value> --replication-group-id <value> --snapshot-retention-limit <value> --apply-immediately",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-that-amazon-elasticache-redis-clusters-have-automatic-backup-turned-on/"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure Elasticache Cluster has automatic backups enabled.",
|
||||
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-1"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
elasticache_client,
|
||||
)
|
||||
|
||||
|
||||
class elasticache_cluster_backup_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.status = "FAIL"
|
||||
report.status_extended = f"Elasticache Cluster {repl_group.id} does not have automated snapshot backups enabled."
|
||||
if repl_group.snapshot_retention > elasticache_client.audit_config.get(
|
||||
"minimum_snapshot_retention_period", 7
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Elasticache Cluster {repl_group.id} has automated snapshot backups enabled with retention period {repl_group.snapshot_retention} days."
|
||||
else:
|
||||
if repl_group.snapshot_retention > 0:
|
||||
report.status = "FAIL"
|
||||
report.check_metadata.Severity = "low"
|
||||
report.status_extended = f"Elasticache Cluster {repl_group.id} has automated snapshot backups enabled with retention period {repl_group.snapshot_retention} days. Recommended to increase the snapshot retention period to a minimum of 7 days."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_cluster_multi_az_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Cluster has Multi-AZ enabled.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "elasticache",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AWSElastiCacheClusters",
|
||||
"Description": "Ensure Elasticache 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": {
|
||||
"Code": {
|
||||
"CLI": "aws elasticache modify-replication-group --region <value> --replication-group-id <value> --multi-az-enabled --apply-immediately",
|
||||
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#",
|
||||
"Other": "",
|
||||
"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 Cluster has Multi-AZ enabled.",
|
||||
"Url": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
elasticache_client,
|
||||
)
|
||||
|
||||
|
||||
class elasticache_cluster_multi_az_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.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Elasticache Cluster {repl_group.id} does not have Multi-AZ enabled."
|
||||
)
|
||||
if repl_group.multi_az == "enabled":
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Elasticache Cluster {repl_group.id} has Multi-AZ enabled."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_replication_group_encrypted_at_rest",
|
||||
"CheckTitle": "Ensure Elasticache Replication Groups have at rest encryption enabled.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "elasticache",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AWSElastiCacheReplicationGroups",
|
||||
"Description": "Ensure Elasticache Replication Groups have at rest encryption enabled.",
|
||||
"Risk": "There is a risk of exposing sensitive data if Elasticache Replication Group does not have at rest encryption enabled.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-4",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "https://docs.prowler.com/checks/aws/general-policies/general_9/",
|
||||
"NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/general_9/",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_9/"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure your Elasticache replication groups have at rest encryption enabled.",
|
||||
"Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html#at-rest-encryption-enable"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
elasticache_client,
|
||||
)
|
||||
|
||||
|
||||
class elasticache_replication_group_encrypted_at_rest(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.status = "FAIL"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} does not have at rest encryption enabled."
|
||||
if repl_group.encrypted:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} has at rest encryption enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_replication_group_encrypted_in_transit",
|
||||
"CheckTitle": "Ensure Elasticache Replication Groups have in transit encryption enabled.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "elasticache",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AWSElastiCacheReplicationGroups",
|
||||
"Description": "Ensure Elasticache Replication Groups have in transit encryption enabled.",
|
||||
"Risk": "There is a risk of exposing sensitive data if Elasticache Replication Group does not have in transit encryption enabled.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-5",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "https://docs.prowler.com/checks/aws/general-policies/general_10/",
|
||||
"NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/general_10/",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_10/"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure your Elasticache replication groups have in transit encryption enabled.",
|
||||
"Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
elasticache_client,
|
||||
)
|
||||
|
||||
|
||||
class elasticache_replication_group_encrypted_in_transit(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.status = "FAIL"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} does not have in transit encryption enabled."
|
||||
if repl_group.transit_encryption:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} has in transit encryption enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -14,9 +14,11 @@ class ElastiCache(AWSService):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.clusters = {}
|
||||
self.replication_groups = {}
|
||||
self.__threading_call__(self.__describe_cache_clusters__)
|
||||
self.__threading_call__(self.__describe_cache_subnet_groups__)
|
||||
self.__list_tags_for_resource__()
|
||||
self.__threading_call__(self.__describe_replication_groups__)
|
||||
|
||||
def __describe_cache_clusters__(self, regional_client):
|
||||
logger.info("Elasticache - Describing Cache Clusters...")
|
||||
@@ -32,6 +34,11 @@ class ElastiCache(AWSService):
|
||||
id=cache_cluster["CacheClusterId"],
|
||||
arn=cluster_arn,
|
||||
region=regional_client.region,
|
||||
security_groups=[
|
||||
sg["SecurityGroupId"]
|
||||
for sg in cache_cluster["SecurityGroups"]
|
||||
if sg["Status"] == "active"
|
||||
],
|
||||
cache_subnet_group_id=cache_cluster.get(
|
||||
"CacheSubnetGroupName", None
|
||||
),
|
||||
@@ -95,11 +102,48 @@ class ElastiCache(AWSService):
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __describe_replication_groups__(self, regional_client):
|
||||
logger.info("Elasticache - Describing Replication Groups...")
|
||||
try:
|
||||
for repl_group in regional_client.describe_replication_groups()[
|
||||
"ReplicationGroups"
|
||||
]:
|
||||
replication_arn = repl_group["ARN"]
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(replication_arn, self.audit_resources)
|
||||
):
|
||||
self.replication_groups[replication_arn] = ReplicationGroup(
|
||||
id=repl_group["ReplicationGroupId"],
|
||||
arn=replication_arn,
|
||||
region=regional_client.region,
|
||||
status=repl_group["Status"],
|
||||
snapshot_retention=repl_group.get("SnapshotRetentionLimit", 0),
|
||||
encrypted=repl_group["AtRestEncryptionEnabled"],
|
||||
transit_encryption=repl_group["TransitEncryptionEnabled"],
|
||||
multi_az=repl_group["MultiAZ"],
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
class Cluster(BaseModel):
|
||||
id: str
|
||||
arn: str
|
||||
region: str
|
||||
security_groups: list[str] = []
|
||||
cache_subnet_group_id: Optional[str]
|
||||
subnets: list = []
|
||||
tags: Optional[list]
|
||||
|
||||
|
||||
class ReplicationGroup(BaseModel):
|
||||
id: str
|
||||
arn: str
|
||||
region: str
|
||||
status: str
|
||||
snapshot_retention: int
|
||||
encrypted: bool
|
||||
transit_encryption: bool
|
||||
multi_az: str
|
||||
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
from unittest import mock
|
||||
|
||||
import botocore
|
||||
from mock import MagicMock
|
||||
from moto import mock_aws
|
||||
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import (
|
||||
ReplicationGroup,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
REPLICATION_GROUP_ID = "clustered-redis"
|
||||
REPLICATION_GROUP_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:replicationgroup:{REPLICATION_GROUP_ID}"
|
||||
REPLICATION_GROUP_STATUS = "available"
|
||||
REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
class Test_elasticache_cluster_backup_enabled:
|
||||
@mock_aws
|
||||
def test_elasticache_no_replication_groups(self):
|
||||
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.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_client,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_cluster_backup_enabled.elasticache_cluster_backup_enabled import (
|
||||
elasticache_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_elasticache_cluster_backup_disabled(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.replication_groups = {}
|
||||
|
||||
elasticache_client.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=0,
|
||||
encrypted=False,
|
||||
transit_encryption=False,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7}
|
||||
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_client,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_cluster_backup_enabled.elasticache_cluster_backup_enabled import (
|
||||
elasticache_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Cluster {REPLICATION_GROUP_ID} does not have automated snapshot backups 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
|
||||
|
||||
def test_elasticache_cluster_backup_enabled(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.replication_groups = {}
|
||||
|
||||
elasticache_client.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=9,
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7}
|
||||
|
||||
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_client,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_cluster_backup_enabled.elasticache_cluster_backup_enabled import (
|
||||
elasticache_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Cluster {REPLICATION_GROUP_ID} has automated snapshot backups enabled with retention period 9 days."
|
||||
)
|
||||
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
|
||||
|
||||
def test_elasticache_cluster_backup_enabled_modified_retention(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.replication_groups = {}
|
||||
|
||||
elasticache_client.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=3,
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 1}
|
||||
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_client,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_cluster_backup_enabled.elasticache_cluster_backup_enabled import (
|
||||
elasticache_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Cluster {REPLICATION_GROUP_ID} has automated snapshot backups enabled with retention period 3 days."
|
||||
)
|
||||
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
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
from unittest import mock
|
||||
|
||||
import botocore
|
||||
from mock import MagicMock
|
||||
from moto import mock_aws
|
||||
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import (
|
||||
ReplicationGroup,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
REPLICATION_GROUP_ID = "clustered-redis"
|
||||
REPLICATION_GROUP_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:replicationgroup:{REPLICATION_GROUP_ID}"
|
||||
REPLICATION_GROUP_STATUS = "available"
|
||||
REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
class Test_elasticache_replication_group_multi_az_enabled:
|
||||
@mock_aws
|
||||
def test_elasticache_no_replication_groups(self):
|
||||
|
||||
# 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,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_cluster_multi_az_enabled.elasticache_cluster_multi_az_enabled import (
|
||||
elasticache_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_elasticache_cluster_multi_az_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=False,
|
||||
transit_encryption=False,
|
||||
multi_az="disabled",
|
||||
)
|
||||
)
|
||||
|
||||
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_cluster_multi_az_enabled.elasticache_cluster_multi_az_enabled import (
|
||||
elasticache_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Cluster {REPLICATION_GROUP_ID} does not have Multi-AZ 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
|
||||
|
||||
def test_elasticache_cluster_multi_az_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=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
)
|
||||
|
||||
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_cluster_multi_az_enabled.elasticache_cluster_multi_az_enabled import (
|
||||
elasticache_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Cluster {REPLICATION_GROUP_ID} has Multi-AZ 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
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
from unittest import mock
|
||||
|
||||
import botocore
|
||||
from mock import MagicMock
|
||||
from moto import mock_aws
|
||||
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import (
|
||||
ReplicationGroup,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
REPLICATION_GROUP_ID = "clustered-redis"
|
||||
REPLICATION_GROUP_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:replicationgroup:{REPLICATION_GROUP_ID}"
|
||||
REPLICATION_GROUP_STATUS = "available"
|
||||
REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = True
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
@mock_aws
|
||||
def test_elasticache_no_replication_groups(self):
|
||||
|
||||
# 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,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_replication_group_encrypted_at_rest.elasticache_replication_group_encrypted_at_rest import (
|
||||
elasticache_replication_group_encrypted_at_rest,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_elasticache_replication_groups_at_rest_encryption_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=False,
|
||||
transit_encryption=False,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
)
|
||||
|
||||
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_replication_group_encrypted_at_rest.elasticache_replication_group_encrypted_at_rest import (
|
||||
elasticache_replication_group_encrypted_at_rest,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Replication Group {REPLICATION_GROUP_ID} does not have at rest encryption 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
|
||||
|
||||
def test_elasticache_replication_groups_at_rest_encryption_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=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
)
|
||||
|
||||
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_replication_group_encrypted_at_rest.elasticache_replication_group_encrypted_at_rest import (
|
||||
elasticache_replication_group_encrypted_at_rest,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Replication Group {REPLICATION_GROUP_ID} has at rest encryption 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
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
from unittest import mock
|
||||
|
||||
import botocore
|
||||
from mock import MagicMock
|
||||
from moto import mock_aws
|
||||
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import (
|
||||
ReplicationGroup,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
REPLICATION_GROUP_ID = "clustered-redis"
|
||||
REPLICATION_GROUP_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:replicationgroup:{REPLICATION_GROUP_ID}"
|
||||
REPLICATION_GROUP_STATUS = "available"
|
||||
REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
@mock_aws
|
||||
def test_elasticache_no_replication_groups(self):
|
||||
|
||||
# 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,
|
||||
):
|
||||
from prowler.providers.aws.services.elasticache.elasticache_replication_group_encrypted_in_transit.elasticache_replication_group_encrypted_in_transit import (
|
||||
elasticache_replication_group_encrypted_in_transit,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_elasticache_replication_groups_in_transit_encryption_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,
|
||||
)
|
||||
)
|
||||
|
||||
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_replication_group_encrypted_in_transit.elasticache_replication_group_encrypted_in_transit import (
|
||||
elasticache_replication_group_encrypted_in_transit,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Replication Group {REPLICATION_GROUP_ID} does not have in transit encryption 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
|
||||
|
||||
def test_elasticache_replication_groups_in_transit_encryption_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=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
)
|
||||
)
|
||||
|
||||
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_replication_group_encrypted_in_transit.elasticache_replication_group_encrypted_in_transit import (
|
||||
elasticache_replication_group_encrypted_in_transit,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Replication Group {REPLICATION_GROUP_ID} has in transit encryption 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
|
||||
@@ -4,6 +4,7 @@ from mock import patch
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import (
|
||||
Cluster,
|
||||
ElastiCache,
|
||||
ReplicationGroup,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
@@ -25,6 +26,14 @@ ELASTICACHE_CLUSTER_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
REPLICATION_GROUP_ID = "clustered-redis"
|
||||
REPLICATION_GROUP_ARN = f"arn:aws:elasticache:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:replicationgroup:{REPLICATION_GROUP_ID}"
|
||||
REPLICATION_GROUP_STATUS = "available"
|
||||
REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
|
||||
# Mocking Access Analyzer Calls
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
@@ -44,6 +53,7 @@ def mock_make_api_call(self, operation_name, kwargs):
|
||||
"CacheClusterId": ELASTICACHE_CLUSTER_NAME,
|
||||
"CacheSubnetGroupName": SUBNET_GROUP_NAME,
|
||||
"ARN": ELASTICACHE_CLUSTER_ARN,
|
||||
"SecurityGroups": [],
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -77,7 +87,20 @@ def mock_make_api_call(self, operation_name, kwargs):
|
||||
}
|
||||
if operation_name == "ListTagsForResource":
|
||||
return {"TagList": ELASTICACHE_CLUSTER_TAGS}
|
||||
|
||||
if operation_name == "DescribeReplicationGroups":
|
||||
return {
|
||||
"ReplicationGroups": [
|
||||
{
|
||||
"ReplicationGroupId": REPLICATION_GROUP_ID,
|
||||
"Status": REPLICATION_GROUP_STATUS,
|
||||
"SnapshotRetentionLimit": REPLICATION_GROUP_SNAPSHOT_RETENTION,
|
||||
"MultiAZ": REPLICATION_GROUP_MULTI_AZ,
|
||||
"TransitEncryptionEnabled": REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
"AtRestEncryptionEnabled": REPLICATION_GROUP_ENCRYPTION,
|
||||
"ARN": REPLICATION_GROUP_ARN,
|
||||
},
|
||||
]
|
||||
}
|
||||
return make_api_call(self, operation_name, kwargs)
|
||||
|
||||
|
||||
@@ -132,7 +155,28 @@ class Test_ElastiCache_Service:
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
security_groups=[],
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
subnets=[SUBNET_1, SUBNET_2],
|
||||
tags=ELASTICACHE_CLUSTER_TAGS,
|
||||
)
|
||||
|
||||
# Test ElastiCache Replication Groups
|
||||
def test_describe_replication_groups(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
elasticache = ElastiCache(aws_provider)
|
||||
|
||||
assert len(elasticache.replication_groups) == 1
|
||||
assert elasticache.replication_groups[REPLICATION_GROUP_ARN]
|
||||
assert elasticache.replication_groups[
|
||||
REPLICATION_GROUP_ARN
|
||||
] == ReplicationGroup(
|
||||
id=REPLICATION_GROUP_ID,
|
||||
arn=REPLICATION_GROUP_ARN,
|
||||
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,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user