flysystem-aws-s3-v3 icon indicating copy to clipboard operation
flysystem-aws-s3-v3 copied to clipboard

Error executing "PutObject" when 'visibility' = 'public'

Open jakxnz opened this issue 5 years ago • 12 comments

Uploading public/visible files to S3 invokes an Error executing "PutObject"... error. But Uploading protected/private files works.

Version:

> composer show
league/flysystem-aws-s3-v3                1.0.23
aws/aws-sdk-php                           3.101.1

Example:

$adapter = new \League\Flysystem\AwsS3v3\AwsS3Adapter($client, 'bucket');
$fs = new \League\Flysystem\Filesystem($adapter, ['visibility' => 'public']);
$fs->write('public/test.txt', '');

Error:

Uncaught Aws\S3\Exception\S3Exception: Error executing "PutObject" on "https://bucket.s3.ap-southeast-2.amazonaws.com/public/test.txt"; AWS HTTP error: Client error: `PUT https://bucket.s3.ap-southeast-2.amazonaws.com/public/test.txt` resulted in a `403 Forbidden` response: AccessDeniedAccess Denied9C83D1 (truncated...) AccessDenied (client): Access Denied - AccessDeniedAccess

I notice that AwsS3Adapter will set the ACL to public-read. But no matter what I've tried I haven't been able to set a policy that will allow an ACL of public-read to PutObject. The bucket is configured to block public access, because we have a protected folder convention in the project. Can anyone suggest how to integrate?

jakxnz avatar Jul 03 '19 04:07 jakxnz

Hi to all,

I have the same problem with Aruba Object Storage, that implements S3 API.

ivanghisleni avatar Dec 13 '19 08:12 ivanghisleni

I have the same issue with Digital Ocean

KeizerDev avatar Mar 29 '21 15:03 KeizerDev

This is an issue with either the AWS SDK or the platform you're using. Flysytem is just a layer on top, but does nothing special but follow the AWS docks.

frankdejonge avatar Mar 29 '21 18:03 frankdejonge

This is an issue with either the AWS SDK or the platform you're using. Flysytem is just a layer on top, but does nothing special but follow the AWS docks.

Isn't the pattern of a protected path and a public path introduced by Flysystem?

If so, if S3 doesn't support a public-read ACL PutObject to a non-public bucket, then what configuration does Flysystem have for its public/protected pattern to support this use-case?

If it doesn't have a way to achieve a protected/public paradigm in S3 where the protected folder is equally protected at the S3 layer, then is that a potential issue with Flysystem?

jakxnz avatar Mar 29 '21 19:03 jakxnz

@jakxnz it works for regular S3, how can it be a Flysystem issue?

frankdejonge avatar Mar 29 '21 19:03 frankdejonge

Besides that, there is no way to enforce directory level visibility in S3.

frankdejonge avatar Mar 29 '21 20:03 frankdejonge

While putting visibility on public when doing initialisation of the adapter and using the write function to upload to my Digital Ocean spaces storage the file uploaded remains private. By default I have put file listing on restricted but having public files will still work.

I now have to use s3cmd setacl ....... --acl-public after I have uploaded the files to make it public because it doesn't work straightaway using Flysystem unfortunately.

In the past I have used the aws sdk directly and it used to work but I can't get it to work with this adapter unfortunately.

Edit: I do use the most recent version of this adapter

KeizerDev avatar Mar 29 '21 21:03 KeizerDev

Could anybody surface some example script or payloads I can look at? If there's really something on Flysystem's end I always want to fix it, but I have very little to go on right now apart from a "this doesn't work" statement.

frankdejonge avatar Mar 30 '21 06:03 frankdejonge

My Flysystem code look like this:

    $client = new Aws\S3\S3Client([
        'version' => 'latest',
        'region' => 'ams3',
        'endpoint' => 'https://ams3.digitaloceanspaces.com',
        'credentials' => [
            'key' => ''
            'secret' => '',
        ],
    ]);

    $adapter = new League\Flysystem\AwsS3V3\AwsS3V3Adapter(
        $client,
        'bucket-name',
        'my-prefix',
        new League\Flysystem\AwsS3V3\PortableVisibilityConverter(
            League\Flysystem\Visibility::PUBLIC
        ),
        null,
        ['ACL' => 'public-read']
    );

    $filesystem = new League\Flysystem\Filesystem($adapter);

Then I use the $filesystem to do:

$filesystem->write("path/image.png", $image, ['ACL' => 'public-read']);

This will as expected store the image on my Digital Ocean Spaces but even with the ACL options there it is still not getting the right ACL settings. I have to use s3cmd now to fix the acl.

When I use the Aws SDK directly it is working:

    $client = new Aws\S3\S3Client([
        'version' => 'latest',
        'region' => 'ams3',
        'endpoint' => 'https://ams3.digitaloceanspaces.com',
        'credentials' => [
            'key' => '',
            'secret' => '',
        ],
    ]);

    $client->putObject([
        'Bucket' => 'bucket-name',
        'Key' => $prefix . "/path/on/bucket.png",
        'SourceFile' => __DIR__."/local/path.png",
        'ACL' => 'public-read'
    ]);

After this is executed I am able to see the file directly as a public file on my Digital Ocean spaces like how it's expected.

The output of composer show is:

league/flysystem                 2.0.4 
aws/aws-sdk-php                  3.176.2 
league/flysystem-aws-s3-v3       2.0.4 

Please let me know if there is more information needed!

KeizerDev avatar Mar 30 '21 11:03 KeizerDev

i have same trouble with Aruba without ACL

tomas-kulhanek avatar Apr 15 '21 06:04 tomas-kulhanek

I was having the same problem, but adding ['ACL' => 'public-read'] to the write() method, did the trick for me.

phptek avatar Nov 04 '21 22:11 phptek

See https://github.com/thephpleague/flysystem-aws-s3-v3/issues/73#issuecomment-1015856788

cedricgeffroy avatar Jan 18 '22 21:01 cedricgeffroy