使用来自另一个帐户(us-east-1)的密钥加密 sqs 队列(us-east-2)并使用 lambda 访问它 - 面临错误
Encrypting an sqs queue(us-east-2) using a key from another account(us-east-1) and access it using lambda - facing error
考虑两个帐户帐户 A 和帐户 B。我们必须使用帐户 A 中的 KMS 密钥加密帐户 B 中的 SQS 队列,然后使用 lambda(在帐户 A 中)向队列发送和接收消息).
SQS CFN 模板:
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?)
主要政策:
{
"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 队列策略:
{
"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 函数 - Python 向队列发送和接收消息的代码:
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)
完成所有这些事情后,我在 lambda 中创建了一个测试事件并对其进行了测试。出现以下错误:
[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)
在没有 KMS 的情况下,此设置有效。有人可以帮助我将 KMS 集成到其中吗?
为了解决这个问题,我联系了 AWS Support 并获得了解决方案。最初我将我的密钥输入 us-east-1 并尝试使用它。为了访问 us-east-2 中的 SQS,密钥也必须在 us-east-2 中。所以向我建议的解决方案是,在 us-east-2 中创建密钥的副本并输入副本密钥的 arn (我在这里也犯了一个错误,我在cfn 模板) 在 cloudformation 模板中 (因为我使用的是 multi-region 密钥)。如果它不是 multi-region 密钥,我们必须在 SQS 队列的同一区域中创建一个新密钥。
考虑两个帐户帐户 A 和帐户 B。我们必须使用帐户 A 中的 KMS 密钥加密帐户 B 中的 SQS 队列,然后使用 lambda(在帐户 A 中)向队列发送和接收消息). SQS CFN 模板:
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?)
主要政策:
{
"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 队列策略:
{
"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 函数 - Python 向队列发送和接收消息的代码:
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)
完成所有这些事情后,我在 lambda 中创建了一个测试事件并对其进行了测试。出现以下错误:
[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)
在没有 KMS 的情况下,此设置有效。有人可以帮助我将 KMS 集成到其中吗?
为了解决这个问题,我联系了 AWS Support 并获得了解决方案。最初我将我的密钥输入 us-east-1 并尝试使用它。为了访问 us-east-2 中的 SQS,密钥也必须在 us-east-2 中。所以向我建议的解决方案是,在 us-east-2 中创建密钥的副本并输入副本密钥的 arn (我在这里也犯了一个错误,我在cfn 模板) 在 cloudformation 模板中 (因为我使用的是 multi-region 密钥)。如果它不是 multi-region 密钥,我们必须在 SQS 队列的同一区域中创建一个新密钥。