Skip to content

Commit

Permalink
Disable source interface when Trusty is end-of-life
Browse files Browse the repository at this point in the history
If the underlying OS is Ubuntu 14.04 (Trusty) and the date for Trusty's end-of-life has passed, we should shortcut the source interface application logic to display an internationalized page indicating that the source interface has been disabled, to preserve the security and anonymity of sources.
  • Loading branch information
emkll authored and kushaldas committed Sep 25, 2019
1 parent b0ffc2b commit 04b2f6c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@
/var/www/securedrop/source_app/api.pyc rw,
/var/www/securedrop/source_app/decorators.py r,
/var/www/securedrop/source_app/decorators.pyc rw,
/var/www/securedrop/source_app/disable.py r,
/var/www/securedrop/source_app/disable.pyc rw,
/var/www/securedrop/source_app/forms.py r,
/var/www/securedrop/source_app/forms.pyc rw,
/var/www/securedrop/source_app/info.py r,
Expand All @@ -211,6 +213,7 @@
/var/www/securedrop/source_templates/banner_warning_flashed.html r,
/var/www/securedrop/source_templates/base.html r,
/var/www/securedrop/source_templates/error.html r,
/var/www/securedrop/source_templates/disabled.html r,
/var/www/securedrop/source_templates/first_submission_flashed_message.html r,
/var/www/securedrop/source_templates/flashed.html r,
/var/www/securedrop/source_templates/generate.html r,
Expand Down
5 changes: 4 additions & 1 deletion securedrop/source_app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from db import db
from models import Source
from request_that_secures_file_uploads import RequestThatSecuresFileUploads
from source_app import main, info, api
from source_app import main, info, api, disable
from source_app.decorators import ignore_static
from source_app.utils import logged_in
from store import Storage
Expand Down Expand Up @@ -115,6 +115,9 @@ def setup_i18n():
g.html_lang = i18n.locale_to_rfc_5646(g.locale)
g.locales = i18n.get_locale2name()

# Disables the app if the server is running Trusty past its EOL date.
disable.disable_app(app)

@app.before_request
@ignore_static
def check_tor2web():
Expand Down
17 changes: 17 additions & 0 deletions securedrop/source_app/disable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from datetime import date
from flask import render_template
from source_app.decorators import ignore_static
import platform

XENIAL_VER = "16.04"
TRUSTY_DISABLE_DATE = date(2019, 4, 30)


def disable_app(app):

@app.before_request
@ignore_static
def disable_ui():
if(platform.linux_distribution()[1] != XENIAL_VER and
date.today() > TRUSTY_DISABLE_DATE):
return render_template('disabled.html')
7 changes: 7 additions & 0 deletions securedrop/source_templates/disabled.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block body %}
<h1>{{ gettext("We're sorry, our SecureDrop is currently offline.") }}</h1>

<p>{{ gettext("Please try again later. Check our website for more information.") }}</p>

{% endblock %}
58 changes: 58 additions & 0 deletions securedrop/tests/test_source.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import gzip
import json
import platform
import re
import subprocess

Expand All @@ -13,14 +14,21 @@
import utils
import version

from datetime import date
from db import db
from models import Source, Reply
from source_app import main as source_app_main
from source_app import api as source_app_api
from source_app import disable as source_app_disable
from utils.db_helper import new_codename
from utils.instrument import InstrumentedApp

overly_long_codename = 'a' * (Source.MAX_CODENAME_LEN + 1)
TRUSTY_DISABLED_ENDPOINTS = ['main.index', 'main.lookup', 'main.generate', 'main.login',
'info.download_journalist_pubkey', 'info.tor2web_warning',
'info.recommend_tor_browser', 'info.why_download_journalist_pubkey']
STATIC_ASSETS = ['css/source.css', 'i/custom_logo.png', 'i/font-awesome/fa-globe-black.png',
'i/favicon.png']


def test_page_not_found(source_app):
Expand Down Expand Up @@ -696,3 +704,53 @@ def test_source_can_only_delete_own_replies(source_app):

reply = Reply.query.filter_by(filename=filename).one()
assert reply.deleted_by_source


def test_source_disabled_when_trusty_is_eol(config, source_app):
with patch.object(source_app_api.platform, "linux_distribution") as mocked_platform:
mocked_platform.return_value = ("Ubuntu", "14.04", "Trusty")

with source_app.test_client() as app:
source_app_disable.TRUSTY_DISABLE_DATE = date(2001, 1, 1)

assert platform.linux_distribution()[1] == "14.04"
for endpoint in TRUSTY_DISABLED_ENDPOINTS:
resp = app.get(url_for(endpoint))
assert resp.status_code == 200
text = resp.data.decode('utf-8')
assert "We're sorry, our SecureDrop is currently offline." in text
# Ensure static assets are properly served
for asset in STATIC_ASSETS:
resp = app.get(url_for('static', filename=asset))
assert resp.status_code == 200
text = resp.data.decode('utf-8')
assert "We're sorry, our SecureDrop is currently offline." not in text


def test_source_not_disabled_before_trusty_eol(config, source_app):
with patch.object(source_app_api.platform, "linux_distribution") as mocked_platform:
mocked_platform.return_value = ("Ubuntu", "14.04", "Trusty")

with source_app.test_client() as app:
source_app_disable.TRUSTY_DISABLE_DATE = date(2097, 1, 1)
assert platform.linux_distribution()[1] == "14.04"
for endpoint in TRUSTY_DISABLED_ENDPOINTS:
resp = app.get(url_for(endpoint), follow_redirects=True)
assert resp.status_code == 200
text = resp.data.decode('utf-8')
assert "We're sorry, our SecureDrop is currently offline." not in text


def test_source_not_disabled_xenial(config, source_app):
with patch.object(source_app_api.platform, "linux_distribution") as mocked_platform:
mocked_platform.return_value = ("Ubuntu", "16.04", "Xenial")

with source_app.test_client() as app:
source_app_disable.TRUSTY_DISABLE_DATE = date(2001, 1, 1)

assert platform.linux_distribution()[1] == "16.04"
for endpoint in TRUSTY_DISABLED_ENDPOINTS:
resp = app.get(url_for(endpoint), follow_redirects=True)
assert resp.status_code == 200
text = resp.data.decode('utf-8')
assert "We're sorry, our SecureDrop is currently offline." not in text

0 comments on commit 04b2f6c

Please sign in to comment.