SQS cross-account access is usually set up to allow services in one AWS account to send messages to or receive messages from a queue in another AWS account.
Here’s a typical setup where an application in Account B needs to send messages to an SQS queue in Account A.
{
"Version": "2012-01-01",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__owner_statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_A_ID:root"
},
"Action": "sqs:*",
"Resource": "arn:aws:sqs:REGION:ACCOUNT_A_ID:YOUR_QUEUE_NAME"
},
{
"Sid": "AllowSendFromAccountB",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_B_ID:root"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:REGION:ACCOUNT_A_ID:YOUR_QUEUE_NAME",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:lambda:REGION:ACCOUNT_B_ID:function:YOUR_LAMBDA_FUNCTION_NAME"
}
}
}
]
}
In this policy, Account A owns the queue. The __owner_statement grants full SQS access to the account owner. The AllowSendFromAccountB statement is the crucial part for cross-account access. It allows principals from Account B to perform the sqs:SendMessage action on the queue in Account A. The Condition block is highly recommended to restrict which resources in Account B can perform this action, in this case, a specific Lambda function.
The most surprising true thing about SQS cross-account access is that the IAM principal performing the action (e.g., the Lambda function in Account B) also needs IAM permissions to access the SQS queue, in addition to the queue policy allowing it. The queue policy acts as an allow list for the queue itself, but the sender’s IAM role/user still needs the underlying permissions.
Let’s see this in action. Imagine a Lambda function in Account B (ACCOUNT_B_ID) that needs to send a message to an SQS queue named my-cross-account-queue in Account A (ACCOUNT_A_ID) in us-east-1.
First, in Account A, we attach the following queue policy to my-cross-account-queue:
{
"Version": "2012-01-01",
"Statement": [
{
"Sid": "AllowSendFromAccountB",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_B_ID:root"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:ACCOUNT_A_ID:my-cross-account-queue",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:lambda:us-east-1:ACCOUNT_B_ID:function:my-sender-lambda"
}
}
}
]
}
This policy says: "Allow principals identified by ACCOUNT_B_ID to send messages to this queue, but only if the source ARN matches the specific Lambda function my-sender-lambda."
Now, in Account B, the IAM role assumed by my-sender-lambda needs a policy that grants it permission to send messages to the SQS queue in Account A.
{
"Version": "2012-01-01",
"Statement": [
{
"Effect": "Allow",
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:ACCOUNT_A_ID:my-cross-account-queue"
}
]
}
This IAM policy states: "Allow sqs:SendMessage action on the SQS queue arn:aws:sqs:us-east-1:ACCOUNT_A_ID:my-cross-account-queue."
When my-sender-lambda in Account B attempts to send a message:
- AWS IAM checks the permissions of the
my-sender-lambda’s execution role. Does it havesqs:SendMessagepermission for the target queue ARN? If not, access is denied. - If IAM permits it, SQS then checks the queue policy attached to
my-cross-account-queue. Does the principal (which is associated withAccount B’s root ARN) havesqs:SendMessagepermission, and does it satisfy any conditions (likeaws:SourceArn)? If not, access is denied.
Both must be true for the message to be sent successfully.
The Principal element in the queue policy can be more granular than just AWS: arn:aws:iam::ACCOUNT_B_ID:root. You can specify individual IAM users, roles, or even AWS service principals (like lambda.amazonaws.com) if you want to delegate access more narrowly. For example, Principal: { "AWS": "arn:aws:iam::ACCOUNT_B_ID:role/MySpecificSenderRole" } would only allow that specific role in Account B to send messages, provided the aws:SourceArn condition is also met.
The aws:SourceArn condition is incredibly powerful for limiting which specific resources within the trusted account can interact with your queue. Without it, any IAM principal in Account B with sqs:SendMessage permission could send messages to your queue, which is often too broad.
The next challenge is often setting up cross-account receiving of messages, which involves different SQS actions and potentially more complex IAM configurations for the consumer.