thephpleague / flysystem

Abstraction for local and remote filesystems
https://flysystem.thephpleague.com
MIT License
13.36k stars 827 forks source link

S3 v3 createDirectory() is triggering a 403 Forbidden Client Error #1784

Open rk opened 6 months ago

rk commented 6 months ago

Bug Report

Recently upgraded application with Laravel 10, Laravel Backpack 6, with barryvdh/elfinder as a filemanager for the client (for organization and bulk-uploads). Prior to these upgrades, the application had stable access to the S3 bucket and could easily create/delete/upload files and folders.

Q A
Flysystem Version 3.27.0
Adapter Name league/flysystem-aws-s3-v3
Adapter version 3.27.0
PHP 8.2

Summary

We recently upgraded an application to Laravel v10, Backpack v6, and the latest elfinder. Previous to these upgrades, for some unknown time, the application was able to call $adapter->createDirectory('test') and succeed.

Now, we get the following error.

elfinder debug: [error] [elfinder] Unable to write file at location: Brand Resources/test/.
Error executing "PutObject" on "https://[bucketname].s3.amazonaws.com/Brand%20Resources/test/"
AWS HTTP error: 
Client error: `PUT https://[bucketname].s3.amazonaws.com/Brand%20Resources/test/` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>T9W6QS (truncated...)
 AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>T9W6QSBF8FVGBK4K</RequestId><HostId>FGsBhIy7PIIRYJ0UGNBeOQujDI8t6NSOpcGcDCcsaXCy7J6Lwton0dHSlSImGKkmsGmywvpJf5hfyZsQ/q/2tEt2qpLH/I8fLUdqGpZRHEY=</HostId></Error>

I updated the IAM policy to allow all S3 actions on the bucket for testing (I don't recommend this, but had to rule a policy issue out):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::bucketname",
                "arn:aws:s3:::bucketname/*"
            ]
        }
    ]
}

So this doesn't appear to be an issue with the IAM policy attached to the user. I can upload files to this same bucket/adapter, but it immediately dies upon a call to createDirectory().

Laravel configuration for the disk is 100% stock. Nothing custom.

Bucket settings/details:

How to reproduce

Reproducing this error does not require use of elFinder. So I can eliminate that as a cause of the issue.

Steps to reproduce for me:

$ php artisan tinker
Psy Shell v0.12.3 (PHP 8.2.18 — cli) by Justin Hileman
> \Storage::disk('s3')->createDirectory('test')

   League\Flysystem\UnableToWriteFile  Unable to write file at location: test/. Error executing "PutObject" on "https://[bucketname].s3.amazonaws.com/test/"; AWS HTTP error: Client error: `PUT https://[bucketname].s3.amazonaws.com/test/` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>FS62F3 (truncated...)
 AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>FS62F37KJGX47BRS</RequestId><HostId>pR6z/0NhBPLqnFt5FTbmFI/VOkTidY2rF1kwXgysSqEzik8jF2NNJeewJkZb9dhC8QwGiByJOzk=</HostId></Error>.

> \Storage::disk('s3')->createDirectory('Brand Resources/test')

   League\Flysystem\UnableToWriteFile  Unable to write file at location: Brand Resources/test/. Error executing "PutObject" on "https://[bucketname].s3.amazonaws.com/Brand%20Resources/test/"; AWS HTTP error: cURL error 35: A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot. (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://[bucketname].s3.amazonaws.com/Brand%20Resources/test/.

The 2nd test is the first time I've observed that error. Is this server related?

frankdejonge commented 6 months ago

Hi, I'm not sure how a Flysystem change can cause a 403 in this case. I would have expected a 400. Are you able to do any other write? Since directory creation in S3 is just a relatively normal write. If you have a bucket that enforces no ACL, you may need to configure the default directory permissions to be private instead of the default public permissions.

rk commented 6 months ago

Hi Frank,

Yes, I can write files to both locations. I thought to check that, and I'm wondering if it's an AWS client library issue. I maintain several other projects with similar policies, and library versions, and they haven't had the issue.

The bucket is 100% private, and we use signed links for any downloads.

It's been driving me crazy this week.