Skip to main content

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

  1. Sign in to the AWS Management Console
  2. Navigate to Amazon MQ (search for "Amazon MQ" in the search bar)
  3. Click Brokers in the left navigation
  4. Click Create broker
  5. Choose your broker engine (ActiveMQ or RabbitMQ) and click Next
  6. Configure your broker settings:
    • Enter a Broker name
    • Select your Deployment mode
    • Choose the Instance type
  7. 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
  8. Configure authentication (username/password)
  9. Review your settings and click Create broker
  10. After the new broker is running, update your applications to use the new private endpoints
  11. 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:

  1. In the AWS Console, go to Amazon MQ > Brokers
  2. Click on your broker name
  3. Under Details, verify that Public accessibility shows No
  4. 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

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.