如何将S3预签名URL有效期从12小时延长至24小时?
解决Lambda生成S3预签名URL有效期受限问题
核心原因
Lambda默认使用的执行角色临时凭证有效期固定为12小时,预签名URL的有效期无法超过生成它的凭证的有效期,所以即使你把预签名URL设为7天,实际也会在12小时后失效。要延长到24小时,需要通过Assume另一个IAM角色来获取更长有效期的临时凭证。
具体解决方案
1. 创建并配置目标IAM角色
- 新建一个IAM角色,信任策略允许Lambda执行角色Assume它:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::你的账号ID:role/Lambda执行角色ARN" }, "Action": "sts:AssumeRole", "Condition": { "NumericLessThanEquals": { "sts:DurationSeconds": 86400 } } } ] }
- 给该角色添加所需的S3操作权限(如
s3:GetObject/s3:PutObject,根据预签名URL用途设置)。 - 在IAM控制台角色详情页,将最大会话时长(MaxSessionDuration)修改为24小时(86400秒)。
2. 修改Go代码,通过AssumeRole创建S3客户端
替换原session创建逻辑,先获取有效期24小时的临时凭证,再生成S3客户端:
import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/sts" ) func createS3Client() (*s3Client, error) { // 基于Lambda默认执行角色创建基础会话 baseSession := session.Must(session.NewSession(&aws.Config{ Region: aws.String("us-west-2"), })) // 调用STS服务Assume目标角色,获取24小时有效期的临时凭证 stsClient := sts.New(baseSession) assumeRoleInput := &sts.AssumeRoleInput{ RoleArn: aws.String("arn:aws:iam::你的账号ID:role/新建角色ARN"), RoleSessionName: aws.String("lambda-s3-presign-session"), DurationSeconds: aws.Int64(86400), // 必须不超过目标角色的MaxSessionDuration } assumeRoleOutput, err := stsClient.AssumeRole(assumeRoleInput) if err != nil { return nil, err } // 使用临时凭证创建S3客户端 creds := credentials.NewStaticCredentials( *assumeRoleOutput.Credentials.AccessKeyId, *assumeRoleOutput.Credentials.SecretAccessKey, *assumeRoleOutput.Credentials.SessionToken, ) s3Session := session.Must(session.NewSession(&aws.Config{ Region: aws.String("us-west-2"), Credentials: creds, })) return &s3Client{ client: s3.New(s3Session), } }
3. 调整预签名URL的有效期
生成预签名URL时,设置的有效期不能超过24小时:
// 示例:生成PutObject类型的预签名URL req, err := s3Client.client.PutObjectRequest(&s3.PutObjectInput{ Bucket: aws.String("你的存储桶名称"), Key: aws.String("目标对象键"), }) if err != nil { // 处理错误逻辑 } // 有效期设为24小时(需与临时凭证有效期一致或更短) urlStr, err := req.Presign(24 * time.Hour) if err != nil { // 处理错误逻辑 }
关键注意点
- 目标角色的MaxSessionDuration必须设置为24小时,否则AssumeRole请求会报错。
- Lambda执行角色需拥有
sts:AssumeRole权限,权限范围指向新建的目标角色ARN。 - 预签名URL的有效期不能超过临时凭证的有效期,否则会被自动截断到凭证过期时间。
内容的提问来源于stack exchange,提问作者rsundhar
相关产品推荐
相关产品推荐

