SSL certificates and https for AWS hosted django site - django

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

Related

aws express TIMED OUT on port 443 https

I have configured Hosted zones in Route 53 with external domaine.
I have upload and deploy app express with Elastic Beanstalk.
const express = require("express")
const cors = require('cors');
const app = express()
const PORT = process.env.PORT || 8000
connection()
app.use(cors({
origin: '*'
}));
app.get('/', (req, res) => {
res.send('Hello World')
})
app.listen(PORT, () => console.log(`Listen on port ${PORT}`))
module.exports = app
I have created AWS Certificate Manager with success.
In Elastic Beanstalk > Configuration > Load balancer > add listener :
443 | HTTPS : selected my certification
When i make request with http protocol (port 80) that work.
But when i make request with https, i have error timeout.
for information my app work in Heroku with https.
EDIT:
the problem came from Hosted zones. thank for your help

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

HTTP to HTTPS with health link on Elastic Beanstalk using 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.

using AWS Elastic search with VPC endpoint django haystack

I want to use AWS Elastic-search service with my django application which is running on EC2 instance.
For that I use the settings -
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine',
'URL': 'https://vpc-ES-CLUSTER.ap-south-1.es.amazonaws.com:9200/',
'INDEX_NAME': 'haystack',
'INCLUDE_SPELLING':True,
},
}
I am not even able to set the connection. Here I am getting this error -
raise ConnectionError('N/A', str(e), e)
elasticsearch.exceptions.ConnectionError: ConnectionError((, 'Connection to vpc-ES-CLUSTER.ap-south-1.es.amazonaws.com timed out. (connect timeout=10)')) caused by: ConnectTimeoutError((, 'Connection to vpc-ES-CLUSTER.ap-south-1.es.amazonaws.com timed out. (connect timeout=10)'))
I have updated the access policy to allow the user for edit and list, also in security group add the port 9200 TCP rule. How to connect ec2 with elastic search using VPC.
It is working on 443 port, use
'URL': 'https://vpc-ES-CLUSTER.ap-south-1.es.amazonaws.com:443/',
and in security groups add 443 open port.

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.