将消息从一个帐户中的 lambda 发送到另一个帐户中的 SQS

时间:2021-07-29 23:54:41

标签: amazon-web-services aws-lambda amazon-iam amazon-sqs

对于来自 lambda 的 SQS 的跨账户访问,我是否需要允许附加到 lambda 的 IAM 角色拥有 SQS 权限,或者允许 IAM 角色在 SQS 的访问策略中拥有权限? (或者两者都做?)

更新:基本上我按照以下一些答案中的建议设置了 SQS 访问策略。

我得到一个

<块引用>

AWS.SimpleQueueService.NonExistentQueue

当尝试从 lambda 向队列 (boto3.resource('sqs').Queue(" some queue_url").send_message(**kwargs))` 发送内容时,我想知道是否有权限需要显式添加到 IAM 角色本身以允许发送到队列。

在 lambda(在 us-west-1 中)发送到 SQS 的代码如下:

import boto3
from botocore.config import Config
def lambda_handler(event, context):
    boto3.resource('sqs').Queue('https://sqs.us-east-1.amazonaws.com/sqs_accnt_num/name_of_sqs').send_message(MessageBody="SomeMessageJSONDUMP") 

SQS 访问策略如下:

{
  "Version": "2012-10-17"
  "Id": "SomeID",
  "Statement" : [
    {
      "Sid": "somesid",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "SQS:SendMessage",
      "Resource":"arn:aws:sqs:us-east-1:sqs_accnt_num:name_of_sqs",
      "Condition": {
         "ArnEquals": {
            "aws:SourceArn": "arn:aws:iam::lambda_accnt_num:role/name:" 
          } 
       }
    },
    {
      "Sid": "somesid2",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "sqs:*",
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:secureTransport": "false"
         }
      }
  }
]} 

更新:问题已解决:

所以看起来问题出在 SQS 访问策略中。出于某种原因,在我进行条件检查时的原始政策中,如:

      "Sid": "somesid",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "SQS:SendMessage",
      "Resource":"arn:aws:sqs:us-east-1:sqs_accnt_num:name_of_sqs",
      "Condition": {
         "ArnEquals": {
            "aws:SourceArn": "arn:aws:iam::lambda_accnt_num:role/name:" 
          } 
       }

然后,在尝试从 lambda 发送消息时,我仍然收到“拒绝访问”错误。但是正如 John Rotenstein 在他的回答中所建议的那样,我完全删除了 Condition 子句,并将 iam 角色 arn 直接放在 Principal 中,如下所示:

      "Sid": "somesid2",
      "Effect": "Allow",
      "Principal": {
            "AWS":"arn:aws:iam::lambda_accnt_num:role/name:"
      },
      "Action": "sqs:*",
      "Resource": "arn:aws:sqs:us-east-1:sqs_accnt_num:name_of_sqs"

成功了! 虽然问题已解决,但有谁知道为什么我的原始政策(带有 Condition 条款)不起作用?我认为政策本身没有任何问题。

John Rotenstein 的回答中的一个小警告;对于来自 lambda 的跨区域 sqs 访问,您必须添加 region_name 字段来表示 sqs 所在的区域,同时创建 sqs_resource,如下所示:

boto3.resource('sqs', region_name='us-east-1')

此外,如果您在 SQS 中启用了加密,请确保您的 lambda 具有 KMS 权限,并且允许从 lambda 帐户访问 SQS 拥有的 KMS 密钥。

2 个答案:

答案 0 :(得分:1)

这取决于你将如何做到这一点。一种方法是:

  • 在 SQS Acc 中设置代入角色,可由不同账户中的 lambda 函数代入。
  • 该函数具有 assume-role 权限,因此它可以承担来自 SQS 帐户的角色。
  • lambda 调用 assume-role 以获取临时凭据以在 SQS 帐户中执行操作。

另一种方式是通过基于 SQS 资源的策略,这将允许 lambda 角色向其提交消息。

答案 1 :(得分:1)

Amazon SQS 队列可以获得访问策略

此策略允许您授予实体访问队列的权限,包括来自其他 AWS 账户的实体

因此,您可以简单地编辑 SQS 队列上的访问策略,以允许从 AWS Lambda 函数使用的 IAM 角色的 ARN 进行访问。

以下是来自 Identity and access management in Amazon SQS - Amazon Simple Queue Service 的示例:

<块引用>

以下示例 Amazon SQS 策略授予 AWS 账户 111122223333 向 AWS 账户 444455556666 拥有的 queue2 发送和接收的权限。

{   
   "Version": "2012-10-17",
   "Id": "UseCase1",
   "Statement" : [{
      "Sid": "1", 
      "Effect": "Allow",           
      "Principal": {
         "AWS": [
            "111122223333"
         ]
      },
      "Action": [
         "sqs:SendMessage",
         "sqs:ReceiveMessage"
      ], 
      "Resource": "arn:aws:sqs:us-east-2:444455556666:queue2"  
   }]
}

您应该能够更改 Principal 以引用正在使用的特定 IAM 角色。


更新:为了重现您的情况,我执行了以下操作:

  • 使用 Role-A 策略为账户 A(发送账户)中的 Lambda 创建 IAM 角色 AmazonSQSFullAccess
  • 使用访问策略在账户 B(接收账户)中创建 SQS 队列 Queue-B
{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__owner_statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::Account-B:root"
      },
      "Action": "SQS:*",
      "Resource": "arn:aws:sqs:ap-southeast-2:Account-B:queue-b"
    },
    {
      "Sid": "__sender_statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::Account-A:role/role-a"
      },
      "Action": "SQS:SendMessage",
      "Resource": "arn:aws:sqs:ap-southeast-2:Account-B:queue-b"
    }
  ]
}
  • 在账户 A 中创建了 AWS Lambda 函数 Lambda-A 以向 Queue-B 发送消息:
import boto3

def lambda_handler(event, context):
    
    sqs_resource = boto3.resource('sqs')
    queue = sqs_resource.Queue('https://sqs.ap-southeast-2.amazonaws.com/Account-B/queue-b')
    response = queue.send_message(MessageBody="SomeMessageJSONDUMP")
    
    # Debug
    print(response)

调试日志条目为:

<块引用>

{'MD5OfMessageBody': '...', 'MessageId': '...', 'ResponseMetadata': {'RequestId': '...', 'HTTPStatusCode': 200, 'HTTPHeaders': { 'x-amzn-requestid': '...', 'date': 'Fri, 30 Jul 2021 23:25:40 GMT', 'content-type': 'text/xml', 'content-length': '378'}, 'RetryAttempts': 0}}

消息已成功接收:

SQS queue