diff --git a/authentik/api/v2/sentry.py b/authentik/api/v2/sentry.py new file mode 100644 index 000000000..dc0935814 --- /dev/null +++ b/authentik/api/v2/sentry.py @@ -0,0 +1,38 @@ +"""Sentry tunnel""" +from json import loads + +from django.conf import settings +from django.http.request import HttpRequest +from django.http.response import HttpResponse +from django.views.generic.base import View +from requests import post +from requests.exceptions import RequestException + +from authentik.lib.config import CONFIG + + +class SentryTunnelView(View): + """Sentry tunnel, to prevent ad blockers from blocking sentry""" + + def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: + """Sentry tunnel, to prevent ad blockers from blocking sentry""" + # Only allow usage of this endpoint when error reporting is enabled + if not CONFIG.y_bool("error_reporting.enabled", False): + return HttpResponse(status=400) + # Body is 2 json objects separated by \n + full_body = request.body + header = loads(full_body.splitlines()[0]) + # Check that the DSN is what we expect + dsn = header.get("dsn", "") + if dsn != settings.SENTRY_DSN: + return HttpResponse(status=400) + response = post( + "https://sentry.beryju.org/api/8/envelope/", + data=full_body, + headers={"Content-Type": "application/octet-stream"}, + ) + try: + response.raise_for_status() + except RequestException: + return HttpResponse(status=500) + return HttpResponse(status=response.status_code) diff --git a/authentik/api/v2/urls.py b/authentik/api/v2/urls.py index 3cd090fe0..c1b20d572 100644 --- a/authentik/api/v2/urls.py +++ b/authentik/api/v2/urls.py @@ -1,5 +1,6 @@ """api v2 urls""" from django.urls import path +from django.views.decorators.csrf import csrf_exempt from drf_spectacular.views import SpectacularAPIView from rest_framework import routers @@ -10,6 +11,7 @@ from authentik.admin.api.tasks import TaskViewSet from authentik.admin.api.version import VersionView from authentik.admin.api.workers import WorkerView from authentik.api.v2.config import ConfigView +from authentik.api.v2.sentry import SentryTunnelView from authentik.api.views import APIBrowserView from authentik.core.api.applications import ApplicationViewSet from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet @@ -235,6 +237,7 @@ urlpatterns = ( FlowExecutorView.as_view(), name="flow-executor", ), + path("sentry/", csrf_exempt(SentryTunnelView.as_view()), name="sentry"), path("schema/", SpectacularAPIView.as_view(), name="schema"), ] ) diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 1354e187a..0b27cf31f 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -364,11 +364,12 @@ if CONFIG.y("postgresql.s3_backup"): ) # Sentry integration +SENTRY_DSN = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8" _ERROR_REPORTING = CONFIG.y_bool("error_reporting.enabled", False) if _ERROR_REPORTING: # pylint: disable=abstract-class-instantiated sentry_init( - dsn="https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8", + dsn=SENTRY_DSN, integrations=[ DjangoIntegration(transaction_style="function_name"), CeleryIntegration(), diff --git a/web/package-lock.json b/web/package-lock.json index 068dfbd90..8dbef7c52 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -61,19 +61,21 @@ "typescript": "^4.3.5", "webcomponent-qr-code": "^1.0.5", "yaml": "^1.10.2" - } + }, + "devDependencies": {} }, "api": { "name": "authentik-api", - "version": "0.0.1", - "dependencies": { - "typescript": "^3.6" + "version": "1.0.0", + "devDependencies": { + "typescript": "^3.9.5" } }, "api/node_modules/typescript": { "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9305,6 +9307,7 @@ "@babel/types": "^7.11.5", "@lingui/babel-plugin-extract-messages": "^3.10.2", "@lingui/conf": "^3.10.2", + "babel-plugin-macros": "^3.0.1", "bcp-47": "^1.0.7", "chalk": "^4.1.0", "chokidar": "3.5.1", @@ -10198,13 +10201,14 @@ "authentik-api": { "version": "file:api", "requires": { - "typescript": "^3.6" + "typescript": "^3.9.5" }, "dependencies": { "typescript": { "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==" + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true } } }, diff --git a/web/src/api/Sentry.ts b/web/src/api/Sentry.ts index 6e939f79f..462114c00 100644 --- a/web/src/api/Sentry.ts +++ b/web/src/api/Sentry.ts @@ -15,6 +15,7 @@ export function configureSentry(canDoPpi: boolean = false): Promise { Sentry.init({ dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8", release: `authentik@${VERSION}`, + tunnel: "/api/v2beta/sentry/", integrations: [ new Integrations.BrowserTracing({ tracingOrigins: [window.location.host, "localhost"],