You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang Lambda读取S3文件遇凭证问题,如何用IAM角色创建Session?

AWS Lambda + Go 读取S3文件的凭证问题解决

我编写了一段Golang代码,用于在AWS Lambda中接收文件名后读取S3文件并提取指定列,但在获取S3文件的步骤出现问题。

我的代码如下:

package main

import (
    "fmt"
    "packageXXX/cmd/utils"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
    "github.com/aws/aws-sdk-go/service/s3/s3manager"
    "go.uber.org/zap"
)

var (
    log *zap.Logger
)

func init() {
    log = utils.InitLogger()
}

func DownloadFile(downloader *s3manager.Downloader, bucketName string, key string) error {

    buff := &aws.WriteAtBuffer{}

    numBytes, err := downloader.Download(
        buff,
        &s3.GetObjectInput{
            Bucket: aws.String(bucketName),
            Key:    aws.String(key),
        },
    )

    data := buff.Bytes() // now data is my []byte array

    log.Info("nnnnnnnnnnnnnnn", zap.Any("nnn", numBytes))
    log.Info("xxxxxxxxxxxxxxx", zap.Any("bytes", data))
    return err
}

func handler(fileName string) (string, error) {
    log.Info(fmt.Sprintf("received: %s", fileName))
    sess, err := session.NewSessionWithOptions(session.Options{
        Profile: "default",
        Config: aws.Config{
            Region: aws.String("us-west-2"),
        },
    })

    if err != nil {
        log.Info("errorrrrrrrrr", zap.Any("session", err))
        return "errorr,", nil
    } else {
        log.Info("sessionnnnnnnnnnnnnn", zap.Any("sess", sess))
    }

    bucketName := "s3-test-lambda-go-xxx"
    downloader := s3manager.NewDownloader(sess)
    log.Info("downloader", zap.Any("downloader", err))
    key := fileName
    err = DownloadFile(downloader, bucketName, key)

    if err != nil {
        fmt.Printf("Couldn't download file: %v", err)
        return "errror", nil
    }

    fmt.Println("Successfully downloaded file")

    return fmt.Sprintf("el file recibido es: %s", fileName), nil
}

func main() {
    lambda.Start(handler)
}

日志输出如下:

For verbose messaging see aws.Config.CredentialsChainVerboseErrorsSTART RequestId: dba8ebd5-9102-4a2f-8e45-cdef355f1bbd Version: $LATEST
{"level":"info","ts":"2022-11-02T17:31:32Z","msg":"received: gggggg2.txt"}
{"level":"info","ts":"2022-11-02T17:31:32Z","msg":"sessionnnnnnnnnnnnnn","sessError":"json: unsupported type: endpoints.endpointDefaults"}
{"level":"info","ts":"2022-11-02T17:31:32Z","msg":"downloader","downloader":null}
{"level":"info","ts":"2022-11-02T17:31:38Z","msg":"nnnnnnnnnnnnnnn","nnn":0}
{"level":"info","ts":"2022-11-02T17:31:38Z","msg":"xxxxxxxxxxxxxxx","bytes":""}
Couldn't download file: NoCredentialProviders: no valid providers in chain. Deprecated.
END RequestId: dba8ebd5-9102-4a2f-8e45-cdef355f1bbd

问题出在Session创建环节,日志显示错误为“NoCredentialProviders: no valid providers in chain”。由于是生产环境,我不想使用Access Key和Secret Key,请问是否可以通过IAM角色创建Session?


解决方案

完全可以通过IAM角色解决这个问题,这也是AWS生产环境的最佳实践,具体操作如下:

1. 移除代码中的本地Profile配置

Lambda运行环境中不存在本地的default Profile配置,这会导致SDK尝试读取不存在的凭证文件,直接删除Profile: "default"这一行。

2. 为Lambda函数关联IAM角色

创建一个IAM角色,为其添加允许读取目标S3桶的权限策略,示例策略如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::s3-test-lambda-go-xxx/*"
        }
    ]
}

将该角色关联到你的Lambda函数上,Lambda运行时会自动获取该角色的临时凭证,无需手动配置。

3. 简化Session创建代码

修改后的Session创建代码无需指定Profile,SDK会自动从Lambda运行环境中获取凭证和区域信息(也可以保留区域配置确保一致性):

func handler(fileName string) (string, error) {
    log.Info(fmt.Sprintf("received: %s", fileName))
    // 简化Session创建,移除Profile配置
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("us-west-2"),
    })

    if err != nil {
        log.Error("Failed to create session", zap.Error(err))
        return "error creating session", err
    }

    bucketName := "s3-test-lambda-go-xxx"
    downloader := s3manager.NewDownloader(sess)
    key := fileName
    err = DownloadFile(downloader, bucketName, key)

    if err != nil {
        log.Error("Failed to download file", zap.Error(err))
        return "error downloading file", err
    }

    log.Info("Successfully downloaded file")
    return fmt.Sprintf("Received file: %s", fileName), nil
}

原理说明

AWS Lambda运行时会自动为关联的IAM角色生成临时凭证,并通过环境变量和元数据服务暴露给函数进程。AWS Go SDK会自动按照凭证链顺序查找这些凭证,无需手动指定Access Key和Secret Key,完全符合生产环境的安全要求。


内容的提问来源于stack exchange,提问作者user2291499

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:10:58