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

Error creating directory when public access is blocked to the bucket.

Open abishekrsrikaanth opened this issue 2 years ago • 4 comments

I am using Laravel 9 and I am trying to create a directory in a bucket.

Storage::disk('s3')->makeDirectory("tenants/abcde");

The tenants directory already exists, but running the above command throws the following error.

League\Flysystem\UnableToWriteFile with message 'Unable to write file at location: tenants/abcde/.'

I have checked the credentials that I am using and the access_key has S3FullAccess. The strange thing is, I created a folder directly using the S3 console and I am able to programmatically add files in the folder or even delete the folder, but if I try to make a new directory, I get the above error. I have even tried to use the root access_key and I still get the same error.

abishekrsrikaanth avatar Apr 01 '22 21:04 abishekrsrikaanth

On further debugging, I see the following error from AWS.

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessControlListNotSupported</Code><Message>The bucket does not all (truncated...)
 AccessControlListNotSupported (client): The bucket does not allow ACLs - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessControlListNotSupported</Code><Message>The bucket does not allow ACLs</Message>

My bucket is public access blocked as recommended by Amazon's best practice and the only way to read files are through cloudfront. There is a bucket policy that allows read access only through cloudfront.

Having said that, debugging the underlying code the following code doesn't work and results in the error above.

use Aws\S3\S3Client;

$client = new S3Client([
    'credentials' => [
        'key'    => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY')
    ],
    'region' => 'us-east-1',
    'version' => 'latest',
]);

$client->putObject(array( 
                   'Bucket' => 'bucket-name',
                   'Key'    => "tenant/cdfe",
                   'Body'   => "",
                   'ACL'    => 'public-read'
                  ));

but removing the ACL from the array passed to putObject works correctly.

abishekrsrikaanth avatar Apr 01 '22 22:04 abishekrsrikaanth

@abishekrsrikaanth what if you use an ACL of private?

frankdejonge avatar Apr 02 '22 08:04 frankdejonge

@frankdejonge ACL set to private works.

abishekrsrikaanth avatar Apr 02 '22 20:04 abishekrsrikaanth

@abishekrsrikaanth then you can configure the adapter to have a default directory visibility of private to resolve this issue. The visibility constructor property allows you to use a PortableVisibilityConverter instance which accepts this configuration setting.

frankdejonge avatar Apr 02 '22 20:04 frankdejonge