not-kennethreitz / flask-sslify Goto Github PK
View Code? Open in Web Editor NEWForce SSL on your Flask app.
Home Page: https://pypi.python.org/pypi/Flask-SSLify
License: BSD 2-Clause "Simplified" License
Force SSL on your Flask app.
Home Page: https://pypi.python.org/pypi/Flask-SSLify
License: BSD 2-Clause "Simplified" License
I'd like to add a criteria to the existing ones (app.debug, x-forwarded-proto, request.is_secure), which is to support local development. If the incoming request URL host name is "localhost" or 127.0.0.1, don't force SSL.
Objections / thoughts?
I am attempting to use flask-sslify==0.1.5 on Heroku with expeditedSSL. I have tried default, and other settings, such as sslify = SSLify(app, age=31536000, permanent=True, subdomains=True). However, each scan gives the same indication that HSTS is not fully working. It was working fine for another site until I upgraded to 0.1.5, and then when I did the earlier version 0.1.3 that had been working. Now, none of the versions are getting an A+ scan.
Any thoughts?
Thanks,
Glen
Site uses HSTS
HTTP Strict Transport Security (HSTS) is a HTTP response header that is set on your web application server. Supporting browsers read the header which contains an expiration max-age value and will NOT reconnect on a plain HTTP connection until the max-age value is exceeded. HSTS prevents a variety of attacks where an intermediary could disrupt or spoof connections.
You'll need to implement this in your application.
More HSTS information at: http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
It appears that requests other than GET
are converted to GET
requests... Example from my heroku log
Aug 30 08:43:18 app/router: at=info method=DELETE path="/v2/feed?source=test" host=app.herokuapp.com request_id=xxx fwd="xxx" dyno=web.1 connect=1ms service=11ms status=302 bytes=592 protocol=http
Aug 30 08:43:19 app/router: at=info method=GET path="/v2/feed?source=test" host=app.herokuapp.com request_id=xxx fwd="xxx" dyno=web.1 connect=1ms service=18ms status=200 bytes=15801 protocol=https
I used: http://myserver.com:8080/ and turned debug mode to False.
'app.run(host='0.0.0.0', port=8080, debug=False, ssl_context=context )'
The https server works properly. But it returns saying: unepectedly dropped the connection...
I have a minimal web app that works fine:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
app.run(host='localhost', port='1234')
I can enable https successfully (page views fine this way):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
app.run(host='localhost', port='1234', ssl_context='adhoc')
But, when I Flask-SSLify it:
from flask import Flask
from flask_sslify import SSLify
app = Flask(__name__)
sslify = SSLify(app)
@app.route('/')
def hello_world():
return 'Hello, World!'
app.run(host='localhost', port='1234')
...visiting https://localhost:1234 yields ERR_SSL_PROTOCOL_ERROR in Chrome and the server prints out a bunch of code 400, message Bad HTTP/0.9 request type
and code 400, message Bad request version
. The redirect appears to work properly though; when I visit http://localhost:1234, I am redirected to the https page and I see a "GET / HTTP/1.1" 302 -
on the server. What's going on here?
python --version
yields Python 2.7.13
yolk -V Flask-SSLify
yields Flask-SSLify 0.1.5
Are there any plans to migrate to/support python 3?
I'd kinda like a 301 instead of a 302. :o
Is my understanding correct that the 'skips' parameter only works for the request path, but not for the base URL?
For example there is no way to enforce SSL for:
But to skip:
Could you release version 0.1.6 of this package to PyPI?
The latest version on Pypi is 0.1.5 and it doesn't contain this commit that I need. Currently I have to specify URL to the commit in my requirements.txt, and the installation takes more time than with packages that can be downloaded directly from PyPI.
Thanks!
Hi,
This isn't a problem with SSLify. It is a design decision I'm faced with, but not one for which I have any experience.
I'm building a secure website on Amazon Elastic Beanstalk and have the option to terminate the SSL connection at the Elastic Load Balancer (and pass un-encrypted data over the amazon network to my app) or have the Elastic Load Balancer pass the encrypted data to my app.
I don't know the pro and cons of either approach, do you by chance have any advice? If not, any suggestions about where I should turn?
Thank you so much!
~Victor
This is more of a documentation and commitment thing - it's almost possible to use the extension on a Blueprint as-is, by simply doing SSLify(my_blueprint)
and working around the app.debug issue.
That seems to be a good usecase for the future (for example it may be convenient to only protect an admin area blueprint instead of the whole site).
There's not official API for extending blueprints that I know of. Maybe adding an init_blueprint() method would be a way to go?
This code:
request.headers.get('X-Forwarded-Proto', 'http') == 'https'
Really should be checking against the wsgi.url_scheme. Just trusting HTTP headers from the client is generally not the best idea. If yuo want to use X-Forwarded-Proto you can still remap them as necessary in a WSGI middleware.
I'm using basic auth. If the client requests with HTTP, are credentials sent in plain text before the redirect occurs?
This code:
request.headers.get('X-Forwarded-Proto', 'http') == 'https'
Really should be checking against the wsgi.url_scheme. Just trusting HTTP headers from the client is generally not the best idea. If yuo want to use X-Forwarded-Proto you can still remap them as necessary in a WSGI middleware.
When you get a chance can you update your tarball on PyPi to the same code you have on GitHub? It's a little bit behind (2012-11-16).
Currently, SSLify watches DEBUG to see if it should SSLify or not a request. However, it would be useful to be able to provide a more advanced criteria for per-request SSLification.
For example, using SSLify on Amazon Elastic Beanstalk, SSLify keeps trying to redirect the health checker, which results in failing checks. It would be nice to be able to add a "criteria" to the list of criteria in redirect_to_ssl, so that you could check to see if, for example, the user agent was the ELB Health Checker and the requested URL was the URL to be tested. Or even, just to exclude a URL from the SSLification.
If the maintainer would be open to such a patch, I'll submit it.
As glencarl mentioned in issue #42, the Expedited SSL scanner isn't picking up HSTS with v0.1.5 installed. This comes back to the Strict-Transport-Security
flag not being sent in the header, as illustrated below.
I believe this warrants opening a separate issue as it clarifies that it's not an issue with Expedited SSL's scanner but is in fact an issue with HSTS itself.
curl -D - https://myapp014.herokuapp.com | head -n 20
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
1HTTP/1.1 200 OK 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
Connection: keep-alive
Server: gunicorn/19.4.5
Date: Thu, 21 Apr 2016 14:07:37 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 8622
Strict-Transport-Security: max-age=31536000
Via: 1.1 vegur
curl -D - https://myapp015.herokuapp.com | head -n 20
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10HTTP/1.1 200 OK 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
Connection: keep-alive
Server: gunicorn/19.4.5
Date: Thu, 21 Apr 2016 14:09:16 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 8622
Via: 1.1 vegur
Hey,
Flask extensions must only store references to app if the app was passed to the constructor and should provide a init_app
function that allows the extension to be used with multiple apps.
Is there a problem that the STS header is also sent over an HTTP link on the first return?
See this line in para [7.2] at : http://tools.ietf.org/html/rfc6797:
_ "...An HSTS Host MUST NOT include the STS header field in HTTP responses
conveyed over non-secure transport."_
It seems that the "set_hsts_header" function should be modified to only set the header if the connection occurs over an https link. I am not 100% what the security issue is - but the standard does seem to require this. Does that seem correct to people?
Placing the SSLify(app, ..) command before another function definition decorated with "@app.before_request" makes my app produce 500 errors on http requests instead of redirecting, while working ok for https requests.
My other decorated func adds properties to the flask g object which in the error case aren't found later at request time, so I assume it isn't called.
Just placing the SSLify(..) after that decorated func resolves this issue, everything works. I assume this is a SSLify issue?
Since v0.1.5, any app using this extension with the app factory pattern crashes on startup because current_app
is being manipulated without an active application context.
This regression was introduced by #28.
Merging #32 should fix this issue.
I feel like it might make sense to support TESTING in addition to DEBUG:
http://flask.pocoo.org/docs/testing/
See also #19.
From the Wikipedia page on HSTS:
"Strict-Transport-Security headers must be sent via HTTPS responses only. Client implementations must not respect STS headers sent over non-HTTPS responses, or over HTTPS responses which are not using properly configured, trusted certificates. The following server configuration snippets should be within the context of an SSL site configuration block, and the code examples are intended to be within the context of HTTPS responses only."
So https://github.com/kennethreitz/flask-sslify/blob/6735984ce259aee0d042c9e36d5d79040ccd0319/flask_sslify.py#L54 should be returning HSTS-headers only for HTTPS responses.
I'm not sure what's the best criterium to decide whether the current response is secure in Flask, though. Ideas?
http://werkzeug.pocoo.org/docs/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
Based on commit history, there should be a tag that points to a5576e9.
Following instructions doesn't seem to redirect my traffic.
def app_factory():
app = Flask(__name__)
app.config.from_object('config')
if app.config['ENV'] == 'prod': # only trigger SSLify if the app is running on Heroku
sslify = SSLify(app)
After I push everything up:
(venv)โ heterogeneous git:(master) curl -I http://www.heterogeneous.co.uk
HTTP/1.1 200 OK
Connection: keep-alive
Server: gunicorn/19.6.0
Date: Sun, 06 Aug 2017 21:12:39 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 45089
Via: 1.1 vegur
Potential reasons:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.