Skip to content

Commit

Permalink
add server os eol warning
Browse files Browse the repository at this point in the history
  • Loading branch information
Allie Crevier committed Feb 17, 2021
1 parent a21aae2 commit 4c56f48
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 13 deletions.
9 changes: 7 additions & 2 deletions securedrop/journalist_app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
JournalistInterfaceSessionInterface,
cleanup_expired_revoked_tokens)
from models import InstanceConfig, Journalist
from server_os import is_os_near_eol, is_os_past_eol
from store import Storage

import typing
Expand Down Expand Up @@ -53,8 +54,7 @@ def create_app(config: 'SDConfig') -> Flask:
app.config['SQLALCHEMY_DATABASE_URI'] = config.DATABASE_URI
db.init_app(app)

def _url_exists(u: str) -> bool:
return path.exists(path.join(config.SECUREDROP_DATA_ROOT, u))
app.config.update(OS_PAST_EOL=is_os_past_eol(), OS_NEAR_EOL=is_os_near_eol())

# TODO: Attaching a Storage dynamically like this disables all type checking (and
# breaks code analysis tools) for code that uses current_app.storage; it should be refactored
Expand Down Expand Up @@ -157,6 +157,11 @@ def setup_g() -> 'Optional[Response]':
else:
g.organization_name = gettext('SecureDrop')

if app.config["OS_PAST_EOL"]:
g.show_os_past_eol_warning = True
elif app.config["OS_NEAR_EOL"]:
g.show_os_near_eol_warning = True

if request.path.split('/')[1] == 'api':
pass # We use the @token_required decorator for the API endpoints
else: # We are not using the API
Expand Down
20 changes: 9 additions & 11 deletions securedrop/journalist_templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@
<body>

{% if g.user %}
{% if g.show_v2_onion_eol_warning %}
<div id="v2-onion-eol" class="alert-banner">
<img src="{{ url_for('static', filename='i/bang-circle.png') }}" width="20" height="20"> {{ gettext('<strong>Update Required</strong>&nbsp;&nbsp;Set up v3 Onion Services before April 30 to keep your SecureDrop servers online. Please contact your administrator. <a href="//securedrop.org/v2-onion-eol" rel="noreferrer">Learn More</a>') }}
</div>
{% endif %}

{% if g.show_v2_onion_migration_warning %}
<div id="v2-complete-migration" class="alert-banner">
<img src="{{ url_for('static', filename='i/bang-circle.png') }}" width="20" height="20"> {{ gettext('<strong>Update Required</strong>&nbsp;&nbsp;Complete the v3 Onion Services setup before April 30. Please contact your administrator. <a href="//securedrop.org/v2-onion-eol" rel="noreferrer">Learn More</a>') }}
</div>
{% endif %}
{% if g.show_os_past_eol_warning %}
<div id="os-past-eol" class="alert-banner">
<img src="{{ url_for('static', filename='i/bang-circle.png') }}" width="20" height="20"> {{ gettext ('<strong>Critical Security:</strong>&nbsp;&nbsp;The operating system used by your SecureDrop servers has reached its end-of-life. A manual update is required to re-enable the Source Interface and remain safe. Please contact your administrator. <a href="//securedrop.org/xenial-eol" rel="noreferrer">Learn More</a>') }}
</div>
{% elif g.show_os_near_eol_warning %}
<div id="os-near-eol" class="alert-banner">
<img src="{{ url_for('static', filename='i/bang-circle.png') }}" width="20" height="20"> {{ gettext ('<strong>Critical Security:</strong>&nbsp;&nbsp;The operating system used by your SecureDrop servers is approaching its end-of-life on April 30, 2021. A manual update is urgently required to remain safe. Please contact your adminstrator. <a href="//securedrop.org/xenial-eol" rel="noreferrer">Learn More</a>') }}
</div>
{% endif %}

<div id="logout">
{{ gettext('Logged on as') }} <a href="{{ url_for('account.edit') }}" id="link-edit-account">{{ g.user.username }}</a> |
Expand Down
59 changes: 59 additions & 0 deletions securedrop/tests/test_journalist.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,65 @@ def _login_user(app, username, password, otp_secret):
assert hasattr(g, 'user') # ensure logged in


def test_user_sees_os_warning_if_server_past_eol(config, journalist_app, test_journo):
journalist_app.config.update(OS_PAST_EOL=True, OS_NEAR_EOL=False)
with journalist_app.test_client() as app:
_login_user(
app, test_journo["username"], test_journo["password"], test_journo["otp_secret"]
)

resp = app.get(url_for("main.index"))

text = resp.data.decode("utf-8")
assert 'id="os-past-eol"' in text, text
assert 'id="os-near-eol"' not in text, text


def test_user_sees_os_warning_if_server_past_eol_sanity_check(config, journalist_app, test_journo):
"""
Sanity check (both conditions cannot be True but test guard against developer error)
"""
journalist_app.config.update(OS_PAST_EOL=True, OS_NEAR_EOL=True)
with journalist_app.test_client() as app:
_login_user(
app, test_journo["username"], test_journo["password"], test_journo["otp_secret"]
)

resp = app.get(url_for("main.index"))

text = resp.data.decode("utf-8")
assert 'id="os-past-eol"' in text, text
assert 'id="os-near-eol"' not in text, text


def test_user_sees_os_warning_if_server_close_to_eol(config, journalist_app, test_journo):
journalist_app.config.update(OS_PAST_EOL=False, OS_NEAR_EOL=True)
with journalist_app.test_client() as app:
_login_user(
app, test_journo["username"], test_journo["password"], test_journo["otp_secret"]
)

resp = app.get(url_for("main.index"))

text = resp.data.decode("utf-8")
assert 'id="os-past-eol"' not in text, text
assert 'id="os-near-eol"' in text, text


def test_user_does_not_see_os_warning_if_server_is_current(config, journalist_app, test_journo):
journalist_app.config.update(OS_PAST_EOL=False, OS_NEAR_EOL=False)
with journalist_app.test_client() as app:
_login_user(
app, test_journo["username"], test_journo["password"], test_journo["otp_secret"]
)

resp = app.get(url_for("main.index"))

text = resp.data.decode("utf-8")
assert 'id="os-past-eol"' not in text, text
assert 'id="os-near-eol"' not in text, text


def test_user_with_whitespace_in_username_can_login(journalist_app):
# Create a user with whitespace at the end of the username
with journalist_app.app_context():
Expand Down

0 comments on commit 4c56f48

Please sign in to comment.