Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mq): add mq_broker_not_publicly_accessible check #5604

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions prowler/providers/aws/services/mq/mq_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ def _describe_broker(self, broker):
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:
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tests/providers/aws/services/mq/mq_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,5 @@ def test_describe_broker(self):
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"}]