diff --git a/ansible/roles/swagger_ui/files/index.css b/ansible/roles/swagger_ui/files/index.css
new file mode 100644
index 0000000..d99b570
--- /dev/null
+++ b/ansible/roles/swagger_ui/files/index.css
@@ -0,0 +1,17 @@
+html
+{
+ box-sizing: border-box;
+ overflow: -moz-scrollbars-vertical;
+ overflow-y: scroll;
+}
+*,
+*:before,
+*:after
+{
+ box-sizing: inherit;
+}
+
+body {
+ margin:0;
+ background: #fafafa;
+}
\ No newline at end of file
diff --git a/tildes/static/swagger-ui-tildes/index.html b/ansible/roles/swagger_ui/files/index.html
similarity index 77%
rename from tildes/static/swagger-ui-tildes/index.html
rename to ansible/roles/swagger_ui/files/index.html
index fe2954f..1cd1014 100644
--- a/tildes/static/swagger-ui-tildes/index.html
+++ b/ansible/roles/swagger_ui/files/index.html
@@ -4,25 +4,7 @@
Swagger UI
-
+
diff --git a/ansible/roles/swagger_ui/tasks/main.yml b/ansible/roles/swagger_ui/tasks/main.yml
index ccc25be..f1b03b6 100644
--- a/ansible/roles/swagger_ui/tasks/main.yml
+++ b/ansible/roles/swagger_ui/tasks/main.yml
@@ -7,3 +7,18 @@
group: "{{ app_username }}"
mode: 0755
remote_src: true
+
+- name: Copy our own custom swagger-ui web assets
+ block:
+ - copy:
+ src: "index.html"
+ dest: "{{ app_dir }}/static/swagger-ui/index.html"
+ owner: "{{ app_username }}"
+ group: "{{ app_username }}"
+ mode: 0644
+ - copy:
+ src: "index.css"
+ dest: "{{ app_dir }}/static/swagger-ui/index.css"
+ owner: "{{ app_username }}"
+ group: "{{ app_username }}"
+ mode: 0644
diff --git a/tildes/tildes/tweens.py b/tildes/tildes/tweens.py
index 9031c1f..a4c3879 100644
--- a/tildes/tildes/tweens.py
+++ b/tildes/tildes/tweens.py
@@ -3,6 +3,7 @@
"""Contains Pyramid "tweens", used to insert additional logic into request-handling."""
+import secrets
from collections.abc import Callable
from time import time
@@ -106,8 +107,35 @@ def theme_cookie_tween_factory(handler: Callable, registry: Registry) -> Callabl
return theme_cookie_tween
+def inject_csp_header_tween_factory(handler: Callable, registry: Registry) -> Callable:
+ # pylint: disable=unused-argument
+ """Return a tween function that sets a CSP nonce (for Swagger UI)."""
+
+ def inject_csp_header_tween(request: Request) -> Response:
+ """Generate a CSP nonce and add it to the request and response.
+
+ Only apply to specific routes defined here, to minimize performance overhead.
+ """
+ nonce = None
+ route_name = request.matched_route.name if request.matched_route else None
+ if route_name == "pyramid_openapi3.explorer":
+ nonce = secrets.token_urlsafe(16)
+ request.csp_nonce = nonce
+
+ response = handler(request)
+
+ if nonce:
+ response.headers["Content-Security-Policy"] = (
+ f"script-src 'self' 'nonce-{nonce}'"
+ )
+ return response
+
+ return inject_csp_header_tween
+
+
def includeme(config: Configurator) -> None:
"""Attach Tildes tweens to the Pyramid config."""
config.add_tween("tildes.tweens.http_method_tween_factory")
config.add_tween("tildes.tweens.metrics_tween_factory")
config.add_tween("tildes.tweens.theme_cookie_tween_factory")
+ config.add_tween("tildes.tweens.inject_csp_header_tween_factory")