mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
CSP: Add reporting endpoint
This commit is contained in:
@@ -192,6 +192,7 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
# single-sign-on this can be nearly anything so we cannot really restrict
|
||||
# this. However, we'll restrict it to HTTPS.
|
||||
'form-action': ["{dynamic}", "https:"],
|
||||
'report-uri': ["/csp_report/"],
|
||||
}
|
||||
if 'Content-Security-Policy' in resp:
|
||||
_merge_csp(h, _parse_csp(resp['Content-Security-Policy']))
|
||||
|
||||
@@ -32,6 +32,7 @@ class EventSlugBlacklistValidator(BlacklistValidator):
|
||||
'__debug__',
|
||||
'api',
|
||||
'events',
|
||||
'csp_report',
|
||||
]
|
||||
|
||||
|
||||
@@ -51,4 +52,5 @@ class OrganizerSlugBlacklistValidator(BlacklistValidator):
|
||||
'__debug__',
|
||||
'about',
|
||||
'api',
|
||||
'csp_report',
|
||||
]
|
||||
|
||||
25
src/pretix/base/views/csp.py
Normal file
25
src/pretix/base/views/csp.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from django.http import (
|
||||
HttpResponseBadRequest, HttpResponse)
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
logger = logging.getLogger('pretix.security.csp')
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
def csp_report(request):
|
||||
try:
|
||||
body = json.loads(request.body.decode())
|
||||
logger.warning(
|
||||
'CSP violation at {r[document-uri]}\n'
|
||||
'Referer: {r[referrer]}\n'
|
||||
'Blocked: {r[blocked-uri]}\n'
|
||||
'Violated: {r[violated-directive]}\n'
|
||||
'Original polity: {r[original-policy]}'.format(r=body['csp-report'])
|
||||
)
|
||||
except (ValueError, KeyError) as e:
|
||||
logger.exception('CSP report failed')
|
||||
return HttpResponseBadRequest()
|
||||
return HttpResponse()
|
||||
@@ -451,6 +451,12 @@ LOGGING = {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'default'
|
||||
},
|
||||
'csp_file': {
|
||||
'level': loglevel,
|
||||
'class': 'logging.FileHandler',
|
||||
'filename': os.path.join(LOG_DIR, 'csp.log'),
|
||||
'formatter': 'default'
|
||||
},
|
||||
'file': {
|
||||
'level': loglevel,
|
||||
'class': 'logging.FileHandler',
|
||||
@@ -474,6 +480,11 @@ LOGGING = {
|
||||
'level': loglevel,
|
||||
'propagate': True,
|
||||
},
|
||||
'pretix.security.csp': {
|
||||
'handlers': ['csp_file'],
|
||||
'level': loglevel,
|
||||
'propagate': False,
|
||||
},
|
||||
'django.security': {
|
||||
'handlers': ['file', 'console', 'mail_admins'],
|
||||
'level': loglevel,
|
||||
|
||||
@@ -5,7 +5,7 @@ from django.views.generic import RedirectView
|
||||
import pretix.control.urls
|
||||
import pretix.presale.urls
|
||||
|
||||
from .base.views import cachedfiles, health, js_catalog, metrics, redirect
|
||||
from .base.views import cachedfiles, health, js_catalog, metrics, redirect, csp
|
||||
|
||||
base_patterns = [
|
||||
url(r'^download/(?P<id>[^/]+)/$', cachedfiles.DownloadView.as_view(),
|
||||
@@ -16,6 +16,7 @@ base_patterns = [
|
||||
url(r'^jsi18n/(?P<lang>[a-zA-Z-_]+)/$', js_catalog.js_catalog, name='javascript-catalog'),
|
||||
url(r'^metrics$', metrics.serve_metrics,
|
||||
name='metrics'),
|
||||
url(r'^csp_report/$', csp.csp_report, name='csp.report'),
|
||||
url(r'^api/v1/', include('pretix.api.urls', namespace='api-v1')),
|
||||
url(r'^api/$', RedirectView.as_view(url='/api/v1/'), name='redirect-api-version')
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user