mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
feat(aws): Add new check to ensure RDS db clusters copy tags to snapshots (#4846)
This commit is contained in:
committed by
GitHub
parent
0d18406f80
commit
472aea6a91
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "rds_cluster_copy_tags_to_snapshots",
|
||||
"CheckTitle": "Check if RDS DB clusters have copy tags to snapshots enabled",
|
||||
"CheckType": [],
|
||||
"ServiceName": "rds",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
|
||||
"Severity": "low",
|
||||
"ResourceType": "AwsRdsDbCluster",
|
||||
"Description": "Check if RDS DB clusters have copy tags to snapshots enabled, Aurora instances do not support this feature at instance level so those who are clustered will be scan by this check.",
|
||||
"Risk": "If RDS clusters are not configured to copy tags to snapshots, it could lead to compliance issues as the snapshots will not inherit necessary metadata such as environment, owner, or purpose tags. This could result in inefficient tracking and management of RDS resources and their snapshots.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html#USER_Tagging.CopyTags",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws rds modify-db-cluster --db-cluster-identifier <cluster-identifier> --copy-tags-to-snapshot",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-16",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure that the `CopyTagsToSnapshot` setting is enabled for all RDS clusters to propagate cluster tags to their snapshots for improved tracking and compliance.",
|
||||
"Url": "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html#USER_Tagging.CopyTags"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.rds.rds_client import rds_client
|
||||
|
||||
|
||||
class rds_cluster_copy_tags_to_snapshots(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for db_cluster_arn, db_cluster in rds_client.db_clusters.items():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = db_cluster.region
|
||||
report.resource_id = db_cluster.id
|
||||
report.resource_arn = db_cluster_arn
|
||||
report.resource_tags = db_cluster.tags
|
||||
if db_cluster.copy_tags_to_snapshot:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"RDS Cluster {db_cluster.id} has copy tags to snapshots enabled."
|
||||
)
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"RDS Cluster {db_cluster.id} does not have copy tags to snapshots enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
from unittest import mock
|
||||
|
||||
from boto3 import client
|
||||
from moto import mock_aws
|
||||
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_rds_cluster_copy_tags_to_snapshots:
|
||||
@mock_aws
|
||||
def test_rds_no_clusters(self):
|
||||
from prowler.providers.aws.services.rds.rds_service import RDS
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
):
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots.rds_client",
|
||||
new=RDS(aws_provider),
|
||||
):
|
||||
from prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots import (
|
||||
rds_cluster_copy_tags_to_snapshots,
|
||||
)
|
||||
|
||||
check = rds_cluster_copy_tags_to_snapshots()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@mock_aws
|
||||
def test_rds_cluster_without_copy_tags(self):
|
||||
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
|
||||
conn.create_db_cluster(
|
||||
DBClusterIdentifier="test-cluster",
|
||||
AllocatedStorage=10,
|
||||
Engine="mysql",
|
||||
DatabaseName="staging-mysql",
|
||||
DeletionProtection=True,
|
||||
DBClusterParameterGroupName="test",
|
||||
MasterUsername="test",
|
||||
MasterUserPassword="password",
|
||||
Tags=[],
|
||||
CopyTagsToSnapshot=False,
|
||||
)
|
||||
from prowler.providers.aws.services.rds.rds_service import RDS
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
):
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots.rds_client",
|
||||
new=RDS(aws_provider),
|
||||
):
|
||||
from prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots import (
|
||||
rds_cluster_copy_tags_to_snapshots,
|
||||
)
|
||||
|
||||
check = rds_cluster_copy_tags_to_snapshots()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "RDS Cluster test-cluster does not have copy tags to snapshots enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-cluster"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:test-cluster"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
@mock_aws
|
||||
def test_rds_cluster_with_copy_tags(self):
|
||||
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
|
||||
conn.create_db_cluster(
|
||||
DBClusterIdentifier="test-cluster",
|
||||
AllocatedStorage=10,
|
||||
Engine="mysql",
|
||||
DatabaseName="staging-mysql",
|
||||
DeletionProtection=True,
|
||||
DBClusterParameterGroupName="test",
|
||||
MasterUsername="test",
|
||||
MasterUserPassword="password",
|
||||
Tags=[],
|
||||
CopyTagsToSnapshot=True,
|
||||
)
|
||||
from prowler.providers.aws.services.rds.rds_service import RDS
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
):
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots.rds_client",
|
||||
new=RDS(aws_provider),
|
||||
):
|
||||
from prowler.providers.aws.services.rds.rds_cluster_copy_tags_to_snapshots.rds_cluster_copy_tags_to_snapshots import (
|
||||
rds_cluster_copy_tags_to_snapshots,
|
||||
)
|
||||
|
||||
check = rds_cluster_copy_tags_to_snapshots()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "RDS Cluster test-cluster has copy tags to snapshots enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-cluster"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:test-cluster"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == []
|
||||
Reference in New Issue
Block a user