简体   繁体   English

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

[英]aws-sdk-go-v2 PutObject api error AccessDenied

In our Staging environment, we have credential-less access to our private S3 buckets.在我们的暂存环境中,我们可以无凭据访问我们的私有 S3 存储桶。 Access is granted to individual Docker containers.访问权限授予单个 Docker 容器。 I am trying to upload a file using PutObject using the aws-sdk-go-v2 SDK library, but I'm continually getting a 403 AccessDenied api error.我正在尝试使用 aws-sdk-go-v2 SDK 库使用PutObject上传文件,但我不断收到 403 AccessDenied api 错误。

My upload code looks like this:我的上传代码如下所示:

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
    })
}

I am using aws.AnonymousCredentials{} (as our access is credential-less) but this is only to be used for unsigned requests.我正在使用aws.AnonymousCredentials{} (因为我们的访问是无凭据的)但这仅用于未签名的请求。 I cannot use NewStaticCredentialsProvider with empty values for AccessKeyID and/or SecretAccessKey as this will throw a StaticCredentialsEmptyError during the Retrieve() .我不能将NewStaticCredentialsProviderAccessKeyID和/或SecretAccessKey的空值一起使用,因为这会在Retrieve()期间抛出StaticCredentialsEmptyError Adding dummy credentials will throw an error that they are not on record.添加虚拟凭据将引发错误,表明它们未记录在案。 I am assuming that this is the cause of my 403 AccessDenied .我假设这是我的403 AccessDenied的原因。

How do I sign requests without providing credentials in the Go SDK?如何在 Go SDK 中不提供凭证的情况下签署请求? Is it even possible?有可能吗? In the boto3 Python library this works fine.在 boto3 Python 库中,这工作正常。

First of all, I'll strongly suggest you use the v2 of the AWS SDK of Go. I'll present here how I do this so far.首先,我强烈建议您使用 Go 的 AWS SDK 的 v2。我将在这里介绍到目前为止我是如何做到这一点的。
First, I get the AWS config to use with this code (only relevant parts are shown):首先,我获取与此代码一起使用的 AWS 配置(仅显示相关部分):

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

Here the package used is github.com/aws/aws-sdk-go-v2/config .这里使用的 package 是github.com/aws/aws-sdk-go-v2/config Then, I instantiate an s3Client to use for contacting AWS S3 service:然后,我实例化一个 s3Client 以用于联系 AWS S3 服务:

s3Client := s3.NewFromConfig(*cfg)

Here, we use this package github.com/aws/aws-sdk-go-v2/service/s3 .在这里,我们使用这个 package github.com/aws/aws-sdk-go-v2/service/s3 Finally, to post your object you have to run this code:最后,要发布您的 object,您必须运行以下代码:

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)
}

The new package used here is github.com/aws/aws-sdk-go-v2/service/s3/types .此处使用的新 package 是github.com/aws/aws-sdk-go-v2/service/s3/types
This code is a simplification but you should able to achieve what you need.此代码是一种简化,但您应该能够实现您所需要的。 Furthermore, it should take very little time to update the version of the SDK and you can rely on both of them simultaneously if you've to work with a huge codebase.此外,更新 SDK 的版本应该只需要很少的时间,如果您必须使用庞大的代码库,则可以同时依赖它们。
Let me know if this helps!让我知道这是否有帮助!

Edit编辑

I updated my solution by using the aws.AnonymousCredentials{} option.我使用aws.AnonymousCredentials{}选项更新了我的解决方案。 Now I was successfully able to upload a file into an s3 bucket with these options.现在我可以使用这些选项成功地将文件上传到 s3 存储桶中。 Below you can find the entire solution:您可以在下面找到完整的解决方案:

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)
    }
}

Before running the code, you've to create the bucket.在运行代码之前,您必须创建存储桶。 I used the below command:我使用了以下命令:
aws --endpoint-url=http://localhost:4566 s3 mb s3://mybucket
Thanks to this you can upload the file into the mybucket s3 bucket.由于这个,您可以将文件上传到mybucket s3 存储桶中。 To check for the file existence you can issue this command:要检查文件是否存在,您可以发出以下命令:
aws --endpoint-url=http://localhost:4566 s3 ls s3://mybucket --recursive --human-readable
Hope this helps in solving your issue!希望这有助于解决您的问题!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 S3 为使用 aws-sdk v3 预签名的 PutObject 命令 url 提供 SignatureDoesNotMatch 错误 - S3 gives SignatureDoesNotMatch error for PutObject command pre-signed url using aws-sdk v3 如何对使用 AWS SDK 为 Go V2 实施的 Lambda 进行单元测试 - How to Unit Test a Lambda Implemented with AWS SDK for Go V2 调用 PutObject 操作时发生错误 (AccessDenied):Access Denied 但在我的系统上有效 - An error occurred (AccessDenied) when calling the PutObject operation: Access Denied but works on my system 在 AWS 上执行“PutObject”时出错,上传失败 - Error executing "PutObject" on AWS, upload fails 外部机密 AccessDenied 错误中的 aws eks - aws eks in external-secret AccessDenied error AWS SDK JavaScript:如何显示AWS.S3.putObject的上传进度? - AWS SDK JavaScript: how display upload progress of AWS.S3.putObject? AWS Golang SDK v2 - 如何将 function 添加到 Go AWS 脚本 - AWS Golang SDK v2 - How to add function to Go AWS script 使用 aws sdk v3 调试 ENOTFOUND 错误 - Debugging ENOTFOUND error using aws sdk v3 AWS XRay 与 AWS SDK v3 for NodeJS - AWS XRay with AWS SDK v3 for NodeJS AWS Java SDK V2中的package software.amazon.awssdk.core.auth.policy go在哪里? - Where did the package software.amazon.awssdk.core.auth.policy go in the AWS Java SDK V2?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM