5
votes

I'm attempting to use Postman, the chrome extension api client Postman to access Dynamodb via http. This is actually an approach I read about in the Book Dynamodb Applied Design Patterns. It appears that I am doing something wrong because I am unable to sucessfully authenticate and gain access to the web service.

The url and headers I'm using in the Postman client with my most recent request parameters and error messages follow:

url: dynamodb.us-east-1.amazonaws.com
x-amz-date: 20150701T162011Z
x-amz-targe: DynamoDB_20120810.ListTables
authorizaton: AWS4-HMAC-SHA256 Credential=AMyAccessCode/20150701/us-east-1/dynamodb/aws4_request, SignedHeaders=host;x-amz-date;x-amz-target, Signature=8ngTnF8WH//njvBdY5bY5dSp5CAKi8qTXNFuv5Ws+30=
content-type: application/x-amz-json-1.0

The Body of my request is:

{
"ExclusiveStartTableName": "Owner",
"Limit": 3
}

I'm getting the following error message:

{"__type":"com.amazon.coral.service#InvalidSignatureException","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\nhost:dynamodb.us-east-1.amazonaws.com\nx-amz-date:20150701T162011Z\nx-amz-target:DynamoDB_20120810.ListTables\n\nhost;x-amz-date;x-amz-target\nb9e264461dcb0e94e69652f8b2d17c737a29506863d6f09c0f9fc98e9d560e5c'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20150701T162011Z\n20150701/us-east-1/dynamodb/aws4_request\n7a6da3d9e8ed6317e0cb9217e9ea1174d01e86871a159f339f5f6969283264d5'\n"}

Question/Oddity 1. When I issue a request I usually get response back indicating that my request has expired. The error message will include "valid" times that are four hours ahead of the actual time tha I used. When I use the time provided by the error message in the request, I no longer receive the exprired request error message.

Question 2. This message seems to indicate I have to calculate the hash of the canonical request. The documentation on amazon is a bit unclear on this. Do I need to calcuate the has of the canonical request and if so do I include that as a header" If so, what is the header name?

I have been able to calculate the signature and replicate the signature in the Amazon documentation.

Thanks for your input.

3

3 Answers

8
votes

I was able to invoke using Postman 3.

CURL Exmaple:

  curl -X POST \
  https://dynamodb.eu-west-1.amazonaws.com/ \
  -H 'authorization: AWS4-HMAC-SHA256 Credential=ABCDDEFSDFDDFDAG/20170725/eu-west-1/dynamodb/aws4_request,     SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-target,     Signature=7402a0163c267385b7270f5c6ce49748518cac4f4d7e03addbd9ddedf9c9970' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'host: dynamodb.eu-west-1.amazonaws.com' \
  -H 'postman-token: 0152b36c-2947-2a6f-91b9-87884b38fb50' \
  -H 'x-amz-date: 20170725T181135Z' \
  -H 'x-amz-target: DynamoDB_20120810.GetItem' \
  -d '{
    "TableName": "TableName",
    "Key": {
        "id": {"S": "KeyId"}
    }
}'
  1. Insert Body

Insert Body

  1. Enter Credentials and Click on Update Request.You might need to click on Update Request more often to update x-amz-date

Enter Credentials and Click on Update Request

  1. Update Content-Type Header to application/json

Update Content-Type Header to application/json

3
votes

You're on the right path. As you imply, you're running into issues with the API authentication scheme that Amazon uses. See http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html.

The way this works is that Amazon wants you to take a few pieces of information including the service you're calling and current timestamp and compute a hash that uses this data along with your AWS Secret Access Key (actually, they derive a key from your Secret Access Key, but don't worry about that for now).

One of the key design principles going on here is that Amazon wants to prevent Replay Attacks, where someone just sends a request you already sent, even if they can't read it. Amazon expects you to report the current timestamp in the request header, you'll include that exact same timestamp in the hash, and when Amazon receives your request, they will try to re-compute your hash using all the info they've got.

If the hash matches AND the reported timestamp is within 15 minutes of the current time, you're accepted. I suspect the 15-minutes issue is one of your problems.

As far as how to simulate these calls. I think you'll find it's probably easier to just write a very basic RESTful API of your own that does these calls using an SDK published by Amazon. Then you don't have to deal with any of the crazy signature computation and you can call your APIs however you want.

0
votes

Copy-paste from https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html

  1. Launch Postman.

  2. Enter the endpoint URL of a request in the address bar and choose the appropriate HTTP method from the drop-down list to the left of the address bar.

3.If required, choose the Authorization tab. Choose AWS Signature for the authorization Type. Enter your AWS IAM user's access key ID in the AccessKey input field. Enter your IAM user secret key in SecretKey. Specify an appropriate AWS region that matches the region specified in the invocation URL. Enter execute-api in Service Name.

4.Choose the Headers tab. Optionally, delete any existing headers. This can clear any stale settings that may cause errors. Add any required custom headers. For example, if API keys are enabled, you can set the x-api-key:{api_key} name/value pair here.

5.Choose Send to submit the request and receive a response.