Skip to content

Commit

Permalink
Merge pull request #6742 from freedomofpress/6741-wsgi
Browse files Browse the repository at this point in the history
Fix app creation in source.wsgi, add regression test
  • Loading branch information
zenmonkeykstop authored Feb 8, 2023
2 parents ce70c00 + 193b8d1 commit d5f4417
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
src: source.wsgi.logging
dest: /var/www/source.wsgi
owner: "root"
mode: "0640"
mode: "0644"
tags:
- apache
2 changes: 1 addition & 1 deletion molecule/testinfra/app/test_appenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_app_wsgi(host):
f = host.file("/var/www/source.wsgi")
with host.sudo():
assert f.is_file
assert f.mode == 0o640
assert f.mode == 0o644
assert f.user == "root"
assert f.group == "root"
assert f.contains("^import logging$")
Expand Down
33 changes: 33 additions & 0 deletions molecule/testinfra/app/test_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Basic smoke tests that verify the apps are functioning as expected
"""
import pytest
import testutils

sdvars = testutils.securedrop_test_vars
testinfra_hosts = [sdvars.app_hostname]


@pytest.mark.parametrize(
"name,url,curl_flags",
(
# We pass -L to follow the redirect from / to /login
("journalist", "http://localhost:8080/", "L"),
("source", "http://localhost:80/", ""),
),
)
def test_interface_up(host, name, url, curl_flags):
"""
Ensure the respective interface is up with HTTP 200 if not, we try our
best to grab the error log and print it via an intentionally failed
assertion.
"""
response = host.run(f"curl -{curl_flags}i {url}").stdout
if "200 OK" not in response:
# Try to grab the log and print it via a failed assertion
with host.sudo():
f = host.file(f"/var/log/apache2/{name}-error.log")
if f.exists:
assert "nopenopenope" in f.content_string
assert "200 OK" in response
assert "Powered by" in response
1 change: 1 addition & 0 deletions securedrop/journalist.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from sdconfig import SecureDropConfig

config = SecureDropConfig.get_current()
# app is imported by journalist.wsgi
app = create_app(config)


Expand Down
6 changes: 4 additions & 2 deletions securedrop/source.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from sdconfig import SecureDropConfig
from source_app import create_app

config = SecureDropConfig.get_current()
# app is imported by source.wsgi
app = create_app(config)

if __name__ == "__main__": # pragma: no cover
config = SecureDropConfig.get_current()
app = create_app(config)
debug = getattr(config, "env", "prod") != "prod"
# nosemgrep: python.flask.security.audit.app-run-param-config.avoid_app_run_with_bad_host
app.run(debug=debug, host="0.0.0.0", port=8080) # nosec
17 changes: 10 additions & 7 deletions securedrop/source_app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,15 @@ def internal_error(error: werkzeug.exceptions.HTTPException) -> Tuple[str, int]:
# Obscure the creation time of source private keys by touching them all
# on startup.
private_keys = config.GPG_KEY_DIR / "private-keys-v1.d"
now = time.time()
for entry in os.scandir(private_keys):
if not entry.is_file() or not entry.name.endswith(".key"):
continue
os.utime(entry.path, times=(now, now))
# So the ctime is also updated
os.chmod(entry.path, entry.stat().st_mode)
# The folder may not exist yet in some dev/testing setups,
# and if it doesn't exist there's no mtime to obscure.
if private_keys.is_dir():
now = time.time()
for entry in os.scandir(private_keys):
if not entry.is_file() or not entry.name.endswith(".key"):
continue
os.utime(entry.path, times=(now, now))
# So the ctime is also updated
os.chmod(entry.path, entry.stat().st_mode)

return app
22 changes: 22 additions & 0 deletions securedrop/tests/test_wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import subprocess
import sys
from pathlib import Path

import pytest


@pytest.mark.parametrize("filename", ("journalist.wsgi", "source.wsgi"))
def test_wsgi(filename):
"""
Verify that all setup code and imports in the wsgi files work
This is slightly hacky because it executes the wsgi files using
the current virtualenv, and we hack the paths so it works out.
"""
sd_dir = Path(__file__).parent.parent
wsgi = sd_dir / "debian/app-code/var/www" / filename
python_path = os.getenv("PYTHONPATH", "")
subprocess.check_call(
[sys.executable, str(wsgi)], env={"PYTHONPATH": f"{python_path}:{sd_dir}"}
)

0 comments on commit d5f4417

Please sign in to comment.