I'm having an issue with Django static files. I'm using Django admin and Django Rest Framework. I'm trying to serve the static files for admin and DRF with an S3 bucket. I can successfully visit the URL of any file in the bucket and it will load in my browser, and the file is served over HTTPS.
I created a nested stack in CloudFormation for the S3 bucket:
Description: >
This template deploys S3 buckets for serving Django static files.
Parameters:
AppUrl:
Type: "String"
Description: "The URL for our app (e.g. mydomain.com)"
AllowedPattern: "[a-z0-9._-]+"
Resources:
AssetsBucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName: !Sub ${AppUrl}-assets
AssetsBucketPolicy:
Type: "AWS::S3::BucketPolicy"
Properties:
Bucket: !Ref AssetsBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: PublicReadForGetBucketObjects
Effect: "Allow"
Principal: "*"
Action: "s3:GetObject"
Resource: !Sub "${AssetsBucket.Arn}/static/*"
When my application starts, it runs collectstatic
and the static files are moved into the bucket. Here's the issue I'm having:
When I visit a DRF URL with the query parameter ?format=json
. This returns a JSON response, with no static files from the browsable API, and I don't see any errors. However, when I visit the browsable API or the admin interface, I seem to find one of three error messages. In Chrome, I'm either seeing two types of behavior. The HTTPS is stripped from the URL (crossed out in red), but the static assets load with one of these two errors showing up in the console:
Access to font at 'https://mydomain.com-assets.s3.amazonaws.com/static/admin/fonts/Roboto-Bold-webfont.woff' from origin 'https://api.mydomain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
or
GET https://mydomain.com-assets.s3.amazonaws.com/static/rest_framework/css/bootstrap.min.css net::ERR_CERT_COMMON_NAME_INVALID
In Firefox, the static files don't load, the HTTPS is not stripped, and I see the following error in the network tab of the debug window:
An error occured: SSL_ERROR_BAD_CERT_DOMAIN
I have tried adding a CORS policy to the bucket using the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
But this did not fix the HTTPS issue. Is there something I'm missing that will help me get rid of the crossed out HTTPS?
I am confident that the certificate is OK, and that the issue is not related to HTTP being requested over an HTTPS connection. I believe this is a CORS issue, so I'm not sure why adding the CORS bucket policy didn't fix this.
Also, I have django-cors-headers installed in my Django app with CORS_ORIGIN_ALLOW_ALL = True
.
As per the S3 Bucket Naming Documentation, the issue seems to be with the dot in the bucket name.
When you use virtual hosted–style buckets with Secure Sockets Layer (SSL), the SSL wildcard certificate only matches buckets that don't contain periods. To work around this, use HTTP or write your own certificate verification logic. We recommend that you do not use periods (".") in bucket names when using virtual hosted–style buckets.
Slugify the name of the domain name in the bucket name (replace dot with hyphens) to make it work.
Link to the documentation: here