Revised terms and privacy consent dialog, analytics hooks (#1426)

* revised terms and privacy consent

* reorg code

* fix conditional

* Overlay reflects un-dissmissable state

* add inline scripts, and consent callback

* add csp_directive config hook

* revert config.yaml

* fix logic error

Co-authored-by: Colin Megill <colinmegill@gmail.com>
This commit is contained in:
Bruce Martin
2020-04-28 14:21:53 -07:00
committed by GitHub
co-authored by Colin Megill
parent 666e6d9849
commit 05fcdaf93c
7 changed files with 184 additions and 48 deletions
+39 -8
View File
@@ -2,11 +2,14 @@
import sys
import os
import hashlib
import base64
from flask import json
import logging
from flask_talisman import Talisman
import boto3
if os.path.isdir("/opt/python/log"):
# This is the standard location where Amazon EC2 instances store the application logs.
logging.basicConfig(
@@ -54,24 +57,32 @@ class WSGIServer(Server):
@staticmethod
def _before_adding_routes(app, app_config):
script_hashes, style_hashes = WSGIServer.load_csp_hashes(app)
script_hashes, style_hashes = WSGIServer.get_csp_hashes(app, app_config)
csp = {
"default-src": "'self'",
"default-src": ["'self'"],
"script-src": ["'unsafe-eval'", "'unsafe-inline'"] + script_hashes,
"img-src": ["'self'", "data:"],
"object-src": "'none'",
"base-uri": "'none'",
"upgrade-insecure-requests": "",
"frame-ancestors": "'none'",
"require-trusted-types-for": "'script'",
"object-src": ["'none'"],
"base-uri": ["'none'"],
"upgrade-insecure-requests": [""],
"frame-ancestors": ["'none'"],
"require-trusted-types-for": ["'script'"],
}
if len(style_hashes) > 0:
csp["style-src"] = style_hashes
if app_config.server__inline_scripts:
csp["script-src"].append("'strict-dynamic'")
if app_config.server__csp_directives:
for k, v in app_config.server__csp_directives.items():
if not isinstance(v, list):
v = [v]
csp[k] = csp.get(k, []) + v
Talisman(app, force_https=app_config.server__force_https, frame_options="DENY", content_security_policy=csp)
@staticmethod
def load_csp_hashes(app):
def load_static_csp_hashes(app):
csp_hashes = None
try:
with app.open_resource("../common/web/csp-hashes.json") as f:
@@ -88,6 +99,26 @@ class WSGIServer(Server):
return (script_hashes, style_hashes)
@staticmethod
def compute_inline_scp_hashes(app, app_config):
inline_scripts = app_config.server__inline_scripts
hashes = []
for script in inline_scripts:
with app.open_resource(f"../common/web/templates/{script}") as f:
content = f.read()
# we use jinja2 template include, which trims final newline if present.
if content[-1] == 0x0A:
content = content[0:-1]
hash = base64.b64encode(hashlib.sha256(content).digest())
hashes.append(f"'sha256-{hash.decode('utf-8')}'")
return hashes
@staticmethod
def get_csp_hashes(app, app_config):
script_hashes, style_hashes = WSGIServer.load_static_csp_hashes(app)
script_hashes += WSGIServer.compute_inline_scp_hashes(app, app_config)
return (script_hashes, style_hashes)
try:
app_config = AppConfig()