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