mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 04:21:52 +00:00
chore(elasticache): enhance service and checks (#4329)
This commit is contained in:
+10
-4
@@ -16,9 +16,12 @@ class elasticache_cluster_uses_public_subnet(Check):
|
||||
report.region = cluster.region
|
||||
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Cluster {cluster.id} is not using public subnets."
|
||||
)
|
||||
if cluster.engine == "redis":
|
||||
report.status_extended = (
|
||||
f"Elasticache Redis Node {cluster.id} is not using public subnets."
|
||||
)
|
||||
else:
|
||||
report.status_extended = f"Elasticache Memcached Cluster {cluster.id} is not using public subnets."
|
||||
|
||||
public_subnets = []
|
||||
for subnet in cluster.subnets:
|
||||
@@ -30,7 +33,10 @@ class elasticache_cluster_uses_public_subnet(Check):
|
||||
|
||||
if len(public_subnets) > 0:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Cluster {cluster.id} is using {', '.join(public_subnets)} public subnets."
|
||||
if cluster.engine == "redis":
|
||||
report.status_extended = f"Elasticache Redis Node {cluster.id} is using {', '.join(public_subnets)} public subnets."
|
||||
else:
|
||||
report.status_extended = f"Elasticache Memcached Cluster {cluster.id} is using {', '.join(public_subnets)} public subnets."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_cluster_backup_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Cluster has automatic backups enabled.",
|
||||
"CheckID": "elasticache_redis_cluster_backup_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Redis cache 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.",
|
||||
"Description": "Ensure Elasticache Redis cache 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": {
|
||||
+5
-4
@@ -4,7 +4,7 @@ from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
)
|
||||
|
||||
|
||||
class elasticache_cluster_backup_enabled(Check):
|
||||
class elasticache_redis_cluster_backup_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for repl_group in elasticache_client.replication_groups.values():
|
||||
@@ -12,18 +12,19 @@ class elasticache_cluster_backup_enabled(Check):
|
||||
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 = "FAIL"
|
||||
report.status_extended = f"Elasticache Cluster {repl_group.id} does not have automated snapshot backups enabled."
|
||||
report.status_extended = f"Elasticache Redis cache 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."
|
||||
report.status_extended = f"Elasticache Redis cache 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."
|
||||
report.status_extended = f"Elasticache Redis cache 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)
|
||||
|
||||
+5
-5
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_replication_group_encrypted_in_transit",
|
||||
"CheckTitle": "Ensure Elasticache Replication Groups have in transit encryption enabled.",
|
||||
"CheckID": "elasticache_redis_cluster_in_transit_encryption_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Redis cache clusters 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.",
|
||||
"Description": "Ensure Elasticache Redis cache clusters have in transit encryption enabled.",
|
||||
"Risk": "There is a risk of exposing sensitive data if Elasticache Redis cache cluster does not have in transit encryption enabled.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-5",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
@@ -19,7 +19,7 @@
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_10/"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure your Elasticache replication groups have in transit encryption enabled.",
|
||||
"Text": "Ensure your Elasticache Redis cache clusters have in transit encryption enabled.",
|
||||
"Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html"
|
||||
}
|
||||
},
|
||||
+4
-3
@@ -4,7 +4,7 @@ from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
)
|
||||
|
||||
|
||||
class elasticache_replication_group_encrypted_in_transit(Check):
|
||||
class elasticache_redis_cluster_in_transit_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for repl_group in elasticache_client.replication_groups.values():
|
||||
@@ -12,11 +12,12 @@ class elasticache_replication_group_encrypted_in_transit(Check):
|
||||
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 = "FAIL"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} does not have in transit encryption enabled."
|
||||
report.status_extended = f"Elasticache Redis cache cluster {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."
|
||||
report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} has in transit encryption enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_cluster_multi_az_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Cluster has Multi-AZ enabled.",
|
||||
"CheckID": "elasticache_redis_cluster_multi_az_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Elasticache Redis cache 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.",
|
||||
"Description": "Ensure Elasticache 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 Cluster has Multi-AZ enabled.",
|
||||
"Text": "Ensure Elasticache Elasticache Redis cache cluster has Multi-AZ enabled.",
|
||||
"Url": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#"
|
||||
}
|
||||
},
|
||||
+4
-7
@@ -4,7 +4,7 @@ from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
)
|
||||
|
||||
|
||||
class elasticache_cluster_multi_az_enabled(Check):
|
||||
class elasticache_redis_cluster_multi_az_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for repl_group in elasticache_client.replication_groups.values():
|
||||
@@ -12,15 +12,12 @@ class elasticache_cluster_multi_az_enabled(Check):
|
||||
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 = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Elasticache Cluster {repl_group.id} does not have Multi-AZ enabled."
|
||||
)
|
||||
report.status_extended = f"Elasticache Redis cache 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."
|
||||
)
|
||||
report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} has Multi-AZ enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
+5
-5
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "elasticache_replication_group_encrypted_at_rest",
|
||||
"CheckTitle": "Ensure Elasticache Replication Groups have at rest encryption enabled.",
|
||||
"CheckID": "elasticache_redis_cluster_rest_encryption_enabled",
|
||||
"CheckTitle": "Ensure Elasticache Redis cache clusters 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.",
|
||||
"Description": "Ensure Elasticache Redis cache clusters have at rest encryption enabled.",
|
||||
"Risk": "There is a risk of exposing sensitive data if Elasticache Redis cache clusters does not have at rest encryption enabled.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-4",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
@@ -19,7 +19,7 @@
|
||||
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_9/"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure your Elasticache replication groups have at rest encryption enabled.",
|
||||
"Text": "Ensure your Elasticache Redis cache clusters have at rest encryption enabled.",
|
||||
"Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html#at-rest-encryption-enable"
|
||||
}
|
||||
},
|
||||
+4
-3
@@ -4,7 +4,7 @@ from prowler.providers.aws.services.elasticache.elasticache_client import (
|
||||
)
|
||||
|
||||
|
||||
class elasticache_replication_group_encrypted_at_rest(Check):
|
||||
class elasticache_redis_cluster_rest_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for repl_group in elasticache_client.replication_groups.values():
|
||||
@@ -12,11 +12,12 @@ class elasticache_replication_group_encrypted_at_rest(Check):
|
||||
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 = "FAIL"
|
||||
report.status_extended = f"Elasticache Replication Group {repl_group.id} does not have at rest encryption enabled."
|
||||
report.status_extended = f"Elasticache Redis cache cluster {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."
|
||||
report.status_extended = f"Elasticache Redis cache cluster {repl_group.id} has at rest encryption enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
@@ -17,31 +16,33 @@ class ElastiCache(AWSService):
|
||||
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__)
|
||||
self.__list_tags_for_resource__()
|
||||
|
||||
def __describe_cache_clusters__(self, regional_client):
|
||||
# Memcached Clusters and Redis Nodes
|
||||
logger.info("Elasticache - Describing Cache Clusters...")
|
||||
try:
|
||||
for cache_cluster in regional_client.describe_cache_clusters()[
|
||||
"CacheClusters"
|
||||
]:
|
||||
cluster_arn = cache_cluster["ARN"]
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(cluster_arn, self.audit_resources)
|
||||
):
|
||||
self.clusters[cluster_arn] = Cluster(
|
||||
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
|
||||
),
|
||||
try:
|
||||
cluster_arn = cache_cluster["ARN"]
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(cluster_arn, self.audit_resources)
|
||||
):
|
||||
self.clusters[cluster_arn] = Cluster(
|
||||
id=cache_cluster["CacheClusterId"],
|
||||
arn=cluster_arn,
|
||||
region=regional_client.region,
|
||||
engine=cache_cluster["Engine"],
|
||||
cache_subnet_group_id=cache_cluster.get(
|
||||
"CacheSubnetGroupName", None
|
||||
),
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
@@ -75,23 +76,31 @@ class ElastiCache(AWSService):
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __list_tags_for_resource__(self):
|
||||
logger.info("Elasticache - Listing Tags...")
|
||||
def __describe_replication_groups__(self, regional_client):
|
||||
# Redis Clusters
|
||||
logger.info("Elasticache - Describing Replication Groups...")
|
||||
try:
|
||||
for cluster in self.clusters.values():
|
||||
for repl_group in regional_client.describe_replication_groups()[
|
||||
"ReplicationGroups"
|
||||
]:
|
||||
try:
|
||||
regional_client = self.regional_clients[cluster.region]
|
||||
cluster.tags = regional_client.list_tags_for_resource(
|
||||
ResourceName=cluster.arn
|
||||
)["TagList"]
|
||||
except ClientError as error:
|
||||
if error.response["Error"]["Code"] == "CacheClusterNotFound":
|
||||
logger.warning(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
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.get("AtRestEncryptionEnabled", False),
|
||||
transit_encryption=repl_group.get(
|
||||
"TransitEncryptionEnabled", False
|
||||
),
|
||||
multi_az=repl_group.get("MultiAZ", "disabled"),
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
@@ -102,25 +111,38 @@ 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...")
|
||||
def __list_tags_for_resource__(self):
|
||||
logger.info("Elasticache - Listing Tags...")
|
||||
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"],
|
||||
for cluster in self.clusters.values():
|
||||
try:
|
||||
regional_client = self.regional_clients[cluster.region]
|
||||
cluster.tags = regional_client.list_tags_for_resource(
|
||||
ResourceName=cluster.arn
|
||||
)["TagList"]
|
||||
except regional_client.exceptions.CacheClusterNotFoundFault as error:
|
||||
logger.warning(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
for repl_group in self.replication_groups.values():
|
||||
try:
|
||||
regional_client = self.regional_clients[repl_group.region]
|
||||
repl_group.tags = regional_client.list_tags_for_resource(
|
||||
ResourceName=repl_group.arn
|
||||
)["TagList"]
|
||||
except (
|
||||
regional_client.exceptions.ReplicationGroupNotFoundFault
|
||||
) as error:
|
||||
logger.warning(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
@@ -132,7 +154,7 @@ class Cluster(BaseModel):
|
||||
id: str
|
||||
arn: str
|
||||
region: str
|
||||
security_groups: list[str] = []
|
||||
engine: str
|
||||
cache_subnet_group_id: Optional[str]
|
||||
subnets: list = []
|
||||
tags: Optional[list]
|
||||
@@ -147,3 +169,4 @@ class ReplicationGroup(BaseModel):
|
||||
encrypted: bool
|
||||
transit_encryption: bool
|
||||
multi_az: str
|
||||
tags: Optional[list]
|
||||
|
||||
+164
-3
@@ -9,6 +9,8 @@ from tests.providers.aws.services.elasticache.elasticache_service_test import (
|
||||
ELASTICACHE_CLUSTER_ARN,
|
||||
ELASTICACHE_CLUSTER_NAME,
|
||||
ELASTICACHE_CLUSTER_TAGS,
|
||||
ELASTICACHE_ENGINE,
|
||||
ELASTICACHE_ENGINE_MEMCACHED,
|
||||
SUBNET_1,
|
||||
SUBNET_2,
|
||||
SUBNET_GROUP_NAME,
|
||||
@@ -67,6 +69,7 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
tags=ELASTICACHE_CLUSTER_TAGS,
|
||||
@@ -99,7 +102,7 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Cluster {ELASTICACHE_CLUSTER_NAME} is not using public subnets."
|
||||
== f"Elasticache Redis Node {ELASTICACHE_CLUSTER_NAME} is not using public subnets."
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == ELASTICACHE_CLUSTER_NAME
|
||||
@@ -115,6 +118,7 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
subnets=[SUBNET_1, SUBNET_2],
|
||||
@@ -176,7 +180,7 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Cluster {ELASTICACHE_CLUSTER_NAME} is not using public subnets."
|
||||
== f"Elasticache Redis Node {ELASTICACHE_CLUSTER_NAME} is not using public subnets."
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == ELASTICACHE_CLUSTER_NAME
|
||||
@@ -192,6 +196,7 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
subnets=[SUBNET_1, SUBNET_2],
|
||||
@@ -253,7 +258,163 @@ class Test_elasticache_cluster_uses_public_subnet:
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Cluster {ELASTICACHE_CLUSTER_NAME} is using subnet-1, subnet-2 public subnets."
|
||||
== f"Elasticache Redis Node {ELASTICACHE_CLUSTER_NAME} is using subnet-1, subnet-2 public subnets."
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == ELASTICACHE_CLUSTER_NAME
|
||||
assert result[0].resource_arn == ELASTICACHE_CLUSTER_ARN
|
||||
assert result[0].resource_tags == ELASTICACHE_CLUSTER_TAGS
|
||||
|
||||
def test_elasticache_clusters_using_public_subnets_memcached(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_service = MagicMock
|
||||
elasticache_service.clusters = {}
|
||||
|
||||
elasticache_service.clusters[ELASTICACHE_CLUSTER_ARN] = Cluster(
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE_MEMCACHED,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
subnets=[SUBNET_1, SUBNET_2],
|
||||
tags=ELASTICACHE_CLUSTER_TAGS,
|
||||
)
|
||||
|
||||
# Mock VPC Service
|
||||
vpc_client = MagicMock
|
||||
vpc_client.vpc_subnets = {}
|
||||
vpc_client.vpc_subnets[SUBNET_1] = VpcSubnet(
|
||||
id=SUBNET_1,
|
||||
name=SUBNET_1,
|
||||
arn="arn_test",
|
||||
default=False,
|
||||
vpc_id=VPC_ID,
|
||||
cidr_block="192.168.0.0/24",
|
||||
availability_zone=AWS_REGION_US_EAST_1_AZA,
|
||||
public=True,
|
||||
nat_gateway=False,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
tags=[],
|
||||
mapPublicIpOnLaunch=False,
|
||||
)
|
||||
vpc_client.vpc_subnets[SUBNET_2] = VpcSubnet(
|
||||
id=SUBNET_2,
|
||||
name=SUBNET_2,
|
||||
arn="arn_test",
|
||||
default=False,
|
||||
vpc_id=VPC_ID,
|
||||
cidr_block="192.168.0.1/24",
|
||||
availability_zone=AWS_REGION_US_EAST_1_AZB,
|
||||
public=True,
|
||||
nat_gateway=False,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
tags=[],
|
||||
mapPublicIpOnLaunch=False,
|
||||
)
|
||||
|
||||
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_cluster_uses_public_subnet.elasticache_cluster_uses_public_subnet import (
|
||||
elasticache_cluster_uses_public_subnet,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_uses_public_subnet()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Memcached Cluster {ELASTICACHE_CLUSTER_NAME} is using subnet-1, subnet-2 public subnets."
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == ELASTICACHE_CLUSTER_NAME
|
||||
assert result[0].resource_arn == ELASTICACHE_CLUSTER_ARN
|
||||
assert result[0].resource_tags == ELASTICACHE_CLUSTER_TAGS
|
||||
|
||||
def test_elasticache_clusters_using_private_subnets_memchached(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_service = MagicMock
|
||||
elasticache_service.clusters = {}
|
||||
|
||||
elasticache_service.clusters[ELASTICACHE_CLUSTER_ARN] = Cluster(
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE_MEMCACHED,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
subnets=[SUBNET_1, SUBNET_2],
|
||||
tags=ELASTICACHE_CLUSTER_TAGS,
|
||||
)
|
||||
|
||||
# Mock VPC Service
|
||||
vpc_client = MagicMock
|
||||
vpc_client.vpc_subnets = {}
|
||||
vpc_client.vpc_subnets[SUBNET_1] = VpcSubnet(
|
||||
id=SUBNET_1,
|
||||
name=SUBNET_1,
|
||||
arn="arn_test",
|
||||
default=False,
|
||||
vpc_id=VPC_ID,
|
||||
cidr_block="192.168.0.0/24",
|
||||
availability_zone=AWS_REGION_US_EAST_1_AZA,
|
||||
public=False,
|
||||
nat_gateway=False,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
tags=[],
|
||||
mapPublicIpOnLaunch=False,
|
||||
)
|
||||
vpc_client.vpc_subnets[SUBNET_2] = VpcSubnet(
|
||||
id=SUBNET_2,
|
||||
name=SUBNET_2,
|
||||
arn="arn_test",
|
||||
default=False,
|
||||
vpc_id=VPC_ID,
|
||||
cidr_block="192.168.0.1/24",
|
||||
availability_zone=AWS_REGION_US_EAST_1_AZB,
|
||||
public=False,
|
||||
nat_gateway=False,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
tags=[],
|
||||
mapPublicIpOnLaunch=False,
|
||||
)
|
||||
|
||||
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_cluster_uses_public_subnet.elasticache_cluster_uses_public_subnet import (
|
||||
elasticache_cluster_uses_public_subnet,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_uses_public_subnet()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Elasticache Memcached Cluster {ELASTICACHE_CLUSTER_NAME} is not using public subnets."
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == ELASTICACHE_CLUSTER_NAME
|
||||
|
||||
+71
-18
@@ -20,12 +20,15 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
REPLICATION_GROUP_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
class Test_elasticache_cluster_backup_enabled:
|
||||
class Test_elasticache_redis_cluster_backup_enabled:
|
||||
@mock_aws
|
||||
def test_elasticache_no_replication_groups(self):
|
||||
|
||||
@@ -40,11 +43,11 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_backup_enabled.elasticache_redis_cluster_backup_enabled import (
|
||||
elasticache_redis_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
check = elasticache_redis_cluster_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@@ -62,6 +65,7 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
encrypted=False,
|
||||
transit_encryption=False,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7}
|
||||
@@ -72,24 +76,25 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_backup_enabled.elasticache_redis_cluster_backup_enabled import (
|
||||
elasticache_redis_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
check = elasticache_redis_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."
|
||||
== f"Elasticache Redis cache 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_cluster_backup_enabled(self):
|
||||
def test_elasticache_redis_cluster_backup_enabled(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.replication_groups = {}
|
||||
@@ -103,6 +108,7 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 7}
|
||||
@@ -114,24 +120,25 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_backup_enabled.elasticache_redis_cluster_backup_enabled import (
|
||||
elasticache_redis_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
check = elasticache_redis_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."
|
||||
== f"Elasticache Redis cache 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_cluster_backup_enabled_modified_retention(self):
|
||||
def test_elasticache_redis_cluster_backup_enabled_modified_retention(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_client = MagicMock
|
||||
elasticache_client.replication_groups = {}
|
||||
@@ -145,6 +152,7 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 1}
|
||||
@@ -155,19 +163,64 @@ class Test_elasticache_cluster_backup_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_backup_enabled.elasticache_redis_cluster_backup_enabled import (
|
||||
elasticache_redis_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_backup_enabled()
|
||||
check = elasticache_redis_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."
|
||||
== f"Elasticache Redis cache 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_redis_cluster_backup_enabled_low_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=2,
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
|
||||
elasticache_client.audit_config = {"minimum_snapshot_retention_period": 3}
|
||||
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_redis_cluster_backup_enabled.elasticache_redis_cluster_backup_enabled import (
|
||||
elasticache_redis_cluster_backup_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_redis_cluster_backup_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} has automated snapshot backups enabled with retention period 2 days. Recommended to increase the snapshot retention period to a minimum of 7 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
assert result[0].check_metadata.Severity == "low"
|
||||
+19
-11
@@ -20,6 +20,10 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
REPLICATION_GROUP_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
@@ -40,11 +44,11 @@ class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_in_transit_encryption_enabled.elasticache_redis_cluster_in_transit_encryption_enabled import (
|
||||
elasticache_redis_cluster_in_transit_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
check = elasticache_redis_cluster_in_transit_encryption_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@@ -63,6 +67,7 @@ class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=False,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -73,22 +78,23 @@ class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_in_transit_encryption_enabled.elasticache_redis_cluster_in_transit_encryption_enabled import (
|
||||
elasticache_redis_cluster_in_transit_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
check = elasticache_redis_cluster_in_transit_encryption_enabled()
|
||||
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."
|
||||
== f"Elasticache Redis cache cluster {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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_replication_groups_in_transit_encryption_enabled(self):
|
||||
# Mock ElastiCache Service
|
||||
@@ -105,6 +111,7 @@ class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -115,19 +122,20 @@ class Test_elasticache_replication_group_in_transit_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_in_transit_encryption_enabled.elasticache_redis_cluster_in_transit_encryption_enabled import (
|
||||
elasticache_redis_cluster_in_transit_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_in_transit()
|
||||
check = elasticache_redis_cluster_in_transit_encryption_enabled()
|
||||
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."
|
||||
== f"Elasticache Redis cache cluster {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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
+20
-12
@@ -20,6 +20,10 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
REPLICATION_GROUP_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
@@ -40,11 +44,11 @@ class Test_elasticache_replication_group_multi_az_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_multi_az_enabled.elasticache_redis_cluster_multi_az_enabled import (
|
||||
elasticache_redis_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
check = elasticache_redis_cluster_multi_az_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@@ -63,6 +67,7 @@ class Test_elasticache_replication_group_multi_az_enabled:
|
||||
encrypted=False,
|
||||
transit_encryption=False,
|
||||
multi_az="disabled",
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -73,24 +78,25 @@ class Test_elasticache_replication_group_multi_az_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_multi_az_enabled.elasticache_redis_cluster_multi_az_enabled import (
|
||||
elasticache_redis_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
check = elasticache_redis_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."
|
||||
== f"Elasticache Redis cache 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_cluster_multi_az_enabled(self):
|
||||
def test_elasticache_redis_cluster_multi_az_enabled(self):
|
||||
# Mock ElastiCache Service
|
||||
elasticache_service = MagicMock
|
||||
elasticache_service.replication_groups = {}
|
||||
@@ -105,6 +111,7 @@ class Test_elasticache_replication_group_multi_az_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -115,19 +122,20 @@ class Test_elasticache_replication_group_multi_az_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_multi_az_enabled.elasticache_redis_cluster_multi_az_enabled import (
|
||||
elasticache_redis_cluster_multi_az_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_cluster_multi_az_enabled()
|
||||
check = elasticache_redis_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."
|
||||
== f"Elasticache Redis cache 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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
+18
-11
@@ -20,6 +20,9 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = True
|
||||
REPLICATION_GROUP_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
# Patch every AWS call using Boto3
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
@@ -40,11 +43,11 @@ class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_rest_encryption_enabled.elasticache_redis_cluster_rest_encryption_enabled import (
|
||||
elasticache_redis_cluster_rest_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
check = elasticache_redis_cluster_rest_encryption_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@@ -63,6 +66,7 @@ class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
encrypted=False,
|
||||
transit_encryption=False,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -73,22 +77,23 @@ class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_rest_encryption_enabled.elasticache_redis_cluster_rest_encryption_enabled import (
|
||||
elasticache_redis_cluster_rest_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
check = elasticache_redis_cluster_rest_encryption_enabled()
|
||||
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."
|
||||
== f"Elasticache Redis cache cluster {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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
|
||||
def test_elasticache_replication_groups_at_rest_encryption_enabled(self):
|
||||
# Mock ElastiCache Service
|
||||
@@ -105,6 +110,7 @@ class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -115,19 +121,20 @@ class Test_elasticache_replication_group_at_rest_encryption_enabled:
|
||||
"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,
|
||||
from prowler.providers.aws.services.elasticache.elasticache_redis_cluster_rest_encryption_enabled.elasticache_redis_cluster_rest_encryption_enabled import (
|
||||
elasticache_redis_cluster_rest_encryption_enabled,
|
||||
)
|
||||
|
||||
check = elasticache_replication_group_encrypted_at_rest()
|
||||
check = elasticache_redis_cluster_rest_encryption_enabled()
|
||||
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."
|
||||
== f"Elasticache Redis cache cluster {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
|
||||
assert result[0].resource_tags == REPLICATION_GROUP_TAGS
|
||||
@@ -21,6 +21,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_ENGINE = "redis"
|
||||
ELASTICACHE_ENGINE_MEMCACHED = "memcached"
|
||||
|
||||
ELASTICACHE_CLUSTER_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
@@ -33,6 +34,10 @@ REPLICATION_GROUP_SNAPSHOT_RETENTION = "0"
|
||||
REPLICATION_GROUP_ENCRYPTION = True
|
||||
REPLICATION_GROUP_TRANSIT_ENCRYPTION = True
|
||||
REPLICATION_GROUP_MULTI_AZ = "enabled"
|
||||
REPLICATION_GROUP_TAGS = [
|
||||
{"Key": "environment", "Value": "test"},
|
||||
]
|
||||
|
||||
|
||||
# Mocking Access Analyzer Calls
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
@@ -53,6 +58,7 @@ def mock_make_api_call(self, operation_name, kwargs):
|
||||
"CacheClusterId": ELASTICACHE_CLUSTER_NAME,
|
||||
"CacheSubnetGroupName": SUBNET_GROUP_NAME,
|
||||
"ARN": ELASTICACHE_CLUSTER_ARN,
|
||||
"Engine": ELASTICACHE_ENGINE,
|
||||
"SecurityGroups": [],
|
||||
},
|
||||
]
|
||||
@@ -143,7 +149,7 @@ class Test_ElastiCache_Service:
|
||||
elasticache = ElastiCache(aws_provider)
|
||||
assert elasticache.audited_account == AWS_ACCOUNT_NUMBER
|
||||
|
||||
# Test ElastiCache Clusters
|
||||
# Test Elasticache Redis cache clusters
|
||||
def test_describe_cache_clusters(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
elasticache = ElastiCache(aws_provider)
|
||||
@@ -154,6 +160,7 @@ class Test_ElastiCache_Service:
|
||||
arn=ELASTICACHE_CLUSTER_ARN,
|
||||
name=ELASTICACHE_CLUSTER_NAME,
|
||||
id=ELASTICACHE_CLUSTER_NAME,
|
||||
engine=ELASTICACHE_ENGINE,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
security_groups=[],
|
||||
cache_subnet_group_id=SUBNET_GROUP_NAME,
|
||||
@@ -161,7 +168,7 @@ class Test_ElastiCache_Service:
|
||||
tags=ELASTICACHE_CLUSTER_TAGS,
|
||||
)
|
||||
|
||||
# Test ElastiCache Replication Groups
|
||||
# Test Elasticache Redis cache clusters
|
||||
def test_describe_replication_groups(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
elasticache = ElastiCache(aws_provider)
|
||||
@@ -179,4 +186,5 @@ class Test_ElastiCache_Service:
|
||||
encrypted=REPLICATION_GROUP_ENCRYPTION,
|
||||
transit_encryption=REPLICATION_GROUP_TRANSIT_ENCRYPTION,
|
||||
multi_az=REPLICATION_GROUP_MULTI_AZ,
|
||||
tags=REPLICATION_GROUP_TAGS,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user