配置GitHub Action上传静态文件至S3静态网站遇权限问题求助
GitHub Action 上传S3存储桶出现AccessDenied错误的解决方案
问题背景
尝试配置GitHub Action将HTML、CSS等静态文件上传至AWS S3静态网站存储桶,但执行时触发AccessDenied错误,无法完成上传。已创建IAM用户github_runner并配置了用户策略和桶策略,但权限仍未生效。
IAM用户github_runner的策略
{ "Version": "2012-10-17", "Statement": [ { "Sid": "S3AccessWebBucket", "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::myrealbucket-web", "arn:aws:s3:::myrealbucket-web/*" ] } ] }
S3存储桶策略
{ "Version": "2012-10-17", "Statement": [ { "Sid": "SourceIP", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::myrealbucket-web", "arn:aws:s3:::myrealbucket-web/*" ], "Condition": { "NotIpAddress": { "aws:SourceIp": [ "0.0.0.0/32", // 允许的内部访问IP "0.0.0.0/32" ] }, "ArnNotEquals": { "aws:SourceArn": "arn:aws:iam::11111111:user/github_runner" } } }, { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::myrealbucket-web/*" }, { "Sid": "Stmt", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::11111111:user/github_runner" }, "Action": "s3:*", "Resource": "arn:aws:s3:::myrealbucket-web" } ] }
GitHub Action执行错误信息
Run aws s3 mv ./index.html *** aws s3 mv ./index.html *** aws s3 mv ./style.css *** aws s3 mv ./script.js *** shell: /usr/bin/bash -e {0} env: AWS_DEFAULT_REGION: *** AWS_REGION: *** AWS_ACCESS_KEY_ID: *** AWS_SECRET_ACCESS_KEY: *** move failed: ./index.html to ***/index.html An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
问题原因
- 桶策略拒绝规则逻辑错误:当前
SourceIP语句的条件是同时满足NotIpAddress(不在指定IP段)和ArnNotEquals(不是指定IAM用户)时才拒绝。GitHub Action的运行IP不在你指定的内部IP段,因此即使使用github_runner用户,该拒绝规则依然触发,阻止了上传操作。 - 桶策略权限范围不全:第三个授权语句仅覆盖了存储桶本身的权限,未包含存储桶内的对象路径(
arn:aws:s3:::myrealbucket-web/*),而PutObject操作需要的是对象路径的权限。 - 条件匹配错误:使用了
aws:SourceArn而非aws:PrincipalArn来匹配IAM用户,aws:SourceArn通常用于资源级别的关联,而非用户身份验证。
修复方案
1. 修正桶策略的拒绝规则
将拒绝规则的条件改为逻辑或,并排除公共读的GetObject操作,同时使用正确的aws:PrincipalArn匹配用户:
{ "Sid": "SourceIP", "Effect": "Deny", "Principal": "*", "Action": [ "s3:*", "!s3:GetObject" // 保留公共读权限 ], "Resource": [ "arn:aws:s3:::myrealbucket-web", "arn:aws:s3:::myrealbucket-web/*" ], "Condition": { "Or": [ { "NotIpAddress": { "aws:SourceIp": [ "0.0.0.0/32", // 替换为你的实际内部IP "0.0.0.0/32" ] } }, { "StringNotEquals": { "aws:PrincipalArn": "arn:aws:iam::11111111:user/github_runner" } } ] } }
此规则表示:如果请求不在允许的IP段或者不是指定的IAM用户,则拒绝除GetObject之外的所有S3操作。
2. 补全IAM用户的对象权限
修改第三个桶策略语句,将资源范围扩展到存储桶内的所有对象:
{ "Sid": "Stmt", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::11111111:user/github_runner" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::myrealbucket-web", "arn:aws:s3:::myrealbucket-web/*" ] }
3. 验证权限
- 使用AWS IAM Access Analyzer检查策略的有效性,确认没有冲突或语法错误。
- 在本地使用
github_runner的Access Key和Secret Key执行aws s3 cp test.html s3://myrealbucket-web/test.html,测试上传权限是否正常。
内容的提问来源于stack exchange,提问作者lunchbox7804
相关产品推荐
相关产品推荐

