主题 ARN 和目标 ARN AWS SNS 之间有什么区别?

Red*_*Red 9 amazon-sns boto3

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

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

这不起作用,因为它不断给我一个身份验证错误,如下所示:

Error publishing message because lambda_fn_role doesn't have the permissions to invoke SNS:Publish on resource blah_blah_arn
Run Code Online (Sandbox Code Playgroud)

但我确信我对该功能的策略是正确的,因此我将 TopicARN 更改为 TargetARN 并且它起作用了!

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

boto3 的 AWS 文档根本没有回答这个问题。

非常感激!

Mic*_*bot 5

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

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

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

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

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

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

新容器必须使用AssumeRoleAWS Security Token Service 中的操作获取 Lambda 执行角色的临时凭证,该服务提供临时 AWS-Access-Key-ID 和密钥以及会话令牌。Lambda将这些内容存储在环境变量中,如AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN,您的函数中的 AWS-SDK(用于调用其他服务,如本例中的 SNS)会拾取它们并使用它们来签署请求。

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

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

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

IAM 是一个庞大的分布式系统,因此它自然会偶尔出现“最终一致性”问题。

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

在您尝试给定的操作后,有时似乎会弹出该操作,但它失败了,并且您意识到需要编辑您打算足以允许该操作的 IAM 策略。因此,您编辑了该策略,但随后的尝试仍然失败,但该策略似乎有效,因此您无法弄清楚为什么它不起作用,然后您将双手举到空中,向 John Rotenstein 发送一条消息说您正在在你束手无策的时候……然后,在沮丧地放弃了一整晚之后,你第二天早上回来进一步排除故障,然后发现它突然开始工作了。

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

不管怎样,重新部署 Lambda 函数来测试代码更改可能会产生相同的效果,就像这里所做的那样。