HTTP to HTTPS with health link on Elastic Beanstalk using Django - django

I am trying to redirect Http to Https in Django deployed on AWS Beanstalk. Http to Https works fine when I remove the health link from the load balancer. while having link in load balancer the app stops working.
I am using the following config in settings file in the Django project hosted on Aws Beanstalk.
CORS_REPLACE_HTTPS_REFERER = True
HOST_SCHEME = "https://"
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_PRELOAD = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True

With SECURE_SSL_REDIRECT = True all non-secure requests will be redirected to https. Non-secure requests - ones done via http and with not matched SECURE_PROXY_SSL_HEADER.
Even if your load balancer performs http to https redirect by itself - it is good to have this option enabled in django and simplier (all security options enabled).
AWS ALB Health Checks cannot set custom headers. We can exclude requests to certain endpoints from being redirected to https with SECURE_REDIRECT_EXEMPT - [r'^health/$'].
AWS ALB Health Check requests are done to instance ip. To allow django process them - ip needs to be added to ALLOWED_HOSTS: ["172.16.2.5", "my.example.com"]. This needs to be instance private ip, one that will be used by ALB to reach it.
This can be done with:
Adding instance ip on instance start like in example. It can also be done with custom scripts and environment variables.
using custom middleware which allows adding ip ranges in ALLOWED_HOSTS and add VPC Subnet range or implement custom middleware manually
AWS ALB cannot add HSTS headers. If you want to use Strict Transport Security headers - they should be added on app django side. This can be done with setting SECURE_HSTS_SECONDS other than zero.
HSTS headers are only added on responses to secure requests (https:// or SECURE_PROXY_SSL_HEADER match).

I had the same problem and I fixed it with a middleware (python 3.x):
production settings.py:
MIDDLEWARE = ['market.middleware.ELBHealthChecker_middleware'] + MIDDLEWARE
ELB middleware:
def ELBHealthChecker_middleware(get_response):
def middleware(request):
response = get_response(request)
if "ELB-HealthChecker" in request.META["HTTP_USER_AGENT"]:
from django.http import HttpResponse
return HttpResponse(status=200)
return response
return middleware

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
These have worked for me in the past.

Related

how to solve origin 'http://127.0.0.1:9000' has been blocked by CORS policy

Access to font at 'https://fra1.digitaloceanspaces.com/ewan-space/ewan/static/admin/fonts/Roboto-Light-webfont.woff' from origin 'http://127.0.0.1:9000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
i see tihis erorr in django admin when i collect my static in digitalochenspace , and it's work fine in when collect static in localhost,
this is my code
settings
#installed apps
"corsheaders",
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",]
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL=True
django 3.2
python 3.8
how to solve this problem ?

SSL certificates and https for AWS hosted django site

I have a django site hosted on elastic beanstalk. I have obtained a AWS SSL certificate and this has been associated with the load balancer 443 HTTPS port.
In my config file I have:
MIDDLEWARE = [
...
"django.middleware.csrf.CsrfViewMiddleware",
]
CSRF_COOKIE_HTTPONLY = False
SESSION_COOKIE_HTTPONLY = True
With this setup I am able to login to the site but the browser displays 'not secure' in the address bar, and if I prepend 'https://' to the urls I get a page stating the connection is not private.
If I add
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
Then it becomes impossible to login (the login page just reloads) or if I got to a incognito browser I get a 'CSRF verification failed. Request aborted.' message.
Apologies for the long question, I've just tried to include ay detail that may be relevant
In settings.py
Add IP and domain in ALLOWED_HOSTS list.
You can put *, but it is not recomended. * means all host are allowed here.
ALLOWED_HOSTS = ['your_ip']
I had my load balancer listener configured wrong for port 4443. I had the instance port and instance protocol as 443 and https whereas they should be 80 and http

CSRF verification failed when logging into admin panel

In production my app is giving me CSRF verification failed when I log into my admin panel.
I have the following in my settings.py:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
As my site doesn't currently have an SSL certificate I have ignored the following after running python manage.py check --deploy:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
If you use those two settings then you must be using SSL.
See:
SESSION_COOKIE_SECURE
CSRF_COOKIE_SECURE

Redirect root domain to www in aws route 53 without S3

I want to redirect my root domain to www.domain.com. The site is published using s3 CloudFront and route53.
I have seen a lot of docs on how to redirect using s3, but I cannot do it because there's already a bucket with my root domain somewhere. So I cannot create a bucket with my root domain as the name. Also, I doubt whether this s3 redirection will work for the https request.
I haven't seen any blog on redirecting without using the s3 bucket.
So how can I redirect an HTTP/https root domain to www subdomain in aws.
You cannot redirect using Route 53 (it is a DNS configuration service afterall, whereas redirects are a HTTP operation).
If you cannot use S3, another solution could be to use use CloudFront with a Lambda#Edge function.
If the hostname is not the www domain you could perform the redirect to the www domain.
The function might look similar to the below
def lambda_handler(event, context):
request = event["Records"][0]["cf"]["request"]
response = event["Records"][0]["cf"]["response"]
# Generate HTTP redirect response with 302 status code and Location header.
if request['headers']['host'][0]['value'] != 'www.example.com':
response = {
'status': '302',
'statusDescription': 'Found',
'headers': {
'location': [{
'key': 'Location',
'value': 'https://www.example.com/{}' .format(request['uri'])
}]
}
}
return response
This is how I solved it:
Create a CloudFront distribution for your root domain, e.g. domain.com
Set an Application Load Balancer as an origin for this distribution
Create a rule for your ALB listener:
if (all match)
HTTP Host Header is domain.com
Then
Redirect to #{protocol}://www.domain.com:#{port}/#{path}?#{query}
Status code: HTTP_301

Redirect www subdomain to an apex (naked) domain on Route 53 (not using S3)?

How do you redirect a www subdomain to an apex (naked) domain using Route53 and CloudFront?
Please note I am not using S3.
My site is hosted behind an ELB on the AWS ECS service.
I've tried to create a Record Set with the following settings:
- Name: www
- Type: CNAME - Canonical name
- Alias: No
- TTL (Seconds): 300
- Value: example.com
In CloudFront I have only the example.com apex whitelisted. As a result, the request is blocked.
I've also tried adding the www.example.com entry in CloudFront and the site resolves, however, the browser is not redirected example.com
AWS have introduced CloudFront functions which can manipulate the requests and responses that flow through CloudFront.
To redirect a www subdomain to the apex domain you can use the following viewer request function:
function handler(event) {
var request = event.request;
var headers = request.headers;
var host = request.headers.host.value;
if (host.startsWith('www')) {
var response = {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
location: {
value: 'https://' + host.replace('www.', ''),
},
},
};
return response;
}
return request;
}
In order for this function to work the CloudFront distribution needs to be configured with both the www subdomain and the apex domain. You will also need to configure Route 53 with both the subdomain and apex domain.
Using S3 for the redirect is not possible for domains (such as .dev) where the entire gTLD has been included in the HSTS preload-list because S3 website do not support https.
If you are considering to redirect using CloudFront and Route53, currently you have to write an Edge Lambda for HTTP Response Generation to Redirect.