It seems pretty straight forward, but I am not able to figure out yet.
In the code such as below -
resp, err := http.Get("API Gateway endpoint url goes here")
if err != nil {
log.Fatalln(err)
}
I am not sure how I tell http.get to use AWS auth. aws cli is configured the access key and secret on the host. So I do not want to again mention in the code.
Some posts mentioned about signing request. But I am not sure if that's the right way. In light of the AWS SDK in golang, this feels bit low level stuff. I would expect either
Any help is much, much appreciated!
Thanks Sandeep
Some posts mentioned signing requests. But I am not sure if that's the right way
Yes, IAM Auth requires request signing (see docs here and here). The current method is Signature v4. Api Gateway accepts a request if it has the expected headers. "Signing" is the process of adding the right headers:
# signature is derived from your secret key and the request contents.
--header 'Authorization: AWS4-HMAC-SHA256 Credential=AKIASIAXTWO8D5GSN4CS/20220712/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date, Signature=f2d8478ceff83d5cd0696502cb58a8331304846d11367d74608295c7acbfba0c'
# date prevents third parties from intercepting your request and resubmitting it later
--header 'X-Amz-Date: 20220712T124302Z'
There must a way in AWS SDK that encapsulates signing HTTP request etc. and does the job
For several languages (JS, Java, etc. but not Go), the get-sdk command can generate a SDK client for your Rest API that, among other conveniences, wraps the signature process: client.privateGet(params, body, additionalParams)
.
There must be a way to do this using http inbuild package by "somehow" attaching aws creds
Using the plain-old SDKs it's a bit more work to add the headers, easily wrappable in a resusable type:
ctx := context.TODO()
// define the request
endpoint := "https://cbi3vltq21.execute-api.us-east-1.amazonaws.com"
u, _ := url.ParseRequestURI(endpoint)
u.Path = "prod/private"
req, _ := http.NewRequest("GET", u.String(), nil)
// get the credentials from the local config files
cfg, _ := config.LoadDefaultConfig(ctx,
config.WithRegion("us-east-1"),
config.WithSharedConfigProfile("my-profile"))
creds, _ := cfg.Credentials.Retrieve(ctx)
// hash the request body - hex value used in the signature
hash := sha256.Sum256([]byte("")) // if the request has no body, use the empty string
hexHash := fmt.Sprintf("%x", hash)
// add the Authorization and X-Amz-Date headers to the request
signer := v4.NewSigner()
_ = signer.SignHTTP(ctx, creds, req, hexHash, "execute-api", cfg.Region, time.Now())
// execute the request
client := &http.Client{}
resp, _ := client.Do(req)
H/T to this SO answer.