Cross account access to AWS SQS with Server-side Encryption enabled

Tofig Hasanov picture Tofig Hasanov · Jun 8, 2018 · Viewed 7.1k times · Source

Context: There is an API that lives in AWS account 2 takes SQS url as one of it's inputs and publishes output to it. Owner of account 1 wants to use this API with his own SQS queue.

Account 1 has an SQS queue with SSE-KMS enabled. Owner of account 1 wants a specific IAM user in account 2 to be able to publish to this SQS queue. The only way to achieve this that I know if is to:

  1. Add ID of external account 2 to account 1's KMS key settings
  2. Add a policy to account 2's IAM user to allow access to given KMS key

The problem with this approach is that both accounts need to take an action. Is there a simpler way to achieve same result where only account 1 owner needs to do anything and doesn't need to bother account 2's owner?

EDIT 1: When we try our integration without enabling encryption on SQS everything works fine. This is how we know that it's KMS issue, not SQS policy. As soon as we enable SQS encryption it starts to fail due to AccessDeniedException

Answer

John Rotenstein picture John Rotenstein · Jun 8, 2018

To test this situation, I did the following:

In Account-A:

  • Created User-1
  • Created a KMS key
  • Granted me permission to use the key, but not User-1
  • Created a queue in Account-A, activated SSE and selected the new key
  • Granted User-1 the AmazonSQSFullAccess permission policy

I then ran a command as User-1 to send a message to the queue:

aws sqs send-message --queue-url https://sqs.ap-southeast-2.amazonaws.com/123456789012/my-queue --message-body foo --profile user-1

The response was:

An error occurred (KMS.AccessDeniedException) when calling the SendMessage operation: User: arn:aws:iam::123456789012:user/user-1 is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:ap-southeast-2:123456789012:key/xxx (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxx)

So, this shows that the User must be granted permission to use KMS when sending a message to the queue, apparently to kms:GenerateDataKey. I assume that each message is encrypted separately via an unique key that is generated by KMS.

I then granted User-1 permission to use the KMS key and the command completed successfully. So, it is working within the same account.

Then, in Account-2:

  • Created User-2
  • Granted AmazonSQSFullAccess permissions

When I ran the command again with User-2's credentials, I received:

An error occurred (AccessDenied) when calling the SendMessage operation: Access to the resource https://ap-southeast-2.queue.amazonaws.com/ is denied.

This is expected, since User-2 is in a different account (Account-2).

I then went to the SQS queue in Account-1 and added permission for User-2 by providing User-2's ARN.

I ran the command again and got the familiar:

An error occurred (KMS.AccessDeniedException) when calling the SendMessage operation: null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxx)

Notice that it mentions ASKMS in the error.

I then updated the KMS key to allow arn:aws:iam::<Account-2>:root as an External Account.

That still didn't help. It turned out I had to add some kms:* type permissions to User-2. (Too any permissions, but I was getting lazy!)

This, then worked.

I then removed the KMS External Account permission and it still worked.

So, it seems that:

  • User-2 in Account-2 needs permissions to call SQS and KMS
  • The SQS queue in Account-1 needs permissions to allow User-2 to use the queue

You might want to ask them whether they really, really want to use a KMS key! :)