HTTP-запрос клиента API-шлюза с аутентификацией IAM с помощью Go - PullRequest
3 голосов
/ 16 мая 2019

Hello StackOverflow AWS Gophers,

Я реализую CLI с превосходными пакетами кобра / гадюки от spf13 .У нас есть база данных Athena с конечной точкой шлюза API, которая аутентифицируется с помощью IAM.

То есть, чтобы взаимодействовать с его конечными точками с помощью Почтальона, я должен определить AWS Signature как метод авторизации, определить соответствующий идентификатор / секретный код AWS, а затем в заголовках будет X-Amz-Security-Token идругие.Ничего необычного, работает как положено.

Так как я новичок в Go, я был немного шокирован, увидев, что нет примеров для выполнения этого простого запроса HTTP GET с самим aws-sdk-go ... Iпытаюсь использовать поставщика общих учетных данных (~/.aws/credentials), как показано для клиента S3 Фрагменты кода Go из re: Invent 2015 :

req := request.New(nil)

Как можноЯ совершаю этот, казалось бы, легкий подвиг в 2019 году, не прибегая к самостоятельному приготовлению net/http и, следовательно, к необходимости вручную читать ~/.aws/credentials или хуже, идти с os.Getenv и другими уродливыми хаки?

Любые примеры кода Go, взаимодействующие как клиент , были бы очень полезны.Нет примеров Golang Lambda / server, пожалуйста, их много.

Ответы [ 3 ]

2 голосов
/ 17 мая 2019

В приведенном ниже решении используется aws-sdk-go-v2 https://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
        }
1 голос
/ 16 мая 2019

Первый аргумент request.New - aws.Config, куда вы можете отправлять учетные данные.

https://github.com/aws/aws-sdk-go/blob/master/aws/request/request.go#L99 https://docs.aws.amazon.com/sdk-for-go/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}, ...)
0 голосов
/ 23 мая 2019

Я довольно новичок, чтобы пойти сам (3-й день обучения), но после просмотра видео, которое вы разместили на примере 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 / apigateway / 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, поэтому, возможно, попробуйте использовать его и посмотреть, какты идешь?

...