i'm trying to upload a file (an image for my tests) to my s3 bucket with a pre-signed post generated with AWS SDK PHP. Firstable i generate the pre-signed post, then i manually create the request with given PostObjectV4 datas with Postman or via a simple html form... After filling everything, the request result in Access Denied :-(. The user associated with the client to generate the PostObjectV4 has Allowed s3:PutObject policy on the corresponding bucket.
I've already tried to :
PHP code of pre-signed post generation (datas are in $postObject) :
$assetAwsS3Key = $this->getAssetAwsS3Key($asset);
$options = [
['starts-with', '$key', 'myDir/'],
];
// Optional: configure expiration time string
$expires = '+24 hours';
// Set some defaults for form input fields
$formInputs = ['acl' => 'private'];
$postObject = new PostObjectV4(
$this->buildAwsS3UserClient(),
$this->awsBucketName,
$formInputs,
$options,
$expires
);
// Get attributes to set on an HTML form, e.g., action, method, enctype
$formAttributes = $postObject->getFormAttributes();
// Get form input fields. This will include anything set as a form input in
// the constructor, the provided JSON policy, your AWS access key ID, and an
// auth signature.
$formInputs = $postObject->getFormInputs();
return ['formAttributes' => $formAttributes, 'formInputs' => $formInputs];
My user (used for client generation) policy :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::awsBucketName/*"
]
}
]
}
My simple html form for test upload:
<form method="post" action="https://my-bucket.s3.eu-west-3.amazonaws.com" enctype="multipart/form-data">
<input type="hidden" name="key" value="myKey/sources/myImg.jpg" /><br />
<input type="file" name="file" /> <br />
<input type="hidden" name="X-Amz-Credential" value="MYUSERACCESSKEY/20190510/eu-west-3/s3/aws4_request" />
<input type="hidden" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" name="X-Amz-Date" value="20190510T132109Z" />
<input type="hidden" name="Policy" value='MYBASE64ENCODEDPOLICY' />
<input type="hidden" name="X-Amz-Signature" value="MYSIGNATURE" />
<input type="submit" name="submit"/>
</form>
Do you have an idea/clue why this upload fail while the bucket isn't public write-access allowed ?
Many thanks in advance !
I got rid of the problem, i'll share the changes i made here since my first post in order to get the upload to work. Please adapt it to your needs if necessary.
The AWS configuration used: - Same in-line policy attached to my user as in the first post(please be sure of the bucket name you set in the resource key) - S3 Bucket with no policy attached to it - S3 Bucket All Public Access Disabled
Here is my up to date php code for creating the postObject :
$objectKey = $this->objectKeyGenerator->getObjectKey($object);
$options = [
['bucket' => $this->getBucketName()],
['eq', '$key', $objectKey],
['acl' => 'private']
];
// Optional: configure expiration time string
$expires = '+2 hours';
// Set some defaults for form input fields
$formInputs = [
'acl' => $acl,
'key' => $objectKey
];
$postObject = new PostObjectV4(
$this->getS3Client(),
$this->getBucketName(),
$formInputs,
$options,
$expires
);
// Get attributes to set on an HTML form, e.g., action, method, enctype
$formAttributes = $postObject->getFormAttributes();
// Get form input fields. This will include anything set as a form input in
// the constructor, the provided JSON policy, your AWS access key ID, and an
// auth signature.
$formInputs = $postObject->getFormInputs();
return ['formAttributes' => $formAttributes, 'formInputs' => $formInputs];
What changes in the postObject generation compared to my first post :
I tried to reproduce the error by removing the bucket and acl from the $option array and this led to an '403 Forbidden error' but with a message stating 'Invalid according to Policy: Extra input fields: bucket' which i find not very obvious... I haven't investigate more on this error.
I'm also sharing my html form that changed a bit since first post, input fields order changed and acl field was added because required by the policy.
<form method="post" action="https://my-bucket.s3.eu-west-3.amazonaws.com/" enctype="multipart/form-data">
<input type="hidden" name="key" value="object/key.txt" /><br />
<input type="hidden" name="acl" value="private"/>
<input type="hidden" name="X-Amz-Credential" value="MYUSERACCESSKEY/20190510/eu-west-3/s3/aws4_request" />
<input type="hidden" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" name="X-Amz-Date" value="20200108T093921Z" />
<input type="hidden" name="Policy" value='MYBASE64ENCODEDPOLICY' />
<input type="hidden" name="X-Amz-Signature" value="MYSIGNATURE" />
File:
<input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit"/>
To conclude, in my original post i don't talk about my s3 bucket public-access and policy configuration and i think that the problem could have been here.
Hope this helps, feel free to ask for details if necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With