← Back to DevBytes

SQS Security: IAM Policies and Network Security

SQS Security: IAM Policies and Network Security

Amazon Simple Queue Service (SQS) is a fully managed message queuing service that enables decoupling and scaling of microservices, distributed systems, and serverless applications. Because SQS often carries sensitive data flowing between application components, securing access to your queues is critical. This tutorial covers the two primary pillars of SQS security: IAM (Identity and Access Management) policies that control who can interact with your queues, and network security controls that restrict where requests can originate from.

Why SQS Security Matters

By default, a newly created SQS queue is accessible only by the AWS account owner. However, in practice, queues are shared across services, roles, and sometimes even AWS accounts. Misconfigured permissions can lead to unauthorized message consumption, data leakage, message tampering, or denial-of-service through queue flooding. A defense-in-depth strategy combining IAM policies, resource-based policies, and network-level restrictions dramatically reduces your attack surface.

Understanding SQS Access Control Layers

SQS security operates at two policy layers that work together:

For an action to succeed, both the identity-based policy of the caller and the resource-based policy of the queue must allow the action (unless the caller and queue are in the same account, in which case a single explicit allow is sufficient).

Securing SQS with IAM Policies

Granting Least-Privilege Access to a Producer

A producer service only needs to send messages. Avoid granting sqs:* or broad sqs:SendMessage across all resources. Scope the action to a specific queue ARN:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSendMessageToOrdersQueue",
      "Effect": "Allow",
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue"
    }
  ]
}

Granting Least-Privilege Access to a Consumer

A consumer needs to receive, delete, and optionally change message visibility. It should not be able to purge the queue or alter its attributes:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowConsumeFromOrdersQueue",
      "Effect": "Allow",
      "Action": [
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:ChangeMessageVisibility"
      ],
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue"
    }
  ]
}

Using Condition Keys for Tighter Control

IAM condition keys let you constrain access further. For example, you can require that messages sent to a queue include specific attributes, or that requests originate from a specific VPC endpoint:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSendOnlyFromVpce",
      "Effect": "Allow",
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue",
      "Condition": {
        "StringEquals": {
          "aws:sourceVpce": "vpce-1a2b3c4d5e6f7g8h9"
        }
      }
    }
  ]
}

Other useful SQS-specific condition keys include sqs:MessageAttributeName, sqs:MessageGroupId, and aws:SourceArn (useful when an SNS topic or EventBridge rule is the only allowed publisher).

Restricting Publishers to a Known SNS Topic

If your queue subscribes to an SNS topic, you can ensure only that topic can publish to it using a resource-based policy with the aws:SourceArn condition:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSNSTopicToPublish",
      "Effect": "Allow",
      "Principal": {
        "Service": "sns.amazonaws.com"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-east-1:123456789012:orders-topic"
        }
      }
    }
  ]
}

Cross-Account Access

To allow an IAM role in account B (e.g., 999999999999) to read from a queue in account A (123456789012), attach a resource-based policy to the queue:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCrossAccountConsumer",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::999999999999:role/ConsumerRole"
      },
      "Action": [
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:GetQueueAttributes"
      ],
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue"
    }
  ]
}

The role in account B must also have an identity-based policy granting the same actions on the queue ARN. Both sides must explicitly allow the access.

Network Security for SQS

IAM policies answer "who can do what," but they do not restrict the network path. By default, SQS endpoints are reachable over the public internet. To prevent traffic from traversing the public internet and to restrict access to specific networks, use VPC endpoints and endpoint policies.

Creating a VPC Endpoint for SQS

A VPC endpoint (PrivateLink) for SQS keeps traffic between your VPC and SQS entirely within the AWS network. The following AWS CLI command creates an interface endpoint for SQS:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0abc123def456 \
  --service-name com.amazonaws.us-east-1.sqs \
  --subnet-ids subnet-0aaa subnet-0bbb \
  --security-group-ids sg-0123456789abcdef \
  --vpc-endpoint-type Interface

Once created, you receive a set of regional DNS names (e.g., vpce-1a2b3c4d5e6f7g8h9-abc123.sqs.us-east-1.vpce.amazonaws.com) that resolve to private IP addresses within your VPC.

VPC Endpoint Policies

Every VPC endpoint can have an attached endpoint policy that controls which principals can use the endpoint and which queues they can access. This is a powerful network-level control. The following policy restricts the endpoint to a single queue and a single role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RestrictToOrdersQueue",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/ConsumerRole"
      },
      "Action": [
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:SendMessage"
      ],
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue"
    }
  ]
}

Enforcing VPC-Only Access with IAM

To guarantee that no caller can reach your queue over the public internet, combine a VPC endpoint with an IAM policy that denies requests not coming through the endpoint. Use the aws:sourceVpce condition in a deny statement:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyIfNotFromVpce",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "sqs:*",
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue",
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "vpce-1a2b3c4d5e6f7g8h9"
        }
      }
    }
  ]
}

Be careful: this deny applies to all principals, including AWS services that may need to publish to your queue (such as SNS or EventBridge). If you use such integrations, add explicit allow statements for those service principals before the deny, or scope the deny to specific IAM roles instead of "Principal": "*".

Restricting by VPC or IP Address

You can also restrict access based on the source VPC ID or source IP range. The following resource-based policy denies access unless the request originates from a specific VPC:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideTrustedVpc",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "sqs:*",
      "Resource": "arn:aws:sqs:us-east-1:123456789012:orders-queue",
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpc": "vpc-0abc123def456"
        }
      }
    }
  ]
}

For IP-based restrictions, use aws:SourceIp with CIDR blocks. Note that aws:SourceIp is not effective when requests come through a VPC endpoint, because the source IP will be a private VPC address; in that case prefer aws:sourceVpce or aws:SourceVpc.

Server-Side Encryption (SSE) with KMS

While not strictly a network control, SSE-KMS complements network security by ensuring that messages at rest are encrypted and that only principals with kms:Decrypt and kms:GenerateDataKey permissions on the associated KMS key can read messages. Enable SSE on a queue with the CLI:

aws sqs set-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/orders-queue \
  --attributes KmsMasterKeyId=alias/sqs/orders-key

Then scope the KMS key policy to only the producer and consumer roles. This adds another layer: even if an IAM principal somehow gains sqs:ReceiveMessage permission, they cannot decrypt the payload without KMS access.

Best Practices

Conclusion

Securing SQS requires a layered approach: IAM identity-based policies define what each role can do, resource-based policies define who can touch a specific queue (including cross-account and service publishers), and network controls such as VPC endpoints and endpoint policies define where requests can come from. By combining least-privilege IAM grants, explicit deny rules tied to aws:sourceVpce or aws:SourceVpc, SSE-KMS encryption, and continuous monitoring through CloudTrail, you can ensure that your queues only accept traffic from trusted producers and only deliver messages to authorized consumers. Applying these controls consistently across every queue in your organization turns SQS from a convenient messaging primitive into a hardened, production-grade backbone for your distributed systems.

— Ad —

Google AdSense will appear here after approval

← Back to all articles