Extension talk:AWS

About this board

No previous topics.

Could not write file "mwstore://AmazonS3/local-public/...

Ajmichels (talkcontribs)

(Also posted in GitHub issues for this repo)

I recently started getting these errors and I am struggling to figure out why.

Nothing has changed in my AWS configuration. The IAM configuration is still good and all of the bucket settings have not changed.

I am on PHP 7.4, MediaWiki 1.35, Extension:AWS 0.11.1. This hasn't really changed either.

I did recently update my composer dependencies. Per the MediaWiki documentation I removed my composer.lock file and ran composer install

Files are still being read from the bucket correctly.

Does anyone have troubleshooting suggests or know what the issue is?

I verified that the AWS credentials I am using are still working correctly. I also tried using the latest code from the extension's repo.

To be clear, this was working just fine a few weeks ago and the only thing that has changed since then was that I updated the composer dependencies and I enabled the VisualEditor functionality.

Here is the error I am seeing in the debug logs (some information obfuscated):

<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>NM94VF (truncated...)
 AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>NM94VF*******</RequestId><HostId>u6uU*************************************************</HostId></Error>
[error] [de39d4fe79d16409eda7a6cf] /wiki/Special:Upload   ErrorException from line 1104 of /var/www/html/extensions/AWS/s3/AmazonS3FileBackend.php: PHP Warning: doCreateInternal: S3Exception: Error executing "PutObject" on "******/Shopify_Photoshop_Actions.atn.zip"; AWS HTTP error: Client error: `PUT *******/Shopify_Photoshop_Actions.atn.zip` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>NM94VF (truncated...)
 AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>NM94VF*******</RequestId><HostId>u6uU*************************************************</HostId></Error>
#0 [internal function]: MWExceptionHandler::handleError()
#1 /var/www/html/extensions/AWS/s3/AmazonS3FileBackend.php(1104): trigger_error()
#2 /var/www/html/extensions/AWS/s3/AmazonS3FileBackend.php(1031): AmazonS3FileBackend->logException()
#3 /var/www/html/extensions/AWS/s3/AmazonS3FileBackend.php(347): AmazonS3FileBackend->runWithExceptionHandling()
#4 /var/www/html/extensions/AWS/s3/AmazonS3FileBackend.php(369): AmazonS3FileBackend->doCreateInternal()
#5 /var/www/html/includes/libs/filebackend/FileBackendStore.php(187): AmazonS3FileBackend->doStoreInternal()
#6 /var/www/html/includes/libs/filebackend/fileop/StoreFileOp.php(74): FileBackendStore->storeInternal()
#7 /var/www/html/includes/libs/filebackend/fileop/FileOp.php(301): StoreFileOp->doAttempt()
#8 /var/www/html/includes/libs/filebackend/FileOpBatch.php(176): FileOp->attempt()
#9 /var/www/html/includes/libs/filebackend/FileOpBatch.php(132): FileOpBatch::runParallelBatches()
#10 /var/www/html/includes/libs/filebackend/FileBackendStore.php(1308): FileOpBatch::attempt()

And here are the versions Composer is using for the extension's dependencies:

  - Locking aws/aws-sdk-php (3.209.17)
  - Locking composer/installers (v1.12.0)
Ajmichels (talkcontribs)

The issue is that my Wiki and bucket are private and I did not have $wgFileBackends['s3']['privateWiki'] = true; in my local settings. I am still not sure yet how this was working before and then stopped but... it is working now.

Thanks to Edward for helping me figure it out on GitHub.

Reply to "Could not write file "mwstore://AmazonS3/local-public/..."

Who should be using this extension?

2 (talkcontribs)

What kind of wiki is this good for?

Kghbln (talkcontribs)
Reply to "Who should be using this extension?"

JSON for IAM Policy update

HyverDev (talkcontribs)

Been looking at this and it seems the JSON for the IAM role isn't correct anymore. Maybe amazon changed their grammar policy since the original entry this is what I have got to:

    "Statement": [
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::<something>/*"
            "Effect": "Allow",
            "Action": [
            "Resource": "arn:aws:s3:::<something>"
Edward Chernenko (talkcontribs)

Nothing changed. The example in the article was always supposed to be inserted into the Statement array. This is not a "replace IAM inline policy with this" example, because IAM inline policy may already exist (and contain other rules that shouldn't be overwritten).

MyWikis-JeffreyWang (talkcontribs)

I think the OP's sentiment is valid. Not sure why the documentation doesn't include this. It would make the setup less confusing to deal with for those who are new to S3/IAM.

MyWikis-JeffreyWang (talkcontribs)

Upon inspection, it did, but as a citation. Since this is very important, I've taken it out of a footnote.

DiscordiaChaos (talkcontribs)

Is there an example file that will work for someone who created a brand-new bucket just for this?

I'm asking about this due to hearing about increased security issues regarding AWS, and I want to keep things locked down while still enabling regular use of Mediawiki.

[Edited to make things more clear and reduce confusion]

MyWikis-JeffreyWang (talkcontribs)

@DiscordiaChaos The above JSON, in its exact form (apart from the ARN needing to be filled in), should be safe.

Reply to "JSON for IAM Policy update"

PDF support lacking

1 (talkcontribs)

Doesn't seem to work very well with the pdf thumbnail pages generated by default by mediawiki, this is probably just a function of the realities of generating of a pdf for a file on an s3 store just don't make a lot of sense and probably should be processed as a batch job than done on the fly like configured by default.

Reply to "PDF support lacking"
Kghbln (talkcontribs)

This seeks to clarify this diff since I fail to understand your edit comment. Note that MediaWiki master is now at 1.37+. Your change means that the extension caters for MW 1.35, 1.36 and 1.37? Not sure if this is meant but it will be cool if this is correct I believe.

Edward Chernenko (talkcontribs)

The extension itself uses "master" compatibility policy, meaning that it maintains backward compatibility with MediaWiki 1.35. Its repository has REL1_34 branch that supports 1.27-1.34.

Kghbln (talkcontribs)

Cool, thanks for clarifying.

S3-compatibles also work?

2 (talkcontribs)

Does this extension also allow use of API-compatible backends like MinIO, Linode Object Storage, etc.?

Edward Chernenko (talkcontribs)

It does (see the README file for examples).

Reply to "S3-compatibles also work?"

Can this extension also store other files except from media files to AWS?

Summary by Edward Chernenko

All uploads (via Special:Upload) are stored in S3.

MavropaliasG (talkcontribs)

Hi, I would like to have mediawiki store uploaded datasets, csv files, and zip files (and in general any file) to AWS. Can I do this with this extension, or is it only for images (and videos?) Thanks

T0lk (talkcontribs)

If you can upload it to your wiki, this extension will put that file on s3. Does that help?

MavropaliasG (talkcontribs)

Thank you @T0lk, so this extension puts ALL uploads, regardless of their file type on s3?

Ciencia Al Poder (talkcontribs)

Yes. This works for all uploads (from Special:Upload)

MavropaliasG (talkcontribs)

Thank you for the reply @Ciencia Al Poder. Can I somehow also integrate it with the upload through visual editor? (i.e. when you edit a page with visual editor, and you press Insert > Media > Upload ?

Ciencia Al Poder (talkcontribs)

AFAIK, it affects *all uploads* to the local wiki, no matter how they're uploaded (special:upload was an example), since this is the common repository for the wiki, and there's no way to choose between file repositories on upload

MavropaliasG (talkcontribs)

Thank you for the information , much appreciated.

Summary by Edward Chernenko

Answered 1) why the current IAM permissions are not broad, 2) how to mark all uploaded S3 objects as non-public. (talkcontribs)

In my S3 bucket permissions I am trying to use the 4 "public access blocks". But when I do this MediaWiki cannot access the bucket and therefore the extension doesn't work.

Now given I am using an IAM policy I understand the "public access blocks" should not be an issue. I saw on an AWS video that an overly permissive IAM policy is considered public by AWS (I couldn't find this video as I was writing this), so I think that is what is happening here. This is surely overly-permissive. Has anyone had this issue?

The recommended IAM poilcy is:

"Action" "s3:*",

"Resource": "arn:aws:s3:::<something>/*",

"Action": [ "s3:Get*", "s3:List*" ],

"Resource": [ "arn:aws:s3:::<something>" ]

Would you agree the following permissions should work too (or am I missing needed permissions)?

"Action" [ "s3:ListObjects", "s3:GetObject", "s3:PutObject" ],

"Resource": "arn:aws:s3:::<something>/*",

"Action": [ "s3:GetObject", "s3:ListObjects" ],

"Resource": [ "arn:aws:s3:::<something>" ]

Thank you

Edward Chernenko (talkcontribs)
  1. It's not overly permissive. You are meant to use a separate S3 bucket for images, and if the S3 bucket contains only images, then there is no extra security added by only permitting certain operations. (I mean, with PutObject alone a malicious user can delete all files by overwriting them with zeroes, and you can't really restrict PutObject. While the very point of minimizing permissions is to reduce the possible impact of such malicious user's actions)
  2. Currently the extension also does CopyObject (when image is moved and/or deleted), DeleteObject and alike. You can find all API calls that it uses by searching for client-> in the code.
  3. There is no guarantee that additional API calls won't be used in the future versions. (that is, if some future change requires the use of "GetObjectVersion", then its addition won't be considered breaking anything, as the permission recommended in README is Get* - but it will break setups where only GetObject is allowed). (talkcontribs)

Understood, and thank you Edward for the prompt response.

The problem I am having is that using those permissions means that I cannot add the extra security layer which is to enforce the "4 public access blocks". While I appreciate that the risk and potential impact is low, I tend to like to increase the restrictions as much as possible.

I will add those permissions used in client-> calls only for the moment.

Edward Chernenko (talkcontribs) (talkcontribs)

Yes, I was referring to those Public Access Policies in your link.

I used to have the Public Access Policies blocked for all S3 buckets both at an individual level and at a global level, as a security setting. Using this extension with the recommended setup makes me have to take off the global block and the block at an individual level for the bucket that is being used by the extension.

I couldn't find clear documentation to understand this issue specifically with regards to IAM, I did listen to a YouTube video where I recall someone from AWS said something along the lines of "we don't like IAM roles that have * so they might be considered public". And when I remove the public access policies block, the extension works correctly. Therefore it seems to me that there is something in my setup that is being 'considered public'.

Other IAM and Bucket Policies that I am using are not creating this issue on other buckets. For example, if I turn on the public access policies block on the bucket being used by MediaWiki, Cloudfront will still serve images from that particular S3 bucket. So Cloudfront, ironically, has no 'public permissions' despite effectively making the entire bucket publicly readable via serving all of its contents through a subdomain...

On the link you provided, there is a section that says "The meaning of 'public'", which talks about the issue of granting * related to some elements in the Bucket Policies.

Its really a pain, but to keep the desired security setting of globally denying all Public Access Policies for S3 buckets I would like to find a solution.

I was planning on doing some testing with 'more restricted permissions' to see if that solves it. Maybe restricting the 'Actions' or maybe restricting access to my VPC only for instance?

Edward Chernenko (talkcontribs)

The only reason why your S3 buckets are considered "public" is because any visitor of non-private wiki can see/download the images that you have uploaded into it. This is by design (it's supposed to be public). It has nothing to do with IAM permissions that you mentioned above.

If you have a private wiki, then Extension:AWS marks all uploaded S3 objects with "private" ACL, so they are not accessible regardless of what you write in IAM.

In short, you are trying to solve a nonexistent problem. Since it has nothing to do with this extension, I can not provide further support on this matter. (talkcontribs)

[Note: _dot_ and _colon_ are used below to circumvent the ⧼abusefilter-warning-linkspam⧽]

It is not related to the images being accessible by any non-private wiki viewer. As I mention above:

"Cloudfront, ironically, has no 'public permissions' despite effectively making the entire bucket publicly readable via serving all of its contents through a subdomain..."

Why is the fact that any visitor can view/download the images not conflicting with the S3 buckets not being considered "public"? Because of the following configuration:

  1. set $wgAWSBucketDomain = 'img_dot_mysite_dot_com'; as indicated in the extension's readme
  2. set Cloudfront to serve the images from my bucket to 'img_dot_mysite_dot_com'
  3. set a Bucket Policy in the S3 bucket to allow Cloudfront to serve the images as follows:


   "Version": "2008-10-17",

   "Id": "PolicyForCloudFrontPrivateContent",

   "Statement": [


           "Sid": "1",

           "Effect": "Allow",

           "Principal": {

               "AWS": "arn:aws:iam::cloudfront:user/XXXXXXXXXXXXX"


           "Action": "s3:GetObject",

           "Resource": "arn:aws:s3:::XXXXXXXXXXXXXXX/*"




Here the buckets are not considered public with regards to the "4 public access blocks" for S3 but Cloudfront is granted access through the bucket policy. That read access is very well isolated from any other S3 type access, e.g. Put. Additionally it adds the extra layer of security of having the 4 public blocks enabled. This is our desired security setting.

And if I use the extension with "4 public access blocks", viewing the images in the wiki is not a problem. Any non-private wiki viewer can view the images given they are being served by AWS Cloudfront.

The problem comes when the EC2 server tries to write to the bucket. Why? it seems to me because the IAM policy is "considered public" by S3, and therefore I get an error such as the following:

Warning: doCreateInternal: S3Exception: Error executing "PutObject" on "https_colon_//s3_dot_amazonaws_dot_com/XXXXXXXXXX/thumb/XXXXXXXXXXXXXXXXX.jpg/120px-XXXXXXXXXXXXXXXXX.jpg"; AWS HTTP error: Client error: `PUT https_colon_//s3_dot_amazonaws_dot_com/XXXXXXXXXXXXXXXXX/thumb/XXXXXXXXXXXXXXXXX.jpg/120px-XXXXXXXXXXXXXXXXX.jpg` resulted in a `403 Forbidden` response: AccessDeniedAccess DeniedXXXXXX (truncated...) AccessDenied (client): Access Denied - AccessDeniedAccess Denied XXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXX/seo= in /var/www/html/w/extensions/AWS/s3/AmazonS3FileBackend.php on line 1117

Kris Ludwig (talkcontribs)

The IAM is not too broad.

The reason you are getting that error shouldn't be because the IAM policy is considered public by S3 but likely because the extension is trying to Put with ACL = public-read:

e.g. AmazonS3FileBackend.php:347: 'ACL' => $this->isSecure( $container ) ? 'private' : 'public-read',

Can you try the following in LocalSettings.php?

$wgFileBackends['s3']['privateWiki'] = true; (talkcontribs)

Seems to work.

Thank you!

Has anyone gotten this to work with $wgUseSharedUploads?

T0lk (talkcontribs)

I have a wiki-family setup and I installed this extension on my shared media repository (similar to commons.wikimedia.org), however, none of the other wiki's (for example, en.wikipedia, fa.wikipedia) could generate thumbnails on demand anymore. Images and thumbnails that existed before the migration loaded from s3 without a problem. Thumbnails generate in s3 when the media repository wiki is the one making the request, just not the other wiki's in the family make the request. These are the shared upload settings I'm using:

$wgUseSharedUploads = true;

//$wgSharedUploadPath = 'https://example.com/images'; #old setting

$wgSharedUploadPath = 'https://examplebucket.s3.amazonaws.com'; #new setting

$wgHashedSharedUploadDirectory = true;

$wgSharedUploadDirectory = "images";

$wgFetchCommonsDescriptions = true;

$wgSharedUploadDBname = 'example_wikidbcommons';

$wgSharedUploadDBprefix = '';

$wgRepositoryBaseUrl = "https://example.com/File:";

This is the equivalent code using wgForeignFileRepos

$wgForeignFileRepos[] = [

        'class' => 'ForeignDBRepo',

        'name' => 'mywiki',

        //'url' => "https://example.com/images", #old

        'url' => "https://examplebucket.s3.amazonaws.com", #new

        'directory' => 'images',

        'hashLevels' => 2, // This must be the same for the other family member

        'dbType' => $wgDBtype,

        'dbServer' => $wgDBserver,

        'dbUser' => $wgDBuser,

        'dbPassword' => $wgDBpassword,

        'dbFlags' => DBO_DEFAULT,

        'dbName' => 'example_wikidbcommons',

        'tablePrefix' => '',

        'hasSharedCache' => false,

        'descBaseUrl' => 'https://example.com/File:',

        'fetchDescription' => true


I'm not sure what else I should be changing, $wgSharedUploadPath says "Thumbnails will also be looked for and generated in this directory."

T0lk (talkcontribs)

I was able to resolve the problem. The solution is to modify the $wgForeignFileRepos I posted above as follows:

Change: 'name' => 'local',

Add: 'backend' => 'AmazonS3',

Reply to "Has anyone gotten this to work with $wgUseSharedUploads?"

Amazon EFS drive and mount it to $wgUploadDirectory.

Donxello (talkcontribs)

you mention " Instead of using Amazon S3 (and this extension), you can create an Amazon EFS drive and mount it to $wgUploadDirectory. It's recommended for small wikis".

I have created an EFS drive and mounted it to my instance where the wikis is being run.

But how can I make this EFS drive the uploadDirectory in the LocalSettings? I have a DNS for this EFS but that's it?

Thanks Tristan

Edward Chernenko (talkcontribs)

Just mount it to /path/to/your/mediawiki/images, that's it.

Donxello (talkcontribs)

This time it worked, the other day not.

We run several WIKIs and your extension is great but will you maintain it or what is the plan in the future?

Anyway, highly appreciate your work so far!

Un abrazo.

Edward Chernenko (talkcontribs)

1) If you use EFS, you don't need this extension. Mounting EFS works with MediaWiki out-of-the-box. 2) No particular plans (I don't use it on my own wikis). But feature-wise, this extension has 99% of what's needed, plus it's covered with automated tests and all.

Reply to "Amazon EFS drive and mount it to $wgUploadDirectory."
Return to "AWS" page.