Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Suspicious Operation: Attempted access to "" denied' while loading static files

I've been through the ringer getting my Django app setup on Heroku using Amazon s3 to host the static and media files. I've been following this guide https://www.caktusgroup.com/blog/2014/11/10/Using-Amazon-S3-to-store-your-Django-sites-static-and-media-files/ and what seems like thousands of other resources, collectstatic has worked and heroku is deploying it - but displays a 400 error. When I try and run it locally i get more info:

Attempted access to '/css/reset.css' denied.

This is the line that gets highlighted:

<link rel="stylesheet" type="text/css" href="{% static '/css/reset.css' %}">

I can load the static files direct from the URL if I grab it from my s3 admin panel so I figured it wasn't a bucket policy issue, I've messed around with https / http options but no joy. So I figure it must be the wrong path is being called somehow in the code - i just can't see where!

Any help much appreciated, I don't think I've blinked for about 4 hours straight.

Traceback:

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in _normalize_name
  358.             return safe_join(self.location, name)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in safe_join
  59.         raise ValueError('the joined path is located outside of the base path'

During handling of the above exception (the joined path is located outside of the base path component), another exception occurred:

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/devtop/webdev/projects/intro/intro/profiles/views.py" in index
  14.     return render(request, 'home.html', {'welcome':welcome})

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/shortcuts.py" in render
  30.     content = loader.render_to_string(template_name, context, request, using=using)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/loader.py" in render_to_string
  68.     return template.render(context, request)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
  207.                     return self._render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  177.             return compiled_parent._render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in render
  105.         url = self.url(context)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in url
  102.         return self.handle_simple(path)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in handle_simple
  117.             return staticfiles_storage.url(path)

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in url
  487.         name = self._normalize_name(self._clean_name(name))

File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in _normalize_name
  361.                                       name)

Exception Type: SuspiciousOperation at /
Exception Value: Attempted access to '/css/reset.css' denied.

settings.py

AWS_ACCESS_KEY_ID=os.environ.get('AWS_ACCESS_KEY_ID',None)
AWS_SECRET_KEY=os.environ.get('AWS_SECRET_KEY',None)
AWS_SECRET_ACCESS_KEY=os.environ.get('AWS_SECRET_KEY', None)
AWS_STORAGE_BUCKET_NAME = 'intro-story'
AWS_S3_HOST='s3.us-east-2.amazonaws.com'
AWS_S3_CUSTOM_DOMAIN = 's3.us-east-2.amazonaws.com/%s' % AWS_STORAGE_BUCKET_NAME

AWS_S3_SECURE_URLS = False

STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = 'custom_storages.StaticStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)

MEDIAFILES_LOCATION = 'media'
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'


try:
    from .local_settings import *
except ImportError:
    pass

local_settings.py

AWS_ACCESS_KEY_ID = "xxx"
AWS_SECRET_ACCESS_KEY = "yyy"

custom_storages.py

from django.conf import settings
from storages.backends.s3boto import S3BotoStorage

class StaticStorage(S3BotoStorage):
    location = settings.STATICFILES_LOCATION

class MediaStorage(S3BotoStorage):
    location = settings.MEDIAFILES_LOCATION

EDIT:


I managed to get it working by messing around with various values in the settings.py, but is still not right.

Here is all the stuff relating to static and media paths

STATICFILES_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'

import custom_storages

STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
STATICFILES_STORAGE = 'custom_storages.StaticStorage'

MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'

Here is custom_storage that I'm importing:

from django.conf import settings
from storages.backends.s3boto import S3BotoStorage

class StaticStorage(S3BotoStorage):
    location = settings.STATICFILES_LOCATION

class MediaStorage(S3BotoStorage):
    location = settings.MEDIAFILES_LOCATION

Now, if i comment out

STATICFILES_STORAGE = 'custom_storages.StaticStorage'

It will load the static files from S3 and all is fine, BUT collectstatic fails. If I uncomment that line, collectstatic works but it gives an error when I try and load the site. The error is:

 # Ensure final_path starts with base_path and that the next character after
    # the final path is '/' (or nothing, in which case final_path must be
    # equal to base_path).
    base_path_len = len(base_path)
    if (not final_path.startswith(base_path) or
            final_path[base_path_len:base_path_len + 1] not in ('', '/')):
        raise ValueError('the joined path is located outside of the base path' ...
                         ' component')
    return final_path.lstrip('/')

So clearly something is up with that custom_storage part but I have no idea what :/

like image 514
Zeb Avatar asked Apr 20 '17 21:04

Zeb


1 Answers

Sorted! As expected it was something annoyingly simple but perhaps this will help anyone else who hits the same wall.

This:

<link rel="stylesheet" type="text/css" href="{% static '/css/reset.css' %}">

Needed to be this:

<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">

I.e. no leading slash in the href. Worked fine using local static files storage but broke the S3 link.

like image 172
Zeb Avatar answered Oct 29 '22 21:10

Zeb