Dmitry Khavanskiy
Dmitry Khavanskiy

Reputation: 51

403 Forbidden: AWS S3, Django, S3Boto3Storage, CKEditor

After several days of continuous attempts, I'm nearly ready to give up. I have a popular setup and I see many people have similar issues, but there is no comprehensive (and working!) answer.

I get this sort of errors in browser:

GET https://hull2hull-bucket.s3.amazonaws.com/ckeditor/ckeditor/?AWSAccessKeyId=AKIAVIMQUGHJHHUVNIPN&Signature=LDq%2F5bhKJUUIUIUUO3GGoH0Iksoho%3D&Expires=1618438498lang/en.js&t=K5H9 net::ERR_ABORTED 403 (Forbidden)

My website is powered by Django and hosted on Pythonanywhere. Static files are on Amazon S3 with a private policy. I connect Django and S3 bucket with S3Boto3Storage. Most of my static files (picture library, admin files etc) are working fine, but not when it comes to some js files or specific components. Particularly CKEditor and Debug Toolbar are refusing to work.

What I tried:

My current CORS:

[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "HEAD", "GET" ], "AllowedOrigins": [ "https://hull2hull-bucket.s3.amazonaws.com", "http://127.0.0.1:8000", "http://127.0.0.1", "http://localhost", "http://localhost:8000" ], "ExposeHeaders": [] } ]

My current policy:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::hull2hull-bucket/" } ] }

I really don't know what else is left to do. I believe I have quite popular setup for a website, there are tons of similar questions everywhere, and yet - no answer :(

Upvotes: 0

Views: 1422

Answers (3)

Kalkulus
Kalkulus

Reputation: 153

I did the above suggestions but didn't work for me. CKEditor by default uses the static directory to reference the static files. When I deployed my app with Nginx, the static_root used staticfiles to collectstatic. By the way, this is digitalocean, but you can always provide the full path to your directory on your cloud provider. A hack that worked for me was to have the below configuration in my settings file.

AWS_QUERYSTRING_AUTH = False
CKEDITOR_BROWSE_SHOW_DIRS = True
CKEDITOR_RESTRICT_BY_USER = True
CKEDITOR_RESTRICT_BY_DATE = False
CKEDITOR_BASEPATH = "https://fra1.digitaloceanspaces.com/<bucket_name>/static/ckeditor/ckeditor/"

The CKEDITOR_BASEPATH worked when I specified the full path. Hope it helps.

Upvotes: 1

Durodola Opemipo
Durodola Opemipo

Reputation: 409

The answer is quite straightforward, which is why you should refer to documentation when having issues with any particular library.

  1. django-ckeditor will not work with S3 through django-storages without this line in settings.py:

    AWS_QUERYSTRING_AUTH = False

ref: https://github.com/django-ckeditor/django-ckeditor#using-s3

  1. AWS_QUERYSTRING_AUTH (optional; default is True) Setting AWS_QUERYSTRING_AUTH to False to remove query parameter authentication from generated URLs. This can be useful if your S3 buckets are public.

ref: https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

Upvotes: 3

Guy_shash
Guy_shash

Reputation: 11

I was stuck in a similar situation in my django project (I've used IBM storage for the object storage instead) and after hours of frustration and headbanging I seem to have found the cause of the situation here.

It is important to understand that IBM object storage, as well as amazon s3 storage are flat i.e., they don't have the typical concept of files and directories. Instead all the files are located in a single location with directory location as file name prefix. See for more [info][1]:

Now with that knowledge, if you take a look at the html rendered from the html rendered upon adding the model you'll notice that the script tag used to fetch the javascript for ckeditor has something interesting.

<script src="{ENDPOINT_URL}/ckeditor/ckeditor-init.js?AWSAccessKeyId={ACCESS_ID};" data-ckeditor-basepath="{ENDPOINT_URL}/ckeditor/ckeditor/?AWSAccessKeyId={ACCESS_ID};" id="ckeditor-init-script"></script>

Now if you notice within the script there is a data-ckeditor-basepath location. This is most likely the directory within which all the ckeditor related modules files are stored. However, in our case the operation of fetching this is not defined in itself. The reason being that the concept of directory and folder doesn't exist for s3 storages. As far as I understand, this is an error within the editor implementation and cannot be gotten rid of. However, a makeshift workaround is that you can manually add the script tag for the required js while getting rid of the "data-ckeditor-basepath" attribute.

<script src="{ENDPOINT_URL}/ckeditor/ckeditor-init.js?AWSAccessKeyId={ACCESS_ID};" id="ckeditor-init-script"></script>

I would suggest adding it in the base.html template within django module. You can find it in the following location (within your virtual environment):

"\Lib\site-packages\django\contrib\admin\templates\admin\base.html".

You can add it just before the extra headers are loaded in the extrahead block.

{% block extrahead %}{% endblock %}

It is important to remember that this is just a makeshift solution and not a permanent one. The basepath attribute is most likely used somewhere but I'm just not able to figure out where. Since, so far, I've been able to use ckeditor without any issues. Do remember that it's best not to use any editor which might be formatting the file automatically with addons (i.e. pylint). I edited it with notepad and I'd suggest that to you too.

It's best to add the tag only within a virtual environment for the project. Further, it might be possible to change the header in the tag template itself but I just went with whatever I could do.

Also I believe that it'd be necessary to ensure public access as well since it'll be needed whenever any resources are rendered from within the used modules. (But that's just my opinion and I am not too sure about that myself).

Upvotes: 1

Related Questions