【问题标题】:What is the difference between Topic ARN and Target ARN AWS SNS?主题 ARN 和目标 ARN AWS SNS 有什么区别?
【发布时间】:2020-02-07 08:52:07
【问题描述】:

我试图在 Lambda 中使用 boto3 将消息发布到 SNS 主题,如下所示:

def publish_msg(msg, bar):
    response = SNS.publish(
        TopicArn='blah_blah_arn',
        Message=msg,
        MessageAttributes={
            'foo': {
                'DataType': 'String',
                'StringValue': bar
            }
        }
    )

这不起作用,因为它一直给我一个类似这样的身份验证错误:

Error publishing message because lambda_fn_role doesn't have the permissions to invoke SNS:Publish on resource blah_blah_arn

但我确信我对该函数的策略是正确的,所以我将 TopicARN 更改为 TargetARN,它起作用了!

所以我的问题是:主题和目标 ARN 有什么区别?什么时候应该使用一个而不是另一个?

AWS docs for boto3 根本不回答这个问题。

非常感谢!

【问题讨论】:

  • 这确实很有趣!我同意文档在两者之间没有太大区别,除了说TopicARN 是“您要发布到的主题”。我可以理解在向非主题(例如移动应用程序)发布消息时应该使用TargetARN,但奇怪的是它也适用于发送到 SNS 主题!我刚刚进行了一些测试并验证了它对我使用TopicARNTargetARN 都有效。据推测,我对这两种情况都有足够的权限。
  • 我建议您现在尝试将其改回,并且我怀疑无论您提供哪种选项,它都会按预期工作。我认为问题与执行角色的临时凭据的缓存有关,而不是与您的代码中的任何内容有关。要进行您所做的更改,您必须重新部署 Lambda 函数,该函数会自动将该函数部署到一个新容器中,并为执行角色提供一组新的临时凭证,这将解决该问题。如果您在之前部署之前不久或之后的任何时间编辑角色权限,这似乎特别有可能。
  • 传奇@迈克尔!做到了,感谢您解释为什么这也有效,非常有帮助!

标签: boto3 amazon-sns


【解决方案1】:

事实证明,这里的问题并不像看起来那样。

TopicArnTargetArn 在这种情况下实际上是可以互换的。 (为什么有两种可能的方式来传递主题 ARN?SNS 最初只支持主题作为目标,但现在支持其他类型的东西,所以这很可能是 API 向后兼容的情况,AWS 通常非常擅长。)

tl;dr:有时,当 Lambda 执行角色使用的 IAM 策略被修改时,Lambda 函数的行为不像发生了策略更改一样。

它似乎仅在从一个更改为另一个后才起作用的原因与(在某种程度上)更新 Lambda 函数的代码时发生的情况有关。

Lambda 服务管理运行您的代码的容器,每个容器一次运行不超过一个函数的并发调用。后续调用可能会重用同一个容器……但前提是与函数关联的代码相同且未更改。

更新函数代码,然后再次运行函数(第一次使用新代码),保证您处于一个以前未使用过的新容器中。

新容器必须使用 AWS Security Token Service 中的 AssumeRole 操作获取 Lambda 执行角色的临时凭证,该操作提供临时 AWS-Access-Key-ID 和密钥以及会话令牌。 Lambda stores these in environment variables as AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN,您的函数中的 AWS-SDK(在此示例中用于调用其他服务,如 SNS)提取它们并使用它们进行签名请求。

OP 遇到的是这个设置的某个地方的一个怪癖。 IAM 或 STS 中的某些内容会导致 AWS 系统内的缓存或陈旧数据——允许 Lambda 执行角色针对相关主题执行SNS:Publish 操作所必需的策略(或最新版本的策略)不是对需要查看它的组件可见,以便允许该操作。

目前尚不清楚这种缓存究竟发生在哪里。 Lambda 当然会缓存临时凭证,但 EC2 元数据服务也会缓存,任何表现良好的客户端也会缓存,因为当临时凭证仍然有效时不断向 STS 发出请求是没有意义的。我不相信凭据本身的缓存是原因(尽管它有所贡献)。

STS 凭据是一个黑匣子,尤其是“会话令牌”。它是否包含加密数据?或者它只是一个很大的随机值,实际上只不过是一个没有内在意义的象征性“令牌”?这并不重要,但关键是它没有明确记录。

IAM 是一个庞大的分布式系统,因此它有时自然会具有“最终一致性”issues that can arise

但是,不知何故,创建一个新的 Lambda 容器——它必然必须对 STS 进行新的调用——似乎有一个缓存破坏的副作用,它使得执行角色的当前 IAM 策略在某些情况下变得可用不工作,在新的部署中。

在您尝试给定操作后,有时会弹出该操作,但它会失败,并且您意识到您需要编辑您打算足以允许该操作的 IAM 策略。因此,您编辑了策略,但随后的尝试仍然失败,但该策略似乎有效,因此您无法弄清楚为什么它不起作用,然后您举起双手,向 John Rotenstein 发送消息说您是不知所措......然后,在绝望地放弃了一夜之后,您第二天早上回来进一步排除故障,发现它突然起作用了。

大概这与旧的执行角色临时凭证被替换有关,要么是由于容器由于不活动而被修剪和替换,要么仅仅是因为临时凭证的寿命有限......但目前尚不清楚是否刷新 STS令牌实际上是解决方案的必要部分,或者它是否只是将 IAM 侧的僵局作为副作用修复。

重新部署 Lambda 函数以测试代码更改可能会产生与此处相同的效果,无论哪种方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-23
    • 2021-09-13
    • 1970-01-01
    • 2021-05-14
    • 2021-12-13
    • 2020-07-13
    • 2019-04-01
    相关资源
    最近更新 更多