MQ Brokers Should Not Be Publicly Accessible
Overview
This check verifies that Amazon MQ brokers are not configured with public accessibility. When a broker is publicly accessible, it can be reached from the internet, which increases your attack surface and exposes your messaging infrastructure to potential threats.
Risk
A publicly accessible Amazon MQ broker can be reached by anyone on the internet. This creates several security risks:
- Denial-of-service attacks: Attackers can flood your broker with connection requests
- Credential attacks: Brute-force or credential-stuffing attempts against broker authentication
- Data exposure: If authentication is compromised, messages could be read or tampered with
- Reconnaissance: Attackers can probe your broker to discover protocols and versions
Keeping brokers private within your VPC significantly reduces these risks by limiting access to trusted networks only.
Remediation Steps
Prerequisites
- AWS account access with permissions to manage Amazon MQ
- A VPC with private subnets where the new broker will be deployed
Important: The public accessibility setting cannot be changed after a broker is created. You must create a new broker with public access disabled and migrate your applications.
AWS Console Method
- Sign in to the AWS Management Console
- Navigate to Amazon MQ (search for "Amazon MQ" in the search bar)
- Click Brokers in the left navigation
- Click Create broker
- Choose your broker engine (ActiveMQ or RabbitMQ) and click Next
- Configure your broker settings:
- Enter a Broker name
- Select your Deployment mode
- Choose the Instance type
- Under Network and security:
- For Access type, select Private access
- Select your VPC and Subnet(s)
- Configure or create a Security group that allows access only from your application servers
- Configure authentication (username/password)
- Review your settings and click Create broker
- After the new broker is running, update your applications to use the new private endpoints
- Delete the old publicly accessible broker once migration is complete
AWS CLI (optional)
List existing brokers to identify publicly accessible ones:
aws mq list-brokers --region us-east-1
Check if a specific broker is publicly accessible:
aws mq describe-broker \
--broker-id <your-broker-id> \
--region us-east-1 \
--query 'PubliclyAccessible'
Create a new broker with public access disabled:
aws mq create-broker \
--broker-name my-private-broker \
--engine-type ACTIVEMQ \
--engine-version "5.17.6" \
--host-instance-type mq.t3.micro \
--deployment-mode SINGLE_INSTANCE \
--no-publicly-accessible \
--security-groups sg-0123456789abcdef0 \
--subnet-ids subnet-0123456789abcdef0 \
--users "Username=admin,Password=YourSecurePassword123!,ConsoleAccess=true" \
--region us-east-1
Delete the old publicly accessible broker (after migration):
aws mq delete-broker \
--broker-id <old-broker-id> \
--region us-east-1
CloudFormation (optional)
Deploy a private Amazon MQ broker using CloudFormation. The key setting is PubliclyAccessible: false.
AWSTemplateFormatVersion: '2010-09-09'
Description: Amazon MQ broker with private access only (not publicly accessible)
Parameters:
BrokerName:
Type: String
Description: Name of the Amazon MQ broker
Default: my-private-broker
EngineType:
Type: String
Description: Message broker engine type
AllowedValues:
- ACTIVEMQ
- RABBITMQ
Default: ACTIVEMQ
EngineVersion:
Type: String
Description: Version of the broker engine
Default: '5.17.6'
HostInstanceType:
Type: String
Description: Instance type for the broker
Default: mq.t3.micro
DeploymentMode:
Type: String
Description: Deployment mode for the broker
AllowedValues:
- SINGLE_INSTANCE
- ACTIVE_STANDBY_MULTI_AZ
- CLUSTER_MULTI_AZ
Default: SINGLE_INSTANCE
BrokerUsername:
Type: String
Description: Username for broker authentication
Default: admin
BrokerPassword:
Type: String
Description: Password for broker authentication
NoEcho: true
MinLength: 12
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC where the broker will be deployed
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Private subnet for the broker
Resources:
BrokerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Amazon MQ broker
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8162
ToPort: 8162
Description: ActiveMQ Web Console
CidrIp: 10.0.0.0/8
- IpProtocol: tcp
FromPort: 61617
ToPort: 61617
Description: ActiveMQ OpenWire
CidrIp: 10.0.0.0/8
- IpProtocol: tcp
FromPort: 5671
ToPort: 5671
Description: RabbitMQ AMQP
CidrIp: 10.0.0.0/8
Tags:
- Key: Name
Value: !Sub '${BrokerName}-sg'
MQBroker:
Type: AWS::AmazonMQ::Broker
Properties:
BrokerName: !Ref BrokerName
EngineType: !Ref EngineType
EngineVersion: !Ref EngineVersion
HostInstanceType: !Ref HostInstanceType
DeploymentMode: !Ref DeploymentMode
PubliclyAccessible: false
AutoMinorVersionUpgrade: true
SecurityGroups:
- !Ref BrokerSecurityGroup
SubnetIds:
- !Ref SubnetId
Users:
- Username: !Ref BrokerUsername
Password: !Ref BrokerPassword
ConsoleAccess: true
Tags:
- Key: Name
Value: !Ref BrokerName
Outputs:
BrokerId:
Description: The ID of the Amazon MQ broker
Value: !Ref MQBroker
BrokerArn:
Description: The ARN of the Amazon MQ broker
Value: !GetAtt MQBroker.Arn
BrokerEndpoints:
Description: The endpoints of the Amazon MQ broker
Value: !Join
- ','
- !GetAtt MQBroker.AmqpEndpoints
Deploy the stack:
aws cloudformation create-stack \
--stack-name private-mq-broker \
--template-body file://mq-broker.yaml \
--parameters \
ParameterKey=BrokerName,ParameterValue=my-private-broker \
ParameterKey=BrokerPassword,ParameterValue=YourSecurePassword123! \
ParameterKey=VpcId,ParameterValue=vpc-0123456789abcdef0 \
ParameterKey=SubnetId,ParameterValue=subnet-0123456789abcdef0 \
--region us-east-1
Terraform (optional)
Deploy a private Amazon MQ broker using Terraform. The critical setting is publicly_accessible = false.
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
variable "broker_name" {
description = "Name of the Amazon MQ broker"
type = string
default = "my-private-broker"
}
variable "engine_type" {
description = "Type of broker engine (ACTIVEMQ or RABBITMQ)"
type = string
default = "ACTIVEMQ"
}
variable "engine_version" {
description = "Version of the broker engine"
type = string
default = "5.17.6"
}
variable "host_instance_type" {
description = "Instance type for the broker"
type = string
default = "mq.t3.micro"
}
variable "deployment_mode" {
description = "Deployment mode for the broker"
type = string
default = "SINGLE_INSTANCE"
}
variable "broker_username" {
description = "Username for broker authentication"
type = string
default = "admin"
}
variable "broker_password" {
description = "Password for broker authentication"
type = string
sensitive = true
}
variable "vpc_id" {
description = "VPC ID where the broker will be deployed"
type = string
}
variable "subnet_ids" {
description = "List of subnet IDs for the broker"
type = list(string)
}
resource "aws_security_group" "mq_broker" {
name = "${var.broker_name}-sg"
description = "Security group for Amazon MQ broker"
vpc_id = var.vpc_id
ingress {
description = "ActiveMQ Web Console"
from_port = 8162
to_port = 8162
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
description = "ActiveMQ OpenWire"
from_port = 61617
to_port = 61617
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
description = "RabbitMQ AMQP"
from_port = 5671
to_port = 5671
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.broker_name}-sg"
}
}
resource "aws_mq_broker" "main" {
broker_name = var.broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
deployment_mode = var.deployment_mode
# CRITICAL: Disable public accessibility
publicly_accessible = false
auto_minor_version_upgrade = true
security_groups = [aws_security_group.mq_broker.id]
subnet_ids = var.subnet_ids
user {
username = var.broker_username
password = var.broker_password
console_access = true
}
tags = {
Name = var.broker_name
}
}
output "broker_id" {
description = "The ID of the Amazon MQ broker"
value = aws_mq_broker.main.id
}
output "broker_arn" {
description = "The ARN of the Amazon MQ broker"
value = aws_mq_broker.main.arn
}
output "broker_endpoints" {
description = "The endpoints of the Amazon MQ broker"
value = aws_mq_broker.main.instances[*].endpoints
}
Deploy with Terraform:
terraform init
terraform plan -var="broker_password=YourSecurePassword123!" \
-var="vpc_id=vpc-0123456789abcdef0" \
-var="subnet_ids=[\"subnet-0123456789abcdef0\"]"
terraform apply -var="broker_password=YourSecurePassword123!" \
-var="vpc_id=vpc-0123456789abcdef0" \
-var="subnet_ids=[\"subnet-0123456789abcdef0\"]"
Verification
After creating your new private broker:
- In the AWS Console, go to Amazon MQ > Brokers
- Click on your broker name
- Under Details, verify that Public accessibility shows No
- Confirm the broker endpoints are private VPC endpoints (not public URLs)
CLI verification
# Check that the broker is not publicly accessible
aws mq describe-broker \
--broker-id <your-broker-id> \
--region us-east-1 \
--query '{BrokerName: BrokerName, PubliclyAccessible: PubliclyAccessible}'
Expected output:
{
"BrokerName": "my-private-broker",
"PubliclyAccessible": false
}
Run the Prowler check to verify compliance:
prowler aws --checks mq_broker_not_publicly_accessible --region us-east-1
Additional Resources
- Amazon MQ Developer Guide
- Amazon MQ Security Best Practices
- Accessing the Amazon MQ Web Console
- VPC Endpoints for Amazon MQ
Notes
- Migration required: The public accessibility setting cannot be changed after broker creation. You must create a new broker and migrate your applications.
- Downtime consideration: Plan your migration carefully to minimize application downtime. Consider using a blue-green deployment approach.
- Security groups: Even with private brokers, configure security groups to allow access only from specific IP ranges or security groups of your application servers.
- VPN or Direct Connect: For on-premises applications that need to reach private brokers, set up AWS VPN or Direct Connect connectivity.
- Web console access: To access the broker's web console for a private broker, use a bastion host, AWS Systems Manager Session Manager, or a VPN connection.