chore(rds): support more AWS RDS DB Instance engines in encryption check (#3968)

This commit is contained in:
madereddy
2024-05-10 04:23:54 -04:00
committed by GitHub
parent 6e88b260d0
commit 6601b4231d
4 changed files with 229 additions and 26 deletions
@@ -1,14 +1,14 @@
{
"Provider": "aws",
"CheckID": "rds_instance_transport_encrypted",
"CheckTitle": "Check if RDS instances client connections are encrypted (Microsoft SQL Server and PostgreSQL).",
"CheckTitle": "Check if RDS instances client connections are encrypted (Microsoft SQL Server, PostgreSQL, MySQL, MariaDB, Aurora PostgreSQL, and Aurora MySQL).",
"CheckType": [],
"ServiceName": "rds",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-instance",
"Severity": "high",
"ResourceType": "AwsRdsDbInstance",
"Description": "Check if RDS instances client connections are encrypted (Microsoft SQL Server and PostgreSQL).",
"Description": "For SQL Server, PostgreSQL and Aurora PostgreSQL databases, if the rds.force_ssl parameter value is set to 0, the Transport Encryption feature is not enabled. For MySQL, Aurora MySQL and MariaDB databases, if the require_secure_transport parameter value is set to OFF, the Transport Encryption feature is not enabled.",
"Risk": "If not enabled sensitive information at transit is not protected.",
"RelatedUrl": "https://aws.amazon.com/premiumsupport/knowledge-center/rds-connect-ssl-connection/",
"Remediation": {
@@ -19,11 +19,13 @@
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure that Microsoft SQL Server and PostgreSQL instances provisioned with Amazon RDS have Transport Encryption feature enabled in order to meet security and compliance requirements.",
"Text": "Ensure that instances provisioned with Amazon RDS have Transport Encryption feature enabled in order to meet security and compliance requirements.",
"Url": "https://aws.amazon.com/premiumsupport/knowledge-center/rds-connect-ssl-connection/"
}
},
"Categories": [ "encryption" ],
"Categories": [
"encryption"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
@@ -5,7 +5,17 @@ from prowler.providers.aws.services.rds.rds_client import rds_client
class rds_instance_transport_encrypted(Check):
def execute(self):
findings = []
supported_engines = ["sqlserver", "postgres"]
supported_engines = [
"sqlserver-se",
"sqlserver-ee",
"sqlserver-ex",
"sqlserver-web",
"postgres",
"aurora-postgresql",
"mysql",
"mariadb",
"aurora-mysql",
]
for db_instance in rds_client.db_instances:
report = Check_Report_AWS(self.metadata())
report.region = db_instance.region
@@ -16,19 +26,34 @@ class rds_instance_transport_encrypted(Check):
report.status_extended = (
f"RDS Instance {db_instance.id} connections are not encrypted."
)
# Check only RDS SQL Server or PostgreSQL engines (Aurora not supported)
if (
any(engine in db_instance.engine for engine in supported_engines)
and "aurora" not in db_instance.engine
):
for parameter in db_instance.parameters:
if (
parameter["ParameterName"] == "rds.force_ssl"
and parameter["ParameterValue"] == "1"
):
report.status = "PASS"
report.status_extended = f"RDS Instance {db_instance.id} connections use SSL encryption."
# Check only RDS DB instances that support parameter group encryption
if not db_instance.cluster_id and any(
engine in db_instance.engine for engine in supported_engines
):
if db_instance.engine in [
"sqlserver-se",
"sqlserver-ee",
"sqlserver-ex",
"sqlserver-web",
"postgres",
"aurora-postgresql",
]:
for parameter in db_instance.parameters:
if (
parameter["ParameterName"] == "rds.force_ssl"
and parameter["ParameterValue"] == "1"
):
report.status = "PASS"
report.status_extended = f"RDS Instance {db_instance.id} connections use SSL encryption."
else:
for parameter in db_instance.parameters:
if (
parameter["ParameterName"] == "require_secure_transport"
and parameter["ParameterValue"] == "1"
):
report.status = "PASS"
report.status_extended = f"RDS Instance {db_instance.id} connections use SSL encryption."
findings.append(report)
return findings
@@ -1,4 +1,3 @@
from re import search
from unittest import mock
import botocore
@@ -75,6 +74,57 @@ class Test_rds_instance_transport_encrypted:
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
with mock.patch(
"prowler.providers.common.common.get_global_provider",
return_value=aws_provider,
):
with mock.patch(
"prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted import (
rds_instance_transport_encrypted,
)
check = rds_instance_transport_encrypted()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "RDS Instance db-master-1 connections are not encrypted."
)
assert result[0].resource_id == "db-master-1"
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}:db:db-master-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_rds_clustered_instance(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="cluster-postgres",
)
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.common.get_global_provider",
return_value=aws_provider,
@@ -94,7 +144,7 @@ class Test_rds_instance_transport_encrypted:
assert len(result) == 0
@mock_aws
def test_rds_instance_no_ssl(self):
def test_postgres_rds_instance_no_ssl(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
@@ -143,9 +193,9 @@ class Test_rds_instance_transport_encrypted:
assert len(result) == 1
assert result[0].status == "FAIL"
assert search(
"connections are not encrypted",
result[0].status_extended,
assert (
result[0].status_extended
== "RDS Instance db-master-1 connections are not encrypted."
)
assert result[0].resource_id == "db-master-1"
assert result[0].region == AWS_REGION_US_EAST_1
@@ -156,7 +206,131 @@ class Test_rds_instance_transport_encrypted:
assert result[0].resource_tags == []
@mock_aws
def test_rds_instance_with_ssl(self):
def test_mysql_rds_instance_no_ssl(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.mysql8.0",
Description="test parameter group",
)
conn.create_db_instance(
DBInstanceIdentifier="db-master-1",
AllocatedStorage=10,
Engine="mysql",
DBName="staging-mysql",
DBInstanceClass="db.m1.small",
DBParameterGroupName="test",
)
conn.modify_db_parameter_group(
DBParameterGroupName="test",
Parameters=[
{
"ParameterName": "require_secure_transport",
"ParameterValue": "0",
"ApplyMethod": "immediate",
},
],
)
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.common.get_global_provider",
return_value=aws_provider,
):
with mock.patch(
"prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted import (
rds_instance_transport_encrypted,
)
check = rds_instance_transport_encrypted()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "RDS Instance db-master-1 connections are not encrypted."
)
assert result[0].resource_id == "db-master-1"
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}:db:db-master-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_mysql_rds_instance_with_ssl(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.mysql8.0",
Description="test parameter group",
)
conn.create_db_instance(
DBInstanceIdentifier="db-master-1",
AllocatedStorage=10,
Engine="mysql",
DBName="staging-mysql",
DBInstanceClass="db.m1.small",
DBParameterGroupName="test",
)
conn.modify_db_parameter_group(
DBParameterGroupName="test",
Parameters=[
{
"ParameterName": "require_secure_transport",
"ParameterValue": "1",
"ApplyMethod": "immediate",
},
],
)
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.common.get_global_provider",
return_value=aws_provider,
):
with mock.patch(
"prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted.rds_client",
new=RDS(aws_provider),
):
# Test Check
from prowler.providers.aws.services.rds.rds_instance_transport_encrypted.rds_instance_transport_encrypted import (
rds_instance_transport_encrypted,
)
check = rds_instance_transport_encrypted()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "RDS Instance db-master-1 connections use SSL encryption."
)
assert result[0].resource_id == "db-master-1"
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}:db:db-master-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_postgres_rds_instance_with_ssl(self):
conn = client("rds", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
@@ -205,9 +379,9 @@ class Test_rds_instance_transport_encrypted:
assert len(result) == 1
assert result[0].status == "PASS"
assert search(
"connections use SSL encryption",
result[0].status_extended,
assert (
result[0].status_extended
== "RDS Instance db-master-1 connections use SSL encryption."
)
assert result[0].resource_id == "db-master-1"
assert result[0].region == AWS_REGION_US_EAST_1
@@ -88,6 +88,7 @@ class Test_RDS_Service:
EnableCloudwatchLogsExports=["audit", "error"],
MultiAZ=True,
DBParameterGroupName="test",
DBClusterIdentifier="cluster-postgres",
Tags=[
{"Key": "test", "Value": "test"},
],
@@ -110,6 +111,7 @@ class Test_RDS_Service:
assert rds.db_instances[0].deletion_protection
assert rds.db_instances[0].auto_minor_version_upgrade
assert rds.db_instances[0].multi_az
assert rds.db_instances[0].cluster_id
assert rds.db_instances[0].tags == [
{"Key": "test", "Value": "test"},
]