feat(mq): add mq_broker_not_publicly_accessible check (#5604)

Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
sansns-aws
2024-11-11 12:12:21 -05:00
committed by GitHub
parent f231d8b080
commit 10766d708d
6 changed files with 203 additions and 0 deletions
@@ -0,0 +1,34 @@
{
"Provider": "aws",
"CheckID": "mq_broker_not_publicly_accessible",
"CheckTitle": "MQ brokers should not be publicly accessible.",
"CheckType": [
"Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls"
],
"ServiceName": "mq",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:mq:region:account-id:broker:broker-id",
"Severity": "medium",
"ResourceType": "AwsAmazonMQBroker",
"Description": "Brokers created without public accessibility can't be accessed from outside of your VPC. This greatly reduces your broker's susceptibility to Distributed Denial of Service (DDoS) attacks from the public internet.",
"Risk": "Public Amazon MQ brokers can be accessed directly, outside of a Virtual Private Cloud (VPC), therefore every machine on the Internet can reach your brokers through their public endpoints and this can increase the opportunity for malicious activity such as cross-site scripting (XSS) and clickjacking attacks. ",
"RelatedUrl": "https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/using-amazon-mq-securely.html#prefer-brokers-without-public-accessibility",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/MQ/publicly-accessible.html#",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure that the Amazon MQ brokers provisioned in your AWS account are not publicly accessible from the Internet in order to avoid exposing sensitive data and minimize security risks.",
"Url": "https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/using-amazon-mq-securely.html#prefer-brokers-without-public-accessibility"
}
},
"Categories": [
"internet-exposed"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,25 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.mq.mq_client import mq_client
class mq_broker_not_publicly_accessible(Check):
def execute(self):
findings = []
for broker in mq_client.brokers.values():
report = Check_Report_AWS(self.metadata())
report.region = broker.region
report.resource_id = broker.id
report.resource_arn = broker.arn
report.resource_tags = broker.tags
report.status = "FAIL"
report.status_extended = f"MQ Broker {broker.name} is publicly accessible."
if not broker.publicly_accessible:
report.status = "PASS"
report.status_extended = (
f"MQ Broker {broker.name} is not publicly accessible."
)
findings.append(report)
return findings
@@ -56,6 +56,9 @@ class MQ(AWSService):
broker.audit_logging_enabled = describe_broker.get("Logs", {}).get(
"Audit", False
)
broker.publicly_accessible = describe_broker.get(
"PubliclyAccessible", False
)
broker.tags = [describe_broker.get("Tags", {})]
except Exception as error:
@@ -87,6 +90,7 @@ class Broker(BaseModel):
id: str
region: str
auto_minor_version_upgrade: bool = Field(default=False)
publicly_accessible: bool = Field(default=False)
general_logging_enabled: bool = Field(default=False)
audit_logging_enabled: bool = Field(default=False)
engine_type: EngineType = EngineType.ACTIVEMQ
@@ -0,0 +1,139 @@
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_mq_broker_not_publicly_accessible:
@mock_aws
def test_no_brokers(self):
from prowler.providers.aws.services.mq.mq_service import MQ
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.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible.mq_client",
new=MQ(aws_provider),
):
# Test Check
from prowler.providers.aws.services.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible import (
mq_broker_not_publicly_accessible,
)
check = mq_broker_not_publicly_accessible()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_broker_publicly_accessible(self):
mq_client = client("mq", region_name=AWS_REGION_US_EAST_1)
broker_name = "test-broker"
broker_id = mq_client.create_broker(
BrokerName=broker_name,
EngineType="ACTIVEMQ",
EngineVersion="5.15.0",
HostInstanceType="mq.t2.micro",
Users=[
{
"Username": "admin",
"Password": "admin",
},
],
DeploymentMode="SINGLE_INSTANCE",
PubliclyAccessible=True,
AutoMinorVersionUpgrade=True,
)["BrokerId"]
from prowler.providers.aws.services.mq.mq_service import MQ
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.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible.mq_client",
new=MQ(aws_provider),
):
# Test Check
from prowler.providers.aws.services.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible import (
mq_broker_not_publicly_accessible,
)
check = mq_broker_not_publicly_accessible()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"MQ Broker {broker_name} is publicly accessible."
)
assert result[0].resource_id == broker_id
assert (
result[0].resource_arn
== f"arn:{aws_provider.identity.partition}:mq:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:broker:{broker_id}"
)
assert result[0].region == AWS_REGION_US_EAST_1
@mock_aws
def test_broker_not_publicly_accessible(self):
mq_client = client("mq", region_name=AWS_REGION_US_EAST_1)
broker_name = "test-broker"
broker_id = mq_client.create_broker(
BrokerName=broker_name,
EngineType="ACTIVEMQ",
EngineVersion="5.15.0",
HostInstanceType="mq.t2.micro",
Users=[
{
"Username": "admin",
"Password": "admin",
},
],
DeploymentMode="SINGLE_INSTANCE",
PubliclyAccessible=False,
AutoMinorVersionUpgrade=False,
)["BrokerId"]
from prowler.providers.aws.services.mq.mq_service import MQ
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.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible.mq_client",
new=MQ(aws_provider),
):
# Test Check
from prowler.providers.aws.services.mq.mq_broker_not_publicly_accessible.mq_broker_not_publicly_accessible import (
mq_broker_not_publicly_accessible,
)
check = mq_broker_not_publicly_accessible()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"MQ Broker {broker_name} is not publicly accessible."
)
assert result[0].resource_id == broker_id
assert (
result[0].resource_arn
== f"arn:{aws_provider.identity.partition}:mq:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:broker:{broker_id}"
)
assert result[0].region == AWS_REGION_US_EAST_1
@@ -109,4 +109,5 @@ class Test_MQ_Service:
assert mq.brokers[broker_arn].engine_type == EngineType.ACTIVEMQ
assert mq.brokers[broker_arn].deployment_mode == DeploymentMode.SINGLE_INSTANCE
assert mq.brokers[broker_arn].auto_minor_version_upgrade
assert mq.brokers[broker_arn].publicly_accessible
assert mq.brokers[broker_arn].tags == [{"key": "value"}]