API网关HTTP客户端请求,带有IAM auth的GO



你好stackoverflow aws gophers,

我正在实施SPF13的出色眼镜蛇/毒素包装的CLI。我们有一个ATHENA数据库,由API网关端点,该数据库用IAM进行了身份验证。

也就是说,为了通过使用Postman与其端点进行交互,我必须将AWS Signature定义为授权方法,定义相应的AWS ID/SECRET,然后在标题中,将有X-Amz-Security-Token等。没有什么不寻常的,可以按预期工作。

由于我是新手,所以我有点震惊地看到没有示例可以使用aws-sdk-go本身进行此简单的HTTP获取请求...我正在尝试使用共享的凭据提供商(~/.aws/credentials(,如RE:Invent 2015:

的S3客户端GO代码片段所示
req := request.New(nil)

我如何在2019年完成这一看似简单的壮举,而不必诉诸于自煮的net/http,因此必须手动读取~/.aws/credentials或更糟糕的是,使用os.Getenv和其他丑陋的hacks?

client 进行交互的任何GO代码样本都将非常有帮助。没有Golang Lambda/服务器示例,请,那里有很多。

不幸的是,似乎已经更新了该库,因为已写下了答案,并且解决方案不再是相同的。经过一定的反复试验,这似乎是处理签名的最新方法(使用https://pkg.go.dev/github.com/aws/aws/aws-sdk-go-v2(:

import (
    "context"
    "net/http"
    "time"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
)
func main() {
    // Context is not being used in this example.
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        // Handle error.
    }
    credentials, err := cfg.Credentials.Retrieve(context.TODO())
    if err != nil {
        // Handle error.
    }
    // The signer requires a payload hash. This hash is for an empty payload.
    hash := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    req, _ := http.NewRequest(http.MethodGet, "api-gw-url", nil)
    signer := v4.NewSigner()
    err = signer.SignHTTP(context.TODO(), credentials, req, hash, "execute-api", cfg.Region, time.Now())
    if err != nil {
        // Handle error.
    }
    // Use `req`
}

下面的解决方案使用AWS-SDK-GO-V2https://github.com/aws/aws-sdk-go-v2

// A AWS SDK session is created because the HTTP API is secured using a
// IAM authorizer. As such, we need AWS client credentials and a
// session to properly sign the request.
cfg, err := external.LoadDefaultAWSConfig(
    external.WithSharedConfigProfile(profile),
)
if err != nil {
    fmt.Println("unable to create an AWS session for the provided profile")
    return
}

req, _ := http.NewRequest(http.MethodGet, "", nil)
req = req.WithContext(ctx)
signer := v4.NewSigner(cfg.Credentials)
_, err = signer.Sign(req, nil, "execute-api", cfg.Region, time.Now())
if err != nil {
    fmt.Printf("failed to sign request: (%v)n", err)
    return
}
res, err := http.DefaultClient.Do(req)
if err != nil {
    fmt.Printf("failed to call remote service: (%v)n", err)
    return
}
defer res.Body.Close()
if res.StatusCode != 200 {
    fmt.Printf("service returned a status not 200: (%d)n", res.StatusCode)
    return
}

request.New的第一个参数是aws.Config,您可以在其中发送凭据。

https://github.com/aws/aws-sdk-go/blob/master/aws/request/request.go#l99https://docs.aws.amazon.com/sdk-for-go/api/api/aws/#config

有多种创建凭证对象的方法:https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html

例如使用静态值:

creds:= credentials.NewStaticCredentials("AKID", "SECRET_KEY", "TOKEN")
req := request.New(aws.Config{Credentials: creds}, ...)

我很新鲜(第三天学习(,但是从观看您在S3示例中发布的视频并读取源代码(对于S3服务和请求模块(这是我的理解(我希望这会有所帮助(。

如果您查看s3.new((函数的代码AWS-SDK-go/service/s3/service.go

func New(p client.ConfigProvider, cfgs ...*aws.Config) *S3 {
c := p.ClientConfig(EndpointsID, cfgs...)
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, .SigningName) }

而不是request.new((函数aws-sdk-go/aws/request/request.go

func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request { ...

您可以在S3方案中看到 *AWS.Config struct是一个指针,因此在其他地方可能是初始化/填充的。与aws.config为参数的请求函数相反。因此,我猜想该请求模块可能是一个非常低的级别模块,该模块不会自动获得共享凭据。

现在,看到您将与API网关进行互动时,我专门查看了该服务,以查看是否有类似的东西。我查看了AWS-SDK-GO/SERVICE/APIGITAWAY/SERVICE.GO

func New(p client.ConfigProvider, cfgs ...*aws.Config) *APIGateway {
c := p.ClientConfig(EndpointsID, cfgs...)
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) }...

看起来与S3客户端几乎相同,所以也许尝试使用它并查看如何走?

相关内容

  • 没有找到相关文章

最新更新