REST API GetBucketCors with AWS4 - amazon-web-services

I am trying to perform GetBucketCors operation using REST API and new AWS4 authorization. It works perfectly when I use old auth method but I cannot find out how to set canonical request right in AWS4.
I am trying to add 'cors' as first query parameter and include it into canonical request but in most of times I get error: "The request signature we calculated does not match the signature you provided. Check your key and signing method."
Can you suggest what should right query string should be? This is noh my canonical request looks like:
GET
/
cors&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJSZ2LLOUSEHIJVQQ%2F20210316%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210316T192947Z&X-Amz-Expires=10&X-Amz-SignedHeaders=host
host:<BUCKET_NAME>.s3.amazonaws.com
host
UNSIGNED-PAYLOAD

OK, I have finally found it out (hint: look at amazon response more ;)
"cors" should be additional query param with "="
GET
/<BUCKET_NAME>/
X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJSZ2LLOUSEHIJVQQ%2F20210317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210317T210203Z&X-Amz-Expires=10&X-Amz-SignedHeaders=host&cors=
host:s3.amazonaws.com
host
UNSIGNED-PAYLOAD

Related

AWS API Gateway expects the request URL to be encoded twice

My API is a request that can potentially have spaces in the pathParameters.
/data/{id}/hello/{Some message with a space}.
A sample request would be /data/23/hello/Say%20Hi
My angular code from the frontend encodes the request URL that is sent out to the AWS API Gateway but I get the following error.
`The Canonical String for this request should have been
'GET
/data/23/hello/Sayr%2520Hi`
My API gateway has a velocity template the decodes the parameters using $util.urlDecode()
I'm facing the same problem.
I've been stuck for a day.
If you are using HttpApi it cannot be solved.
Nevertheless, if you use RestApi I managed to make this work.
Specifically, you should use the URL Path Parameters.
You should:
Add a resource containing the /{variable}
Add a Url Path Parameter in the Integration Request Configuration with name variable and mapped from method.request.path.variable
Notice that the solution may depend on the integration type that you are using.
In the screenshot below you can see how I'm redirecting all the received traffic to a NetworkLoadBalancer.
The resource has the variable /{proxy+}, the endpoint URL has the {proxy}, and, in the URL Path Parameters, I've configured the mapping method.request.path.proxy.

Postman Mock Server matching algorithm logic for request body param

I have two scenarios for the following API URL.
POST http://{{ip_port}}/oauth/token
When I put the user name and password correctly, it should return
200 and mock json response.
When I put user name and password incorrectly, it should return 401 and mocked json(error).
In Postman Mock server, I noticed that there is no matching algorithm logic for request param.
I want to filter by request param and return related mock responses. I don't want to add two URLs(/token and /failedtoken) for above scenarios.
Currently Postman only support three logic for matching algorithm logic.
Properly formatted responses
HTTP method
Filter by URL
Is there any way to add only one URL for many scenarios in Postman Mock Server?
Postman Mock Server now supports matching by request body. You can use it by specifying a custom header (x-mock-match-request-body to true).
You can also check out an example that demonstrates how this feature works by going to New->Templates and searching for Request Body Matching.

Exclude headers from s3v4 signature calculation

We are using an onPrem S3 compatible storage server in an intranet network and we want to expose this intranet url to internet so we used a ReverseProxy with a mapping to the intranet url. When we test the intranet url it works perfectly but when we test the internet url we get the 403 error:
The request signature we calculated does not match the signature you provided. Check your Secret Access Key and signing method. For more information, see REST Authentication and SOAP Authentication for details. (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: 0a440c7f:15cc604b1e2:12d3af:24d; S3 Extended Request ID: null), S3 Extended Request ID: null
After debugging, we found that the proxy modifies the host header used to calculate the signature in order to redirect the request to the intranet url...
So my question is how to supress some headers from the V4 signature calculation using AWS SDK or Boto3 client. or is there a better architecture to expose an onPrem S3 service.
Thanks in advance.
Amir.
There are essentially two solutions to this.
The first one is easier: sign the request for the internal URL, then just use simple string prefix replacement to rewrite the host part of the signed URL to point it to the hostname of the external proxy. When the proxy rewrites the Host header, it will end up rewriting it back to exactly what you signed.
It is, I assume, common knowledge that signed URLs are immune to tampering, for all practical purposes: you can't change anything about a signed URL without invalidating it... but that's not what this is. The change is temporary, and the proxy's net effect is to undo the change.
The alternate solution requires the proxy or another service in the chain (before the storage service) to know the signing keys and secrets, so that it can first validate the incoming request, and if valid, modify the request and then generate a new signature that the service will accept. I once wrote a service to do this so that when a request was for HEAD, the proxy would use the same key and secret (which it knew) to generate a signature for the same request, but with GET. If it matched the signature in the incoming request, the proxy would replace the existing signature with a signature for a HEAD request -- thus allowing the client to use a URL originally signed for a GET request, to make either a GET or a HEAD request -- something S3 does not natively support, since a GET and a HEAD for the same object require two different signed URLs. The concept is the same, though -- generate a signature in the proxy for what the client is requesting, to validate the incoming signature, and then re-sign the request as needed. The solution I built used HAProxy's Lua integration to examine and modify the request in flight.

ApiGateway Autogenerated SDK "The request signature we calculated does not match the signature you provided" Error

I've attempted all solutions (that appear to make sense) from:
AWS The request signature we calculated does not match the signature you provided. Check your key and signing method
And I looked through a handful of other posts that don't apply.
I'm using the Serverless framework to generate my backend. It uses API Gateway with AWS lambda and DynamoDB. In have 4 other API call's that work perfectly, it's only this one call that gives me problems.
Calling code:
//code that calls it
apiClientFactory = new ApiClientFactory();
apiClientFactory.credentialsProvider(credentialsProvider);
accountApiClient = apiClientFactory.build(DevsupercoolsoftwareClient.class);
...
public static InviteCodeResponseModel createInviteCode(InviteCodeRequestModel request) {
//request has one value, which is set to "USER"
InviteCodeResponseModel response = accountApiClient.accountInviteCodeGet(request);
return response;
}
Error:
Caused by: com.amazonaws.mobileconnectors.apigateway.ApiClientException: {"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\n...\n"}
(Service: DevsupercoolsoftwareClient; Status Code: 403; Error Code: null; Request ID: bd8d4c91-7758-11e6-a0a0-69136ab6b7af)
at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.handleResponse(ApiClientHandler.java:255)
at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.invoke(ApiClientHandler.java:88)
at java.lang.reflect.Proxy.invoke(Proxy.java:393)
at $Proxy1.accountInviteCodeGet(Unknown Source)
at com.camhart.supercoolsoftware.communicator.BackendCommunicator.createInviteCode(BackendCommunicator.java:62)
at com.camhart.supercoolsoftware.activities.Devices.triggerShareMenu(Devices.java:159)
at com.camhart.supercoolsoftware.activities.Devices.access$100(Devices.java:27)
at com.camhart.supercoolsoftware.activities.Devices$2.doInBackground(Devices.java:134)
at com.camhart.supercoolsoftware.activities.Devices$2.doInBackground(Devices.java:128)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more
The call to accountInviteCodeGet attempts to do an HTTP GET call with a method body. It appears this isn't allowed. Once I changed it to a POST everything worked great.
I'll try to find some documentation describing this behavior. If I can I'll either edit this or put it in the comments.
Edit:
I talked to AWS support. Here's what they pointed me to stating that it's not possible to include message body with HTTP get requests.
"Generally speaking, as per the HTTP/1.1 specification:
RFC 2616, section 4.3 clearly states:
A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) does not allow sending an entity-body in requests.
[+] https://www.rfc-editor.org/rfc/rfc2616#section-4.3
"

How to pass through a query string parameter with square brackets in Amazon API Gateway

I want to use API Gateway as a caching proxy for an HTTP server, which in turn uses jsonapi-resources to define the API.
The issue is that jsonapi-resources requires query string parameters of the form ?page[number]=10&page[size]=10 to paginate results. However, if I try to add page[number] to URL Query String Parameters on a Method Request page, I receive the following error:
I've also tried to percent-encode the name as page%5Bnumber%5D without any success; the parameter is still filtered out.
Is there a way to make it work?
If you encode the [ by %5B, API Gateway doesn't allow % in the parameter name.
Currently, AWS API Gateway only supports the parameter name matches ^[a-zA-Z0-9._$-]+$
Does page.number work for you?