Open jwineinger opened 1 year ago
Hi @jwineinger , ack. I'll see to provide examples shortly. Thanks for opening it.
@lovaarte I Would like to second the need for golang examples. I currently have a need to use IAM auth with multi region apigateway deployments, but am unable to find any examples on the internet.
I contributed a PR to Open Policy Agent that added v4a signing for S3 multi-region access points. It lifts most of the v4a signing code from the AWS SDK because OPA didn't want to bring the entire SDK in as a dependency.
https://github.com/open-policy-agent/opa/pull/5489/files is the PR, and https://github.com/open-policy-agent/opa/blob/main/internal/providers/aws/signing_v4a.go#L383-L410 might be a good entrypoint to start at for the actual signing mechanics.
Thanks everyone for your feedback, I'll prioritize to get a working code. @jwineinger thanks for the pointer, this is as in your case as there is no go AWS SDK that does it.
https://github.com/aws/aws-sdk-go-v2/issues/1935
The AWS SDK go v2 SDK has internal code to do it, which is where I pulled from.
@jwineinger Thank you, I have been looking at your examples and seeing if i can make sense of it. Using your example I have been able to successfully sign a request, but am getting access denied when attempting to access apigateway. I am able to access this same apigateway when using sigv4. @lovaarte I am wondering if apigateway supports v4a yet?
@brittandeyoung assuming you tested in a language that have sample code. I just tested and it works for me. Make sure you pass correct config. Here is what I used:
service = 'execute-api'
region = '*' # Also works with 'global'
method = 'GET'
url = 'https://{YOUR-DNS}/{ENDPOINT}'
Or are you trying to make it work in go?
@lovaarte I am using the example provided by @jwineinger to create the signed headers. https://github.com/open-policy-agent/opa/blob/c29d375de5a9adf51a0dcd4dda843e811a06c4fc/internal/providers/aws/signing_v4a.go#L383-L410
I am attempting do this in golang.
Here is an example of the headers that are being included with the request. I replaced any sensitive information with ****
map[
Authorization:[
AWS4-ECDSA-P256-SHA256 Credential=*****/execute-api/aws4_request,
SignedHeaders=content-length;host;x-amz-content-sha256;x-amz-date;x-amz-region-set;x-amz-security-token, Signature=******
]
Content-Type:[application/json]
Host:[***.execute-api.us-east-1.amazonaws.com]
X-Amz-Content-Sha256:[***]
X-Amz-Date:[20230615T131316Z]
X-Amz-Region-Set:[*]
X-Amz-Security-Token:[***]
]
Here the snippit I am using to do the signing,
now := time.Now()
req = req.WithContext(ctx)
var creds signer.Credentials
var body []byte
if req.Body == nil {
body = []byte("")
} else {
var err error
body, err = io.ReadAll(req.Body)
if err != nil {
return nil, 0, errors.New("error getting request body: " + err.Error())
}
// Since ReadAll consumed the body ReadCloser, we must create a new ReadCloser for the request so that the
// subsequent read starts from the beginning
req.Body = io.NopCloser(bytes.NewReader(body))
}
creds.AccessKey = c.options.AWSAccessKey
creds.SecretKey = c.options.AWSSecretKey
if c.options.AWSSessionToken != "" {
creds.SessionToken = c.options.AWSSessionToken
}
creds.RegionName = c.options.Region
req.Header.Add("Content-Type", "application/json")
signedHeaders := signer.SignV4a(req.Header, req.Method, req.URL, body, signersService, creds, now)
req.Header = signedHeaders
res, err := c.HTTPClient.Do(req)
if err != nil {
return nil, 0, err
}
defer res.Body.Close()
body, err = io.ReadAll(res.Body)
if err != nil {
return nil, 0, err
}
return body, res.StatusCode, err
The SignV4a
is taken exactly as is from @jwineinger provided example.
Really appreciate sharing it! Would you be interested to contribute and open a PR in the format as other examples? In my view for this case it's important to add a note/disclaimer that it's either a temporary work around till AWS SDK supports it fully, or that it's an example for use cases where you can't, or don't want, bring the whole AWS SDK.
@lovaarte I have not had a successful authentication with this code against apigateway. I am currently getting access denied.
It likely means it's not related to API Gateway (API-GW) but there is something missing in general, as API GW itself supports it (based on my testing yesterday).
@lovaarte In your testing, did you use a rest api
or http api
. I did some more testing and it looks like the sigv4a IS working when attempting to hit a rest api
apigateway, but failing when attempting to hit a http api
apigateway.
For our current use case we are using a http api
.
Can you confirm that sigv4a IS or IS NOT supported on http api
apigateway?
Thanks @lucix-aws for releasing the support https://pkg.go.dev/github.com/aws/smithy-go/aws-http-auth @lovaarte Can you please add example now using the go lang package
In the absence of an explicit example in this repository, https://github.com/aws/smithy-go/blob/main/aws-http-auth/sigv4a/e2e_test.go demonstrates using both sigv4 and sigv4a to do some S3 operations.
Do you have any golang examples that can be added here? thanks!