Amazon Forecast创建数据集导入作业S3角色为何需S3全资源权限?
我最近写了个Lambda函数用来调用Amazon Forecast的API创建数据集导入作业,这个请求的Datasource属性里必须包含S3配置,指定Forecast能访问S3的IAM角色。为了遵循最小权限原则,我想给这个角色配置尽可能少的权限,但遇到了麻烦:我把操作限制在s3:ListBucket和s3:GetObject,但只有当Resource设为*时才正常工作;如果指定具体的存储桶ARN(比如arn:aws:s3:::my-bucket/*)或者具体文件ARN(arn:aws:s3:::my-bucket/path/to/my_file.csv),就会报错——本地用SAM CLI跑的时候提示An error occurred (404) when calling the HeadObject operation: Not Found,在Lambda控制台跑则是An error occurred (403) when calling the HeadObject operation: Forbidden。
我想知道有没有人碰到过这种情况,为啥Forecast创建数据集导入作业的时候必须给S3全资源访问,而不能只指定单个存储桶或文件?
下面是我用CloudFormation定义的角色:
CreateDatasetImportJobS3Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - forecast.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ReadFromBucketPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:ListBucket - s3:GetObject # 这里我不想用星号资源,但似乎必须设为Resource: "*"才能生效
嗨,我之前也碰到过一模一样的问题!其实不是必须用Resource: "*",而是你没搞清楚Forecast在导入数据时的权限需求细节——它的API调用过程中,除了访问你指定的文件,还会做一些额外的S3操作,而且权限的Resource配置需要区分s3:ListBucket和s3:GetObject的不同要求:
s3:ListBucket的Resource必须是存储桶本身的ARN,而不是桶内对象的ARN。因为ListBucket操作是针对存储桶级别的,所以要写成arn:aws:s3:::my-bucket,而不是带/*的路径。s3:GetObject的Resource才是桶内对象的ARN,可以指定具体文件或者路径前缀,比如arn:aws:s3:::my-bucket/path/to/*或者单个文件的ARN。
另外,Forecast在处理导入作业时,会先调用s3:HeadObject来验证文件的存在性和元数据,这个操作其实是包含在s3:GetObject权限里的,但如果你的Resource配置不对,就会触发权限错误或者404(因为权限不足导致Forecast无法确认文件存在,返回的错误信息有点误导)。
给你修正后的CloudFormation权限配置,这样就能实现最小权限了:
CreateDatasetImportJobS3Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - forecast.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ReadFromBucketPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: s3:ListBucket Resource: arn:aws:s3:::my-bucket - Effect: Allow Action: s3:GetObject Resource: arn:aws:s3:::my-bucket/path/to/my_file.csv
这样配置后,Forecast就能正常访问指定的存储桶和文件,同时遵循了最小权限原则。之前的错误就是因为把ListBucket的Resource设成了对象路径,导致Forecast无法列出桶内容来定位文件,进而触发了403或404错误。
内容的提问来源于stack exchange,提问作者Matt

