V
V
Vladimir2019-07-31 11:20:56
PHP
Vladimir, 2019-07-31 11:20:56

AWS S3 Access Denied error when trying to upload files directly via pre-signed POST. Where to dig?

I'm trying to upload files to the cloud, bypassing my server.
Here is the php code:

<?php

require '../vend/vendor/autoload.php';
use Aws\S3\S3Client;  
use Aws\S3\Exception\S3Exception;

$bucket = '***';
$IAM_KEY = '***';
$IAM_SECRET = '***';

try {
    $s3 = S3Client::factory(
        array(
            'credentials' => array(
                'key' => $IAM_KEY,
                'secret' => $IAM_SECRET
            ),
            'version' => 'latest',
            'region'  => 'us-east-1'
        )
    );
} catch (Exception $e) {
    die("Error: " . $e->getMessage());
}

$formInputs = ['acl' => 'public-read'];
$options = [
    ['acl' => 'public-read'],
    ['bucket' => $bucket],
    ['starts-with', '$key', ''],
];
$expires = '+2 hours';

$postObject = new \Aws\S3\PostObjectV4(
    $s3,
    $bucket,
    $formInputs,
    $options,
    $expires
);

$formAttributes = $postObject->getFormAttributes();

$formInputs = $postObject->getFormInputs();

?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Aws S3 Direct File Uploader</title>
</head>
<body>

<form action="<?= $formAttributes['action'] ?>" method="post" enctype="multipart/form-data">
<?php
    foreach ($formInputs as $key => $value) {
        echo "<input type='hidden' name='$key' value='$value' />";
    }
?>
<input type="file" name="file" />
<input type="submit" value="Upload File" />
</form>

CORS config:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
      <CORSRule>
          <AllowedOrigin>*</AllowedOrigin>
          <AllowedMethod>GET</AllowedMethod>
          <AllowedMethod>POST</AllowedMethod>
          <AllowedMethod>PUT</AllowedMethod>
          <MaxAgeSeconds>3000</MaxAgeSeconds>
          <AllowedHeader>*</AllowedHeader>
      </CORSRule>
</CORSConfiguration>

IAM user policy:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::*"
            ]
        }
    ]
}

After the form is submitted, an XML error is thrown:
<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>1A71B86B340FAB93</RequestId>
  <HostId>
    4ve5duEAF5ph+o7Y57JapqU3kzqZzDEWEF6Lrb64lGY2jCZobGB19z06fXRXxI+GzmQRA83o/FU=
  </HostId>
</Error>

I want to clarify an important point: I tried to do a normal download with the same credentials via putObject () and everything went fine, the object was created in the bucket. It was also possible to download objects through getObject(). Tell me where to dig, I've already tried everything, Google does not help.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ivan Shumov, 2019-07-31
@Cosss

By the fact that someone forgot that if you put an ACL on an object, then you need to give the rights to it)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
    ]
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question