限制S3存储桶公访问但允许Lambda访问,部署时提示无效策略主体错误
解决S3桶策略「无效主体」错误,实现禁用公共访问并允许Lambda访问
错误原因分析
- 使用角色名称而非ARN:用
!GetAtt ExampleFunction.Role获取的是Lambda执行角色的名称,而S3桶策略的Principal.AWS要求传入IAM角色的ARN,不是名称,这会触发「无效主体」错误。 - 错误拼接角色ARN:尝试的
!Sub 'arn:aws:iam::${AWS::AccountId}:role/${ExampleFunction.Arn}'格式错误,${ExampleFunction.Arn}是Lambda函数的ARN,不是角色的名称/ARN,拼接后不符合IAM角色ARN的规范(正确格式为arn:aws:iam::账号ID:role/角色名称)。
正确解决方案
方法1:直接引用Lambda执行角色ARN
如果Lambda执行角色是在同一模板中定义的(例如资源名为ExampleFunctionRole和AnotherExampleFunctionRole),直接通过!GetAtt获取角色ARN:
ResultsBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref ResultsBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Deny Action: s3:GetObject Resource: !Sub '${ResultsBucket.Arn}/*' Principal: '*' - Effect: Allow Action: s3:GetObject Resource: !Sub '${ResultsBucket.Arn}/*' Principal: AWS: - !GetAtt ExampleFunctionRole.Arn - !GetAtt AnotherExampleFunctionRole.Arn
方法2:通过Lambda函数间接获取角色ARN
若Lambda函数的Role属性直接传入的是IAM角色ARN,可通过!GetAtt获取该属性值(此时返回的是角色ARN):
ResultsBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref ResultsBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Deny Action: s3:GetObject Resource: !Sub '${ResultsBucket.Arn}/*' Principal: '*' - Effect: Allow Action: s3:GetObject Resource: !Sub '${ResultsBucket.Arn}/*' Principal: AWS: - !GetAtt ExampleFunction.Role - !GetAtt AnotherExampleFunction.Role
注意:此方法生效的前提是Lambda的
Role属性传入的是ARN,而非角色名称。
额外建议:开启公共访问阻止
为彻底禁用公共访问,除桶策略的Deny语句外,建议同时配置S3桶的公共访问阻止:
ResultsBucket: Type: AWS::S3::Bucket Properties: BucketName: your-bucket-name PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true
内容的提问来源于stack exchange,提问作者Keiron Lowe
相关产品推荐
相关产品推荐

