From 1236f0054f4ad8763c7f24234d90ab63996daf54 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Tue, 1 Oct 2013 15:59:47 -0400 Subject: [PATCH 1/5] Try to add an HTTP->HTTPS redirect to the apache config. --- wsgi.conf | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/wsgi.conf b/wsgi.conf index 3671e593f..03645384f 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -6,26 +6,37 @@ WSGIRestrictEmbedded On WSGIPassAuthorization On + SetEnvIf X-Forwarded-Proto https HTTPS=1 -SetEnvIf X-Forwarded-Proto https HTTPS=1 + RewriteEngine On + # This will enable the Rewrite capabilities -Alias /static /opt/python/current/app/static/ - -Order allow,deny -Allow from all - + RewriteCond %{HTTPS} !=on + # This checks to make sure the connection is not already HTTPS + + RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] + # This rule will redirect users from their original location, to the same location but using HTTPS. + # i.e. http://www.example.com/foo/ to https://www.example.com/foo/ + # The leading slash is made optional so that this will work either in httpd.conf + # or .htaccess context + + Alias /static /opt/python/current/app/static/ + + Order allow,deny + Allow from all + -WSGIScriptAlias / /opt/python/current/app/application.py + WSGIScriptAlias / /opt/python/current/app/application.py - -Order allow,deny -Allow from all - + + Order allow,deny + Allow from all + -WSGIDaemonProcess wsgi processes=1 threads=15 display-name=%{GROUP} \ - python-path=/opt/python/current/app:/opt/python/run/venv/lib/python2.7/site-packages user=wsgi group=wsgi \ - home=/opt/python/current/app -WSGIProcessGroup wsgi + WSGIDaemonProcess wsgi processes=1 threads=15 display-name=%{GROUP} \ + python-path=/opt/python/current/app:/opt/python/run/venv/lib/python2.7/site-packages user=wsgi group=wsgi \ + home=/opt/python/current/app + WSGIProcessGroup wsgi From 536f6bb730b28bc8be04289b822aef9ef9fd1c64 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Tue, 1 Oct 2013 16:20:08 -0400 Subject: [PATCH 2/5] Redirect try 2. --- wsgi.conf | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/wsgi.conf b/wsgi.conf index 03645384f..e2efc0c76 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -9,16 +9,8 @@ WSGIPassAuthorization On SetEnvIf X-Forwarded-Proto https HTTPS=1 RewriteEngine On - # This will enable the Rewrite capabilities - - RewriteCond %{HTTPS} !=on - # This checks to make sure the connection is not already HTTPS - - RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] - # This rule will redirect users from their original location, to the same location but using HTTPS. - # i.e. http://www.example.com/foo/ to https://www.example.com/foo/ - # The leading slash is made optional so that this will work either in httpd.conf - # or .htaccess context + RewriteCond %{HTTP:X-Forwarded-Proto} !https + RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R] Alias /static /opt/python/current/app/static/ @@ -29,7 +21,6 @@ WSGIPassAuthorization On WSGIScriptAlias / /opt/python/current/app/application.py - Order allow,deny Allow from all From a3701304945288d4623de9947380781afc906a40 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Tue, 1 Oct 2013 16:28:40 -0400 Subject: [PATCH 3/5] Redirect try 3. --- wsgi.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsgi.conf b/wsgi.conf index e2efc0c76..d269b6912 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -10,7 +10,7 @@ WSGIPassAuthorization On RewriteEngine On RewriteCond %{HTTP:X-Forwarded-Proto} !https - RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R] + RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent] Alias /static /opt/python/current/app/static/ From 0cba17efe35f6938847f2d01a0eff5179d542fb4 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Tue, 1 Oct 2013 16:48:19 -0400 Subject: [PATCH 4/5] Try moving the redirect to the app layer. --- config.py | 2 ++ endpoints/web.py | 22 ++++++++++++++++++++++ wsgi.conf | 4 ---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/config.py b/config.py index 257171c89..f82844f8e 100644 --- a/config.py +++ b/config.py @@ -60,6 +60,7 @@ class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB): 'level': logging.DEBUG, 'format': LOG_FORMAT } + SECURE_REDIRECT = False class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): @@ -69,3 +70,4 @@ class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): 'level': logging.DEBUG, 'format': LOG_FORMAT, } + SECURE_REDIRECT = True diff --git a/endpoints/web.py b/endpoints/web.py index 64a77bef9..fb2dcdbf6 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -1,9 +1,11 @@ import logging +import urlparse from flask import (abort, send_file, redirect, request, url_for, render_template) from flask.ext.login import login_user, UserMixin, login_required, logout_user from flask.ext.principal import identity_changed, Identity, AnonymousIdentity +from functools import wraps from data import model from app import app, login_manager @@ -23,6 +25,20 @@ class _LoginWrappedDBUser(UserMixin): return unicode(self.db_user.username) +def secure_required(f): + @wraps(f) + def decorated_view(*args, **kwargs): + if (app.config['SECURE_REDIRECT'] and + request.environ['wsgi.url_scheme'] == 'http'): + + logger.debug('Redirecting http url to https.') + parsed = urlparse.urlparse(request.url) + location = urlparse.urlunparse(('https',) + parsed[1:]) + return redirect(location) + return f(*args, **kwargs) + return decorated_view + + @login_manager.user_loader def load_user(username): logger.debug('Loading user: %s' % username) @@ -34,6 +50,7 @@ def load_user(username): @app.route('/', methods=['GET']) +@secure_required def index(): return send_file('templates/index.html') @@ -50,11 +67,13 @@ def common_login(db_user): @app.route('/signin', methods=['GET']) +@secure_required def render_signin_page(): return render_template('signin.html') @app.route('/signin', methods=['POST']) +@secure_required def signin(): username = request.form['username'] password = request.form['password'] @@ -75,6 +94,7 @@ def signin(): @app.route('/confirm', methods=['GET']) +@secure_required def confirm_email(): code = request.values['code'] user = model.confirm_user_email(code) @@ -85,11 +105,13 @@ def confirm_email(): @app.route('/reset', methods=['GET']) +@secure_required def password_reset(): pass @app.route("/signout") +@secure_required @login_required def logout(): logout_user() diff --git a/wsgi.conf b/wsgi.conf index d269b6912..2109fa2dd 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -8,10 +8,6 @@ WSGIPassAuthorization On SetEnvIf X-Forwarded-Proto https HTTPS=1 - RewriteEngine On - RewriteCond %{HTTP:X-Forwarded-Proto} !https - RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent] - Alias /static /opt/python/current/app/static/ Order allow,deny From 540815b943b816b8040dce4079650ac8555b2d3a Mon Sep 17 00:00:00 2001 From: yackob03 Date: Tue, 1 Oct 2013 16:54:05 -0400 Subject: [PATCH 5/5] Revert "Try moving the redirect to the app layer." This reverts commit 0cba17efe35f6938847f2d01a0eff5179d542fb4. --- config.py | 2 -- endpoints/web.py | 22 ---------------------- wsgi.conf | 4 ++++ 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/config.py b/config.py index f82844f8e..257171c89 100644 --- a/config.py +++ b/config.py @@ -60,7 +60,6 @@ class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB): 'level': logging.DEBUG, 'format': LOG_FORMAT } - SECURE_REDIRECT = False class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): @@ -70,4 +69,3 @@ class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): 'level': logging.DEBUG, 'format': LOG_FORMAT, } - SECURE_REDIRECT = True diff --git a/endpoints/web.py b/endpoints/web.py index fb2dcdbf6..64a77bef9 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -1,11 +1,9 @@ import logging -import urlparse from flask import (abort, send_file, redirect, request, url_for, render_template) from flask.ext.login import login_user, UserMixin, login_required, logout_user from flask.ext.principal import identity_changed, Identity, AnonymousIdentity -from functools import wraps from data import model from app import app, login_manager @@ -25,20 +23,6 @@ class _LoginWrappedDBUser(UserMixin): return unicode(self.db_user.username) -def secure_required(f): - @wraps(f) - def decorated_view(*args, **kwargs): - if (app.config['SECURE_REDIRECT'] and - request.environ['wsgi.url_scheme'] == 'http'): - - logger.debug('Redirecting http url to https.') - parsed = urlparse.urlparse(request.url) - location = urlparse.urlunparse(('https',) + parsed[1:]) - return redirect(location) - return f(*args, **kwargs) - return decorated_view - - @login_manager.user_loader def load_user(username): logger.debug('Loading user: %s' % username) @@ -50,7 +34,6 @@ def load_user(username): @app.route('/', methods=['GET']) -@secure_required def index(): return send_file('templates/index.html') @@ -67,13 +50,11 @@ def common_login(db_user): @app.route('/signin', methods=['GET']) -@secure_required def render_signin_page(): return render_template('signin.html') @app.route('/signin', methods=['POST']) -@secure_required def signin(): username = request.form['username'] password = request.form['password'] @@ -94,7 +75,6 @@ def signin(): @app.route('/confirm', methods=['GET']) -@secure_required def confirm_email(): code = request.values['code'] user = model.confirm_user_email(code) @@ -105,13 +85,11 @@ def confirm_email(): @app.route('/reset', methods=['GET']) -@secure_required def password_reset(): pass @app.route("/signout") -@secure_required @login_required def logout(): logout_user() diff --git a/wsgi.conf b/wsgi.conf index 2109fa2dd..d269b6912 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -8,6 +8,10 @@ WSGIPassAuthorization On SetEnvIf X-Forwarded-Proto https HTTPS=1 + RewriteEngine On + RewriteCond %{HTTP:X-Forwarded-Proto} !https + RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent] + Alias /static /opt/python/current/app/static/ Order allow,deny