aws-sdk-go-v2 PutObject API错误,拒绝访问

inn6fuwd  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(273)

在我们的暂存环境中,我们可以无凭据地访问我们的私有S3 bucket。访问权限授予单个Docker容器。我尝试使用aws-sdk-go-v2 SDK库使用PutObject上传文件,但我不断收到403 AccessDenied api错误。
我的上传代码如下所示:

var uploadFileFunc = func(s3Details S3Details, key string, payload []byte, params MetadataParams) (*s3.PutObjectOutput, error) {
    client := getS3Client(s3Details)

    return client.PutObject(context.TODO(), &s3.PutObjectInput{
        Bucket:      aws.String(s3Details.Bucket),
        Key:         aws.String(key),
        Body:        bytes.NewReader(payload),
        ContentType: aws.String("text/xml"),
    })
}

func getS3Client(s3Details S3Details) *s3.Client {
    endpointResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
        if s3Details.EndpointUrl != "" {
            return aws.Endpoint{
                PartitionID:   "aws",
                URL:           s3Details.EndpointUrl,
                SigningRegion: s3Details.Region,
                SigningMethod: s3Details.SignatureVersion,
            }, nil
        }
        return aws.Endpoint{}, &aws.EndpointNotFoundError{}
    })

    cfg, _ := config.LoadDefaultConfig(context.TODO(),
        config.WithEndpointDiscovery(aws.EndpointDiscoveryEnabled),
        config.WithEndpointResolverWithOptions(endpointResolver))

    return s3.NewFromConfig(cfg, func(o *s3.Options) {
        o.Region = s3Details.Region
        o.Credentials = aws.AnonymousCredentials{}
        o.UsePathStyle = true
    })
}

我正在使用aws.AnonymousCredentials{}(因为我们的访问是无凭据的),但这只用于未签名的请求。我不能使用AccessKeyID和/或SecretAccessKey为空值的NewStaticCredentialsProvider,因为这将在Retrieve()期间抛出StaticCredentialsEmptyError。添加伪凭据将抛出一个错误,即它们不在记录中。我假设这是我的403 AccessDenied的原因。
如何在Go SDK中不提供证书的情况下对请求进行签名?这可能吗?在boto 3 Python库中,这可以很好地工作。

bvuwiixz

bvuwiixz1#

首先,我强烈建议大家使用Go语言的AWS SDK的v2,我在这里介绍一下我目前是如何做到的。
首先,我获取AWS配置以与此代码一起使用(仅显示相关部分):

cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        Log.Fatal(err)
    }

这里使用的包是github.com/aws/aws-sdk-go-v2/config。然后,我示例化一个s3 Client,用于联系AWS S3服务:

s3Client := s3.NewFromConfig(*cfg)

在这里,我们使用这个包github.com/aws/aws-sdk-go-v2/service/s3。最后,要发布你的对象,你必须运行下面的代码:

input := &s3.PutObjectInput{
    Key:    aws.String("test"),
    Bucket: aws.String("test"),
    Body:   bytes.NewReader([]byte("test")),
    ACL:    types.ObjectCannedACLPrivate,
}

if _, err := s3Client.PutObject(context.TODO(), input); err != nil {
    return "", fmt.Errorf("fn UploadFile %w", err)
}

这里使用的新包是github.com/aws/aws-sdk-go-v2/service/s3/types
这段代码是一个简化,但你应该能够实现你所需要的。此外,它应该花很少的时间来更新SDK的版本,如果你必须使用一个巨大的代码库,你可以同时依赖这两个。
如果有帮助,请告诉我!

编辑

我使用aws.AnonymousCredentials{}选项更新了我的解决方案。现在我可以使用这些选项成功地将一个文件上传到一个s3 bucket中。下面是完整的解决方案:

package main

import (
    "bytes"
    "context"
    "crypto/tls"
    "net/http"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/aws/aws-sdk-go-v2/service/s3/types"
)

func GetAwsConfig() (*aws.Config, error) {
    cfg, err := config.LoadDefaultConfig(context.TODO(),
        // config.WithClientLogMode(aws.LogRequestWithBody|aws.LogResponseWithBody),
        config.WithRegion("eu-west-1"),
        config.WithHTTPClient(&http.Client{Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        }}),
        config.WithEndpointResolverWithOptions(
            aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
                return aws.Endpoint{
                    PartitionID:       "aws",
                    URL:               "http://127.0.0.1:4566",
                    SigningRegion:     "eu-west-1",
                    HostnameImmutable: true,
                }, nil
            }),
        ))
    if err != nil {
        return nil, err
    }
    return &cfg, err
}

func main() {
    cfg, _ := GetAwsConfig()
    s3Client := s3.NewFromConfig(*cfg, func(o *s3.Options) {
        o.Credentials = aws.AnonymousCredentials{}
    })

    if _, err := s3Client.PutObject(context.Background(), &s3.PutObjectInput{
        Bucket: aws.String("mybucket"),
        Key:    aws.String("myfile"),
        Body:   bytes.NewReader([]byte("hello")),
        ACL:    types.ObjectCannedACLPrivate,
    }); err != nil {
        panic(err)
    }
}

在运行代码之前,您必须创建bucket。我使用了以下命令:
aws --endpoint-url=http://localhost:4566 s3 mb s3://mybucket
因此,您可以将文件上传到mybucket s3 bucket中。要检查文件是否存在,您可以发出以下命令:
aws --endpoint-url=http://localhost:4566 s3 ls s3://mybucket --recursive --human-readable
希望这有助于解决您的问题!

相关问题