【问题标题】:Send messages from a lambda in one account to an SQS in another account将消息从一个帐户中的 lambda 发送到另一个帐户中的 SQS
【发布时间】:2021-10-05 14:01:42
【问题描述】:

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

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

我得到了一个

AWS.SimpleQueueService.NonExistentQueue

当尝试从 lambda 向队列 @9​​87654322@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 访问策略中。出于某种原因,在我原来的政策中,当我进行 Condition 检查时:

      "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 权限,并且允许 SQS 拥有的 KMS 密钥从 lambda 帐户访问。

【问题讨论】:

  • 是的,它已解决,请参阅问题的更新
  • 如果任何现有答案有帮助,接受它是一个很好的做法。

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


【解决方案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 角色。


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

  • 使用AmazonSQSFullAccess 策略为账户-A(发送账户)中的 Lambda 创建了 IAM 角色 Role-A
  • 使用访问策略在 Account-B(接收帐户)中创建了 SQS 队列 @9​​87654328@:
{
  "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"
    }
  ]
}
  • 在 Account-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'},'重试次数':0}}

消息已成功接收:

【讨论】:

  • 所以理想情况下,如果我已经设置了 SQS 访问策略(基本上将 Principal 设置为附加到另一个帐户中的 lambda 的 IAM 角色的 arn),我不需要在 IAM 角色中明确声明相同的 SQS 权限?
  • 我在尝试向队列 (boto3.resource('sqs').Queue(" some queue_url").send_message(**kwargs)) 发送内容时收到 AWS.SimpleQueueService.NonExistentQueue,我想知道是否需要将权限显式添加到 IAM 角色本身以允许发送到排队。
  • 表示队列 URL 不正确。 可能是因为它在不同的帐户中,但这无关紧要。与此类似:SQS Cross Account Access | Trend Micro。您确定您使用的是队列 URL 而不是队列 ARN?
  • 不,我很确定我使用了正确的队列 URL。
  • 您能否将您的代码和政策添加到您的问题中?随意隐藏您的帐户 ID。这提醒了我——确保您在队列 URL 中使用正确的帐户 ID
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2020-02-17
    • 1970-01-01
    • 2020-04-16
    • 2011-09-01
    • 1970-01-01
    • 2016-03-10
    • 2016-03-26
    • 1970-01-01
    • 2022-11-15
    相关资源
    最近更新 更多