据我了解,实例需要被授予cloudformation:*
资源访问权限才能使用 CloudFormation 执行任何操作。
但是当我在 Beanstalk Web 服务器实例上运行它时:
cfn-get-metadata -s awseb-e-xxxxxxxxx-stack -r AWSEBAutoScalingGroup
我得到了完整的元数据转储,没有问题。
- 我没有在命令行中指定任何访问/密钥。
- 我的实例角色是(由我)手动创建的,并且绝对不会授予任何
cloudformation:*
资源权限。
我为什么还能读取任何 CF 元数据?
我注意到在客户端代码中,脚本将使用实例凭据(self.using_instance_identity
为 True)
signer = CFNSigner() \
if self.using_instance_identity \
else V4Signer(region, 'cloudformation')
这是 CF 特有的魔法吗,还是我错过了授予 CF 权限的某些地方?
答案1
是的,CloudFormation 服务具有一种特殊的未记录的身份验证机制,允许堆栈中任何实例的 cfn-* 脚本无需使用 IAM 即可查看堆栈的元数据。它的工作原理可能是这样的:
- cfn-get-metadata 和其他 cfn-* 脚本包括的内容http://169.254.169.254/latest/dynamic/instance-identity/document(包含 instanceId 的 JSON 文档)和http://169.254.169.254/latest/dynamic/instance-identity/签名(base64 编码的 128 字节值)在 CloudFormation DescribeStackResource 请求中。
- CloudFormation 通过检查实例文档的签名是否由 EC2 服务签名来验证请求是否来自 EC2 实例。由于签名为 128 字节,因此它很可能是使用 EC2 维护的 RSA 1024 位私钥的签名。
- CloudFormation 从身份文档中获取 instanceId 并调用 DescribeTags 或 DescribeInstances 来获取与其关联的标签。
- CloudFormation 比较标签的值aws:cloudformation:堆栈名称和aws:cloudformation:逻辑 ID(用户无法修改)并且如果它们与请求的 StackName 和 LaunchConfig 匹配,则执行 DescribeStackResource 请求。