3
votes

Demande de client HTTP API Gateway avec authentification IAM avec Go

Bonjour StackOverflow AWS Gophers,

J'implémente une CLI avec l'excellent paquets cobra / viper de spf13 . Nous avons une base de données Athena confrontée à un point de terminaison API Gateway, qui s'authentifie avec IAM.

Autrement dit, pour interagir avec ses points de terminaison à l'aide de Postman, je dois définir Signature AWS comme méthode d'autorisation, définir l'ID / secret AWS correspondant, puis dans les en-têtes il y aura X-Amz-Security-Token et d'autres. Rien d'inhabituel, fonctionne comme prévu.

Depuis que je suis nouveau dans Go, j'ai été un peu choqué de voir qu'il n'y a pas d'exemples pour faire cette simple requête HTTP GET avec le aws-sdk- aller lui-même ... J'essaie d'utiliser le fournisseur d'informations d'identification partagées ( ~ / .aws / credentials ), comme démontré pour le client S3 Extraits de code Go de re: Invent 2015 :

req := request.New(nil)

Comment J'accomplis cet exploit apparemment facile en 2019 sans avoir à recourir à l'auto-cuisson net / http et donc à lire manuellement ~ / .aws / credentials ou pire, allez avec os.Getenv et d'autres hacks horribles?

Tout exemple de code Go interagissant en tant que client serait très utile. Aucun exemple de Golang Lambda / serveur, s'il vous plaît, il y en a beaucoup.


2 commentaires

vous ne pouvez pas obtenir d'informations de cette fonction droite?


Oui, c'est vrai, cette fonction est celle que je devrais écrire, idéalement avec aws-sdk-go .


3 Réponses :


1
votes

Le premier argument de request.New est aws.Config , où vous pouvez envoyer des informations d'identification.

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

Il existe plusieurs façons de créer un objet d'identification: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk .html

Par exemple en utilisant des valeurs statiques:

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


2 commentaires

Correct, définir des informations d'identification statiques dans le code est une mauvaise idée, par conséquent, je suis d'accord avec ce que dit la documentation: "Lorsque vous initialisez un nouveau client de service sans fournir d'arguments d'identification, le SDK utilise la chaîne de fournisseur d'informations d'identification par défaut pour trouver les informations d'identification AWS." ... qui passe nil à la nouvelle méthode, non? Cela ne fonctionne pas, malheureusement.


Je suppose que la nouvelle façon en 2019 est d'opter pour qc comme: req: = request.New (defaults.Get (). Config, metadata.ClientInfo, defaults.Get (). Handlers, client.DefaultRetryer ()) , mais toujours pas d'exemples concrets simples disponibles, malheureusement: /



3
votes

La solution ci-dessous utilise 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
}


3 commentaires

Merci pour ce @craftsource, je vois que cet extrait de code utilise aws-sdk-go-v2 au lieu de v1 ... Je vais chercher celui qui convient mais je reçois ne peut pas utilisez cfg.Credentials (tapez "github.com/aws/aws-sdk-go-v2/aws".CredentialsProvider) comme type * credentials. : /


Vous devez utiliser le signataire aws-sdk-go-v2 v4.


Merci beaucoup! Je n'importais pas le bon sdk, import v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" et c'est parti :)



0
votes

Je suis assez nouveau pour y aller moi-même (apprentissage du 3e jour), mais en regardant la vidéo que vous avez publiée avec l'exemple S3 et en lisant le code source (pour le service s3 et le module de demande), voici ma compréhension (que je j'espère aider).

Si vous regardez le code de la fonction s3.New () aws-sdk-go / service / s3 / 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) }...

Par opposition à request. Nouvelle () fonction 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 { ...

Comme vous pouvez le voir dans le scénario s3, la structure * aws.Config est un pointeur, et donc est probablement initialisé / rempli ailleurs. Contrairement à la fonction de requête où aws.Config est un paramètre. Je suppose donc que le module de requête est probablement un module de très bas niveau qui n'obtient pas automatiquement les informations d'identification partagées.

Maintenant, étant donné que vous allez interagir avec la passerelle API, j'ai jeté un coup d'œil à ce service spécifiquement pour voir s'il y avait quelque chose de similaire. J'ai regardé aws-sdk-go / service /apigateway/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) }

Ce qui ressemble à peu près au client s3, alors essayez peut-être de l'utiliser et voyez comment vous allez? p >


1 commentaires

Bonjour Grizzle, merci pour la procédure pas à pas, mais la réponse de la source artisanale a été acceptée il y a quelques jours, ce qui signifie que j'ai réussi à le faire fonctionner avec aws-sdk-go-v2 SDK (la nouvelle version d'AWS Go SDK ). Vous pouvez jeter un œil à mon code de travail actuel ici: github. com / umccr / cli / blob / master / cmd / find.go # L46