CSP: Add reporting endpoint

This commit is contained in:
Raphael Michel
2017-09-28 18:43:45 +02:00
parent c030bd35ca
commit 29b157f287
5 changed files with 41 additions and 1 deletions

View File

@@ -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']))

View File

@@ -32,6 +32,7 @@ class EventSlugBlacklistValidator(BlacklistValidator):
'__debug__',
'api',
'events',
'csp_report',
]
@@ -51,4 +52,5 @@ class OrganizerSlugBlacklistValidator(BlacklistValidator):
'__debug__',
'about',
'api',
'csp_report',
]

View 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()

View File

@@ -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,

View File

@@ -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')
]