我试图像这样在Lambda中使用boto3将消息发布到SNS主题:
def publish_msg(msg, bar):
response = SNS.publish(
TopicArn='blah_blah_arn',
Message=msg,
MessageAttributes={
'foo': {
'DataType': 'String',
'StringValue': bar
}
}
)
无效,因为它不断给我一个auth错误,如下所示:
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根本没有回答这个问题。
非常感谢!
答案 0 :(得分:2)
事实证明,这里的问题并不像看起来那样。
在这种情况下, TopicArn
和TargetArn
实际上是可以互换的。 (为什么有两种可能的方法来传递主题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分别为AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
和AWS_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策略。因此,您编辑了该策略,但是随后的尝试仍然失败,但是该策略似乎仍然有效,因此您无法弄清它为何不起作用,于是不知所措,向约翰·罗滕斯坦发送了一条信息,告知您在机智的尽头...然后,在失望的夜晚放弃后,您第二天早上返回进一步进行故障排除,发现它突然开始工作。
大概这与替换旧执行角色有关,因为是由于不活动而对容器进行了修剪和替换,或者仅仅是因为临时凭据的寿命有限,所以替换了临时凭据……但是尚不清楚是否刷新STS令牌实际上是解决方案的必要部分,或者它是否只是解决了附加IAM中的对数冲突问题。
无论采用哪种方式,重新部署Lambda函数以测试代码更改都可能具有与此处相同的效果。