Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repos:
# the ruff's version line, it is used by test_pre_commit_ruff_version.py
# test case in order not to have to add a YAML library dependency just
# to test this version:
rev: v0.12.12 # ruff-pre-commit version
rev: v0.13.2 # ruff-pre-commit version
hooks:
# Run the linter
- id: ruff
Expand Down
8 changes: 5 additions & 3 deletions notification_importers/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import importlib
import logging

from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE
from csp.decorators import csp_update
from django.conf import settings
from django.contrib import admin, messages
Expand All @@ -11,8 +12,6 @@
from django_ilmoitin.admin import NotificationTemplateAdmin
from django_ilmoitin.models import NotificationTemplate

from palvelutarjotin.consts import CSP

from .notification_importer import (
AbstractNotificationImporter,
NotificationImporterException,
Expand Down Expand Up @@ -113,7 +112,10 @@ def _send_error_message(self, request, message):
# Acecpt CSP_UNSAFE_INLINE for the changeform view to allow
# the preview template to work correctly.
@csp_update(
SCRIPT_SRC=settings.CSP_SCRIPT_SRC + [CSP.UNSAFE_INLINE],
{
"script-src": settings.CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"]
+ [CSP_UNSAFE_INLINE],
}
)
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
return super().changeform_view(
Expand Down
13 changes: 0 additions & 13 deletions palvelutarjotin/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,3 @@
INVALID_TOKEN_ERROR = "INVALID_TOKEN_ERROR"
INVALID_STUDY_GROUP_UNIT_INFO_ERROR = "INVALID_STUDY_GROUP_UNIT_INFO_ERROR"
QUEUEING_NOT_ALLOWED_ERROR = "QUEUEING_NOT_ALLOWED_ERROR"


class CSP:
"""The “special” source values of 'self', 'unsafe-inline', 'unsafe-eval', 'none'
and hash-source ('sha256-...') must be quoted! e.g.: CSP_DEFAULT_SRC = ("'self'",).
Without quotes they will not work as intended.
Ref. https://django-csp.readthedocs.io/en/stable/configuration.html.
"""

SELF = "'self'"
NONE = "'none'"
UNSAFE_INLINE = "'unsafe-inline'"
UNSAFE_EVAL = "'unsafe-eval'"
49 changes: 21 additions & 28 deletions palvelutarjotin/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@

import environ
import sentry_sdk
from csp.constants import SELF as CSP_SELF
from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import gettext_lazy as _
from sentry_sdk.integrations.django import DjangoIntegration

from palvelutarjotin import __version__
from palvelutarjotin.consts import CSP

checkout_dir = environ.Path(__file__) - 2
assert os.path.exists(checkout_dir("manage.py"))
Expand Down Expand Up @@ -268,33 +269,25 @@
CORS_ALLOWED_ORIGIN_REGEXES = env.list("CORS_ALLOWED_ORIGIN_REGEXES")
CORS_ALLOW_ALL_ORIGINS = env.bool("CORS_ALLOW_ALL_ORIGINS")

# Configure the default CSP rule for different source types
CSP_DEFAULT_SRC = [CSP.SELF]

# CSP_STYLE_SRC includes 'unsafe-inline' for inline styles added by `django-helusers`.
CSP_STYLE_SRC = [
CSP.SELF,
CSP.UNSAFE_INLINE,
"cdn.jsdelivr.net",
"blob:",
]

CSP_SCRIPT_SRC = [
CSP.SELF,
"cdn.jsdelivr.net", # /graphql/ endpoint
"blob:",
]

CSP_FONT_SRC = [
CSP.SELF,
"data:", # /graphql/ endpoint uses "data:font/woff2"
]

CSP_IMG_SRC = [
CSP.SELF,
"blob:",
"data:",
]
# Configure default CSP rules for different source types
CSP_BLOB = "blob:"
CSP_DATA = "data:"
CSP_CDN = "cdn.jsdelivr.net"

CONTENT_SECURITY_POLICY = {
"DIRECTIVES": {
"default-src": [CSP_SELF],
"font-src": [CSP_SELF, CSP_DATA], # /graphql/ endpoint uses "data:font/woff2"
"img-src": [CSP_SELF, CSP_BLOB, CSP_DATA],
"script-src": [CSP_SELF, CSP_CDN, CSP_BLOB], # /graphql/ endpoint
"style-src": [
CSP_SELF,
CSP_UNSAFE_INLINE,
CSP_CDN,
CSP_BLOB,
], # 'unsafe-inline' needed for `django-helusers`.
}
}

AUTHENTICATION_BACKENDS = [
"axes.backends.AxesBackend",
Expand Down
8 changes: 5 additions & 3 deletions palvelutarjotin/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE
from csp.decorators import csp_update
from django.conf import settings
from django.conf.urls.static import static
Expand All @@ -15,7 +16,6 @@
from common.utils import get_api_version
from custom_health_checks.views import HealthCheckJSONView
from palvelutarjotin import __version__
from palvelutarjotin.consts import CSP
from palvelutarjotin.views import SentryGraphQLView

admin.site.index_title = " ".join([gettext("Kultus API"), get_api_version()])
Expand All @@ -25,8 +25,10 @@

# Add unsafe-inline to enable GraphiQL interface at /graphql/
@csp_update(
SCRIPT_SRC=settings.CSP_SCRIPT_SRC
+ ([CSP.UNSAFE_INLINE] if IS_GRAPHIQL_ENABLED else [])
{
"script-src": settings.CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"]
+ ([CSP_UNSAFE_INLINE] if IS_GRAPHIQL_ENABLED else []),
}
)
@csrf_exempt
def graphql_view(request, *args, **kwargs):
Expand Down
Loading
Loading