feat(aws): Add new check to ensure RDS event notification subscriptions are configured for critical database parameter group events (#4907)

This commit is contained in:
Daniel Barranquero
2024-09-10 17:10:57 +02:00
committed by GitHub
parent f5b0583df5
commit 1ef15f0b24
4 changed files with 249 additions and 0 deletions
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "rds_instance_event_subscription_parameter_groups",
"CheckTitle": "Check if RDS Parameter Group events are subscribed.",
"CheckType": [],
"ServiceName": "rds",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-instance",
"Severity": "low",
"ResourceType": "AwsRdsEventSubscription",
"Description": "Ensure that Amazon RDS event notification subscriptions are enabled for database parameter groups events.",
"Risk": "Amazon RDS event subscriptions for database parameter groups are designed to provide incident notification of events that may affect the security, availability, and reliability of the RDS database instances associated with these parameter groups.",
"RelatedUrl": "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html",
"Remediation": {
"Code": {
"CLI": "aws rds create-event-subscription --source-type db-instance --event-categories 'configuration change' --sns-topic-arn <sns-topic-arn>",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-21",
"Terraform": ""
},
"Recommendation": {
"Text": "To subscribe to RDS instance event notifications, see Subscribing to Amazon RDS event notification in the Amazon RDS User Guide.",
"Url": "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.Subscribing.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,30 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.rds.rds_client import rds_client
class rds_instance_event_subscription_parameter_groups(Check):
def execute(self):
findings = []
if rds_client.provider.scan_unused_services or rds_client.db_instances:
for db_event in rds_client.db_event_subscriptions:
report = Check_Report_AWS(self.metadata())
report.status = "FAIL"
report.status_extended = "RDS parameter group event categories of configuration change is not subscribed."
report.resource_id = rds_client.audited_account
report.resource_arn = rds_client.__get_rds_arn_template__(
db_event.region
)
report.region = db_event.region
if db_event.source_type == "db-parameter-group" and db_event.enabled:
if db_event.event_list == [] or db_event.event_list == [
"configuration change",
]:
report.resource_id = db_event.id
report.resource_arn = db_event.arn
report.status = "PASS"
report.status_extended = (
"RDS parameter group events are subscribed."
)
findings.append(report)
return findings
@@ -0,0 +1,189 @@
from unittest import mock
import botocore
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,
)
make_api_call = botocore.client.BaseClient._make_api_call
RDS_ACCOUNT_ARN = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:account"
class Test_rds_instance__no_event_subscriptions:
@mock_aws
def test_rds_no_events(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_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups import (
rds_instance_event_subscription_parameter_groups,
)
check = rds_instance_event_subscription_parameter_groups()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "RDS parameter group event categories of configuration change is not subscribed."
)
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert result[0].resource_arn == RDS_ACCOUNT_ARN
@mock_aws
def test_rds_no_events_ignoring(self):
from prowler.providers.aws.services.rds.rds_service import RDS
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
aws_provider._scan_unused_services = False
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=aws_provider,
):
with mock.patch(
"prowler.providers.aws.services.rds.rds_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups import (
rds_instance_event_subscription_parameter_groups,
)
check = rds_instance_event_subscription_parameter_groups()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_rds_parameter_event_subscription_enabled(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.aurora-postgresql14",
Description="test parameter group",
)
conn.create_db_instance(
DBInstanceIdentifier="db-master-1",
AllocatedStorage=10,
Engine="aurora-postgresql",
DBName="aurora-postgres",
DBInstanceClass="db.m1.small",
DBParameterGroupName="test",
DBClusterIdentifier="db-cluster-1",
)
conn.create_event_subscription(
SubscriptionName="TestSub",
SnsTopicArn=f"arn:aws:sns:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:test",
SourceType="db-parameter-group",
Enabled=True,
Tags=[
{"Key": "test", "Value": "testing"},
],
)
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_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups import (
rds_instance_event_subscription_parameter_groups,
)
check = rds_instance_event_subscription_parameter_groups()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "RDS parameter group events are subscribed."
)
assert result[0].resource_id == "TestSub"
assert result[0].region == AWS_REGION_US_EAST_1
assert (
result[0].resource_arn
== f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:es:TestSub"
)
@mock_aws
def test_rds_parameter_event_configuration_change_only_subscription(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.aurora-postgresql14",
Description="test parameter group",
)
conn.create_db_instance(
DBInstanceIdentifier="db-master-1",
AllocatedStorage=10,
Engine="aurora-postgresql",
DBName="aurora-postgres",
DBInstanceClass="db.m1.small",
DBParameterGroupName="test",
DBClusterIdentifier="db-cluster-1",
)
conn.create_event_subscription(
SubscriptionName="TestSub",
SnsTopicArn=f"arn:aws:sns:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:test",
SourceType="db-parameter-group",
EventCategories=["configuration change"],
Enabled=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_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_event_subscription_parameter_groups.rds_instance_event_subscription_parameter_groups import (
rds_instance_event_subscription_parameter_groups,
)
check = rds_instance_event_subscription_parameter_groups()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "RDS parameter group events are subscribed."
)
assert result[0].resource_id == "TestSub"
assert result[0].region == AWS_REGION_US_EAST_1
assert (
result[0].resource_arn
== f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:es:TestSub"
)