2

There are a few examples for the way to pre-sign the URL of an S3 request, but I couldn't find any working example to pre-sign other services in AWS.

I'm trying to write an item to DynamoDB using the Python SDK botos. The SDK included the option to generate the pre-signed URL here. I'm trying to make it work and I'm getting a URL, but the URL is responding with 404 and the Item is not appearing in the DynamoDB table.

import json
ddb_client = boto3.client('dynamodb')

response = ddb_client.put_item(
    TableName='mutes',
    Item={
        'email': {'S':'[email protected]'},
        'until': {'N': '123'}
        }
    )

print("PutItem succeeded:")
print(json.dumps(response, indent=4))

This code is working directly. But when I try to presign it:

ddb_client = boto3.client('dynamodb')

params = {
    'TableName':'mutes', 
    'Item':
        {
            'email': {'S':'[email protected]'}, 
            'until' : {'N': '1234'}
        }

}

response = ddb_client.generate_presigned_url('put_item', Params = params)

and check the URL:

import requests
r = requests.post(response)
r

I'm getting: Response [404]

Any hint on how to get it working? I checked the IAM permissions, and they are giving full access to DynamoDB.

Please note that you can sign a request to DynamoDB using python, as you can see here: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html#sig-v4-examples-post . But for some reasons, the implementation in the boto3 library doesn't do that. Using the boto3 library is much easier than the code above, as I don't need to provide the credentials for the function.

2
  • Have you tried setting the http method? "By default, the http method is whatever is used in the method's model". Its not clear to me how this works, but are you signing a put method and then calling get on it? Could that be an issue? Commented Feb 20, 2019 at 9:49
  • Thank you @Stu for your attention. I tried to add "HttpMethod = 'PUT'" to the call, and I also tried other methods such as get_item, with the same 404 error. Commented Feb 20, 2019 at 19:39

2 Answers 2

0

You send an empty post request. You should add the data to the request:

import requests
r = requests.post(response, data = params)
Sign up to request clarification or add additional context in comments.

1 Comment

It doesn't work for me. If you notice the params are in presigned URL: "dynamodb.eu-west-1.amazonaws.com/?TableName=mutes&Key=...". There is something else that is missing.
0

I think you are having this issue, that's why you are recieving a 404. They recommend using Cognito for authentication instead of IAM for this cases.

1 Comment

There are many ways that are insecure (Cognito with Unauthenticated users, API Gateway that is open to the world, etc), or Complex (sign into Cognito, or authenticate to API-GW, for example). I'm looking for a way to embed a link in an email. I can't make it too open to be abused by others. It has to have time expiration and simple enough that the user can simply click on it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.