Consider two accounts Account A and Account B. We have to Encrypt an SQS queue in account B using a KMS key from account A and then, send and receive message to the queue using a lambda(which is in account A). SQS CFN TEMPLATE:
MyQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: !Ref QueueName
DelaySeconds: '0'
MaximumMessageSize: '262144'
MessageRetentionPeriod: '345600'
ReceiveMessageWaitTimeSeconds: '0'
VisibilityTimeout: '30'
KmsMasterKeyId: <Key_id of the custom CMK> (I have a doubt here also, should i input the key id or the alias of my key?)
KEY POLICY:
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<Account_B_id>:root",
"arn:aws:iam::<Account_A_id>:root",
"arn:aws:iam::<Account_A_id>:role/lambda-execution-role"
]
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Account_A_id>:role/lambda-execution-role"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion",
"kms:ReplicateKey",
"kms:UpdatePrimaryRegion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<Account_B_id>:root",
"arn:aws:iam::<Account_A_id>:role/lambda-execution-role"
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<Account_B_id>:root",
"arn:aws:iam::<Account_A_id>:role/lambda-execution-role"
]
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}
SQS Queue policy:
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Account_A_id>:role/lambda-execution-role"
},
"Action": "sqs:*",
"Resource": "arn:aws:sqs:us-east-2:<Account_B_id>:queue"
}
]
}
Lambda function - Python code for send and receive message to the queue:
import json
import boto3
def lambda_handler(event, context):
sqs = boto3.client('sqs', region_name='us-east-2')
queue_url = 'https://sqs.us-east-2.amazonaws.com/<Account_B_id>/queue'
response = sqs.send_message(QueueUrl=queue_url,DelaySeconds=0,MessageBody=('hey there 123 !'))
response1 = sqs.send_message(QueueUrl=queue_url,DelaySeconds=0,MessageBody=('hey there 1234 !'))
response2 = sqs.send_message(QueueUrl=queue_url,DelaySeconds=0,MessageBody=('hey there 123345 !'))
print('message sent')
response5 = sqs.receive_message(
QueueUrl=queue_url,
AttributeNames=['All'],
MaxNumberOfMessages=10,
WaitTimeSeconds=7)
message = response5['Messages'][0]['Body']
print(message)
After doing all these things, I have created a test event in lambda and tested it. Getting the below error:
[ERROR] ClientError: An error occurred (KMS.AccessDeniedException) when calling the SendMessage operation: null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: d6913dbc-e22f-4ccf-ba5a-9844ab1156e0; Proxy: null)
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 6, in lambda_handler
response = sqs.send_message(QueueUrl=queue_url,DelaySeconds=0,MessageBody=('hey there 123 !'))
File "/var/runtime/botocore/client.py", line 386, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 705, in _make_api_call
raise error_class(parsed_response, operation_name)
Without KMS this set up is working. Can someone help me out for integrating the KMS in this?
For resolving this, i reached out to AWS Support and got the solution. Initially i had my key in us-east-1 and trying to use it. In order to access an SQS in us-east-2, the key must also be in us-east-2. So the solution suggested to me was, Create a replica of the key in us-east-2 and input the arn of the replica key (I did a mistake here too, i gave the key id in the cfn template) in the cloudformation template (Since i was using a multi-region key). If it isn't a multi-region key, we must create a new key in the same region of the SQS queue.