forked from CGM_Public/pretix_original
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
|
# single-sign-on this can be nearly anything so we cannot really restrict
|
||||||
# this. However, we'll restrict it to HTTPS.
|
# this. However, we'll restrict it to HTTPS.
|
||||||
'form-action': ["{dynamic}", "https:"],
|
'form-action': ["{dynamic}", "https:"],
|
||||||
|
'report-uri': ["/csp_report/"],
|
||||||
}
|
}
|
||||||
if 'Content-Security-Policy' in resp:
|
if 'Content-Security-Policy' in resp:
|
||||||
_merge_csp(h, _parse_csp(resp['Content-Security-Policy']))
|
_merge_csp(h, _parse_csp(resp['Content-Security-Policy']))
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class EventSlugBlacklistValidator(BlacklistValidator):
|
|||||||
'__debug__',
|
'__debug__',
|
||||||
'api',
|
'api',
|
||||||
'events',
|
'events',
|
||||||
|
'csp_report',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -51,4 +52,5 @@ class OrganizerSlugBlacklistValidator(BlacklistValidator):
|
|||||||
'__debug__',
|
'__debug__',
|
||||||
'about',
|
'about',
|
||||||
'api',
|
'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',
|
'class': 'logging.StreamHandler',
|
||||||
'formatter': 'default'
|
'formatter': 'default'
|
||||||
},
|
},
|
||||||
|
'csp_file': {
|
||||||
|
'level': loglevel,
|
||||||
|
'class': 'logging.FileHandler',
|
||||||
|
'filename': os.path.join(LOG_DIR, 'csp.log'),
|
||||||
|
'formatter': 'default'
|
||||||
|
},
|
||||||
'file': {
|
'file': {
|
||||||
'level': loglevel,
|
'level': loglevel,
|
||||||
'class': 'logging.FileHandler',
|
'class': 'logging.FileHandler',
|
||||||
@@ -474,6 +480,11 @@ LOGGING = {
|
|||||||
'level': loglevel,
|
'level': loglevel,
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
|
'pretix.security.csp': {
|
||||||
|
'handlers': ['csp_file'],
|
||||||
|
'level': loglevel,
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
'django.security': {
|
'django.security': {
|
||||||
'handlers': ['file', 'console', 'mail_admins'],
|
'handlers': ['file', 'console', 'mail_admins'],
|
||||||
'level': loglevel,
|
'level': loglevel,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from django.views.generic import RedirectView
|
|||||||
import pretix.control.urls
|
import pretix.control.urls
|
||||||
import pretix.presale.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 = [
|
base_patterns = [
|
||||||
url(r'^download/(?P<id>[^/]+)/$', cachedfiles.DownloadView.as_view(),
|
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'^jsi18n/(?P<lang>[a-zA-Z-_]+)/$', js_catalog.js_catalog, name='javascript-catalog'),
|
||||||
url(r'^metrics$', metrics.serve_metrics,
|
url(r'^metrics$', metrics.serve_metrics,
|
||||||
name='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/v1/', include('pretix.api.urls', namespace='api-v1')),
|
||||||
url(r'^api/$', RedirectView.as_view(url='/api/v1/'), name='redirect-api-version')
|
url(r'^api/$', RedirectView.as_view(url='/api/v1/'), name='redirect-api-version')
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user