-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dms): add new check
dms_endpoint_mongodb_authentication_enabled
(
#5578) Co-authored-by: Sergio Garcia <[email protected]>
- Loading branch information
1 parent
ea03808
commit 9802fc1
Showing
7 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
32 changes: 32 additions & 0 deletions
32
..._mongodb_authentication_enabled/dms_endpoint_mongodb_authentication_enabled.metadata.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"Provider": "aws", | ||
"CheckID": "dms_endpoint_mongodb_authentication_enabled", | ||
"CheckTitle": "Check if DMS endpoints for MongoDB have an authentication mechanism enabled.", | ||
"CheckType": [ | ||
"Software and Configuration Checks/AWS Security Best Practices" | ||
], | ||
"ServiceName": "dms", | ||
"SubServiceName": "", | ||
"ResourceIdTemplate": "arn:aws:dms:region:account-id:endpoint/endpoint-id", | ||
"Severity": "medium", | ||
"ResourceType": "AwsDmsEndpoint", | ||
"Description": "This control checks whether an AWS DMS endpoint for MongoDB is configured with an authentication mechanism. The control fails if an authentication type isn't set for the endpoint.", | ||
"Risk": "Without an authentication mechanism enabled, unauthorized users may gain access to sensitive data during migration, increasing the risk of data breaches and security incidents.", | ||
"RelatedUrl": "https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MongoDB.html", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "aws dms modify-endpoint --endpoint-arn <endpoint-arn> --username <username> --password <password> --authentication-type <authentication-type>", | ||
"NativeIaC": "", | ||
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dms-controls.html#dms-11", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Enable an authentication mechanism on DMS endpoints for MongoDB to ensure secure access control during migration.", | ||
"Url": "https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MongoDB.html" | ||
} | ||
}, | ||
"Categories": [], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "" | ||
} |
42 changes: 42 additions & 0 deletions
42
...ms_endpoint_mongodb_authentication_enabled/dms_endpoint_mongodb_authentication_enabled.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from typing import List | ||
|
||
from prowler.lib.check.models import Check, Check_Report_AWS | ||
from prowler.providers.aws.services.dms.dms_client import dms_client | ||
|
||
|
||
class dms_endpoint_mongodb_authentication_enabled(Check): | ||
""" | ||
Check if AWS DMS Endpoints for MongoDB have an authentication mechanism enabled. | ||
This class verifies whether each AWS DMS Endpoint configured for MongoDB has an authentication | ||
mechanism enabled by checking the `AuthType` property in the endpoint's configuration. The check | ||
ensures that the `AuthType` is not set to "no", indicating that an authentication method is in place. | ||
""" | ||
|
||
def execute(self) -> List[Check_Report_AWS]: | ||
""" | ||
Execute the DMS MongoDB authentication type configured check. | ||
Iterates over all DMS Endpoints and generates a report indicating whether | ||
each MongoDB endpoint has an authentication mechanism enabled. | ||
Returns: | ||
List[Check_Report_AWS]: A list of report objects with the results of the check. | ||
""" | ||
findings = [] | ||
for endpoint_arn, endpoint in dms_client.endpoints.items(): | ||
if endpoint.engine_name == "mongodb": | ||
report = Check_Report_AWS(self.metadata()) | ||
report.resource_id = endpoint.id | ||
report.resource_arn = endpoint_arn | ||
report.region = endpoint.region | ||
report.resource_tags = endpoint.tags | ||
report.status = "FAIL" | ||
report.status_extended = f"DMS Endpoint '{endpoint.id}' for MongoDB does not have an authentication mechanism enabled." | ||
if endpoint.mongodb_auth_type != "no": | ||
report.status = "PASS" | ||
report.status_extended = f"DMS Endpoint '{endpoint.id}' for MongoDB has {endpoint.mongodb_auth_type} as the authentication mechanism." | ||
|
||
findings.append(report) | ||
|
||
return findings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
271 changes: 271 additions & 0 deletions
271
...dpoint_mongodb_authentication_enabled/dms_endpoint_mongodb_authentication_enabled_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
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 | ||
|
||
DMS_ENDPOINT_NAME = "dms-endpoint" | ||
DMS_ENDPOINT_ARN = f"arn:aws:dms:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:endpoint:{DMS_ENDPOINT_NAME}" | ||
DMS_INSTANCE_NAME = "rep-instance" | ||
DMS_INSTANCE_ARN = ( | ||
f"arn:aws:dms:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:rep:{DMS_INSTANCE_NAME}" | ||
) | ||
|
||
|
||
def mock_make_api_call_enabled_not_mongodb(self, operation_name, kwarg): | ||
if operation_name == "DescribeEndpoints": | ||
return { | ||
"Endpoints": [ | ||
{ | ||
"EndpointIdentifier": DMS_ENDPOINT_NAME, | ||
"EndpointArn": DMS_ENDPOINT_ARN, | ||
"SslMode": "require", | ||
"MongoDbSettings": { | ||
"AuthType": "password", | ||
}, | ||
"EngineName": "oracle", | ||
} | ||
] | ||
} | ||
elif operation_name == "ListTagsForResource": | ||
if kwarg["ResourceArn"] == DMS_INSTANCE_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "rep-instance"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
elif kwarg["ResourceArn"] == DMS_ENDPOINT_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "dms-endpoint"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
return make_api_call(self, operation_name, kwarg) | ||
|
||
|
||
def mock_make_api_call_enabled(self, operation_name, kwarg): | ||
if operation_name == "DescribeEndpoints": | ||
return { | ||
"Endpoints": [ | ||
{ | ||
"EndpointIdentifier": DMS_ENDPOINT_NAME, | ||
"EndpointArn": DMS_ENDPOINT_ARN, | ||
"SslMode": "require", | ||
"MongoDbSettings": { | ||
"AuthType": "password", | ||
}, | ||
"EngineName": "mongodb", | ||
} | ||
] | ||
} | ||
elif operation_name == "ListTagsForResource": | ||
if kwarg["ResourceArn"] == DMS_INSTANCE_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "rep-instance"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
elif kwarg["ResourceArn"] == DMS_ENDPOINT_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "dms-endpoint"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
return make_api_call(self, operation_name, kwarg) | ||
|
||
|
||
def mock_make_api_call_not_enabled(self, operation_name, kwarg): | ||
if operation_name == "DescribeEndpoints": | ||
return { | ||
"Endpoints": [ | ||
{ | ||
"EndpointIdentifier": DMS_ENDPOINT_NAME, | ||
"EndpointArn": DMS_ENDPOINT_ARN, | ||
"SslMode": "require", | ||
"MongoDbSettings": { | ||
"AuthType": "no", | ||
}, | ||
"EngineName": "mongodb", | ||
} | ||
] | ||
} | ||
elif operation_name == "ListTagsForResource": | ||
if kwarg["ResourceArn"] == DMS_INSTANCE_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "rep-instance"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
elif kwarg["ResourceArn"] == DMS_ENDPOINT_ARN: | ||
return { | ||
"TagList": [ | ||
{"Key": "Name", "Value": "dms-endpoint"}, | ||
{"Key": "Owner", "Value": "admin"}, | ||
] | ||
} | ||
return make_api_call(self, operation_name, kwarg) | ||
|
||
|
||
class Test_dms_endpoint_mongodb_authentication_enabled: | ||
@mock_aws | ||
def test_no_dms_endpoints(self): | ||
dms_client = client("dms", region_name=AWS_REGION_US_EAST_1) | ||
dms_client.endpoints = {} | ||
|
||
from prowler.providers.aws.services.dms.dms_service import DMS | ||
|
||
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, | ||
), mock.patch( | ||
"prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled.dms_client", | ||
new=DMS(aws_provider), | ||
): | ||
# Test Check | ||
from prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled import ( | ||
dms_endpoint_mongodb_authentication_enabled, | ||
) | ||
|
||
check = dms_endpoint_mongodb_authentication_enabled() | ||
result = check.execute() | ||
|
||
assert len(result) == 0 | ||
|
||
@mock_aws | ||
def test_dms_not_mongodb_auth_mecanism_enabled(self): | ||
with mock.patch( | ||
"botocore.client.BaseClient._make_api_call", | ||
new=mock_make_api_call_enabled_not_mongodb, | ||
): | ||
|
||
from prowler.providers.aws.services.dms.dms_service import DMS | ||
|
||
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, | ||
), mock.patch( | ||
"prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled.dms_client", | ||
new=DMS(aws_provider), | ||
): | ||
# Test Check | ||
from prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled import ( | ||
dms_endpoint_mongodb_authentication_enabled, | ||
) | ||
|
||
check = dms_endpoint_mongodb_authentication_enabled() | ||
result = check.execute() | ||
|
||
assert len(result) == 0 | ||
|
||
@mock_aws | ||
def test_dms_mongodb_auth_mecanism_not_enabled(self): | ||
with mock.patch( | ||
"botocore.client.BaseClient._make_api_call", | ||
new=mock_make_api_call_not_enabled, | ||
): | ||
|
||
from prowler.providers.aws.services.dms.dms_service import DMS | ||
|
||
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, | ||
), mock.patch( | ||
"prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled.dms_client", | ||
new=DMS(aws_provider), | ||
): | ||
# Test Check | ||
from prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled import ( | ||
dms_endpoint_mongodb_authentication_enabled, | ||
) | ||
|
||
check = dms_endpoint_mongodb_authentication_enabled() | ||
result = check.execute() | ||
|
||
assert len(result) == 1 | ||
assert result[0].status == "FAIL" | ||
assert result[0].status_extended == ( | ||
"DMS Endpoint 'dms-endpoint' for MongoDB does not have an authentication mechanism enabled." | ||
) | ||
assert result[0].resource_id == "dms-endpoint" | ||
assert ( | ||
result[0].resource_arn | ||
== "arn:aws:dms:us-east-1:123456789012:endpoint:dms-endpoint" | ||
) | ||
assert result[0].resource_tags == [ | ||
{ | ||
"Key": "Name", | ||
"Value": "dms-endpoint", | ||
}, | ||
{ | ||
"Key": "Owner", | ||
"Value": "admin", | ||
}, | ||
] | ||
assert result[0].region == "us-east-1" | ||
|
||
@mock_aws | ||
def test_dms_mongodb_auth_mecanism_enabled(self): | ||
with mock.patch( | ||
"botocore.client.BaseClient._make_api_call", | ||
new=mock_make_api_call_enabled, | ||
): | ||
|
||
from prowler.providers.aws.services.dms.dms_service import DMS | ||
|
||
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, | ||
), mock.patch( | ||
"prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled.dms_client", | ||
new=DMS(aws_provider), | ||
): | ||
# Test Check | ||
from prowler.providers.aws.services.dms.dms_endpoint_mongodb_authentication_enabled.dms_endpoint_mongodb_authentication_enabled import ( | ||
dms_endpoint_mongodb_authentication_enabled, | ||
) | ||
|
||
check = dms_endpoint_mongodb_authentication_enabled() | ||
result = check.execute() | ||
|
||
assert len(result) == 1 | ||
assert result[0].status == "PASS" | ||
assert result[0].status_extended == ( | ||
"DMS Endpoint 'dms-endpoint' for MongoDB has password as the authentication mechanism." | ||
) | ||
assert result[0].resource_id == "dms-endpoint" | ||
assert ( | ||
result[0].resource_arn | ||
== "arn:aws:dms:us-east-1:123456789012:endpoint:dms-endpoint" | ||
) | ||
assert result[0].resource_tags == [ | ||
{ | ||
"Key": "Name", | ||
"Value": "dms-endpoint", | ||
}, | ||
{ | ||
"Key": "Owner", | ||
"Value": "admin", | ||
}, | ||
] | ||
assert result[0].region == "us-east-1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.