2
votes

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? - F_SO_K
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. - Guy

2 Answers

0
votes

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

import requests
r = requests.post(response, data = params)
0
votes

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.