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")