From 50ca3dc7727668ac479b5e33f51d437dffd478a4 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 15 Dec 2021 15:11:13 +0100 Subject: [PATCH 01/17] core: fix error when attempting to provider from cached application closes #1940 Signed-off-by: Jens Langhammer --- authentik/core/models.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/authentik/core/models.py b/authentik/core/models.py index 136db1c14..33508aac8 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -278,7 +278,13 @@ class Application(PolicyBindingModel): """Get casted provider instance""" if not self.provider: return None - return Provider.objects.get_subclass(pk=self.provider.pk) + # if the Application class has been cache, self.provider is set + # but doing a direct query lookup will fail. + # In that case, just return None + try: + return Provider.objects.get_subclass(pk=self.provider.pk) + except Provider.DoesNotExist: + return None def __str__(self): return self.name From 6ff8fdcc494a2e4c30670c575df553c58916c60c Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 15 Dec 2021 15:49:08 +0100 Subject: [PATCH 02/17] root: enable threading integration in sentry Signed-off-by: Jens Langhammer --- authentik/root/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/authentik/root/settings.py b/authentik/root/settings.py index e1bd798ea..e22134f7c 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -28,6 +28,7 @@ from sentry_sdk.integrations.boto3 import Boto3Integration from sentry_sdk.integrations.celery import CeleryIntegration from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.redis import RedisIntegration +from sentry_sdk.integrations.threading import ThreadingIntegration from authentik import ENV_GIT_HASH_KEY, __version__ from authentik.core.middleware import structlog_add_request_id @@ -424,6 +425,7 @@ if _ERROR_REPORTING: CeleryIntegration(), RedisIntegration(), Boto3Integration(), + ThreadingIntegration(propagate_hub=True), ], before_send=before_send, release=f"authentik@{__version__}", From f410a7701032c899c55f9c54359b9e86504dce45 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 15 Dec 2021 16:44:09 +0100 Subject: [PATCH 03/17] lifecycle: add -Ofair to celery Signed-off-by: Jens Langhammer --- lifecycle/ak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lifecycle/ak b/lifecycle/ak index 7f99cd311..f350ba393 100755 --- a/lifecycle/ak +++ b/lifecycle/ak @@ -67,7 +67,7 @@ if [[ "$1" == "server" ]]; then /authentik-proxy elif [[ "$1" == "worker" ]]; then echo "worker" > $MODE_FILE - check_if_root "celery -A authentik.root.celery worker --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events" + check_if_root "celery -A authentik.root.celery worker -Ofair --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events" elif [[ "$1" == "flower" ]]; then echo "flower" > $MODE_FILE celery -A authentik.root.celery flower From a105760123a122b4f439da8f7ae1a53653de6044 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 15 Dec 2021 16:44:22 +0100 Subject: [PATCH 04/17] events: improve app lookup for event creation Signed-off-by: Jens Langhammer --- authentik/events/models.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/authentik/events/models.py b/authentik/events/models.py index d08ab1e99..c10403488 100644 --- a/authentik/events/models.py +++ b/authentik/events/models.py @@ -2,7 +2,7 @@ import time from collections import Counter from datetime import timedelta -from inspect import getmodule, stack +from inspect import currentframe from smtplib import SMTPException from typing import TYPE_CHECKING, Optional, Type, Union from uuid import uuid4 @@ -192,14 +192,15 @@ class Event(ExpiringModel): def new( action: Union[str, EventAction], app: Optional[str] = None, - _inspect_offset: int = 1, **kwargs, ) -> "Event": """Create new Event instance from arguments. Instance is NOT saved.""" if not isinstance(action, EventAction): action = EventAction.CUSTOM_PREFIX + action if not app: - app = getmodule(stack()[_inspect_offset][0]).__name__ + current = currentframe() + parent = current.f_back + app = parent.f_globals["__name__"] cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs)) event = Event(action=action, app=app, context=cleaned_kwargs) return event From bb34474101f1e2c716b5d687845f16bc4331f574 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 10:13:10 +0100 Subject: [PATCH 05/17] web/admin: fix stage related flows not being shown in a list closes #1941 Signed-off-by: Jens Langhammer --- web/src/pages/stages/StageListPage.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/web/src/pages/stages/StageListPage.ts b/web/src/pages/stages/StageListPage.ts index 7ebe27a6e..a02a6c9eb 100644 --- a/web/src/pages/stages/StageListPage.ts +++ b/web/src/pages/stages/StageListPage.ts @@ -107,11 +107,15 @@ export class StageListPage extends TablePage {
${item.name}
${item.verboseName} `, - html`${item.flowSet?.map((flow) => { - return html` - ${flow.slug} - `; - })}`, + html``, html` ${t`Update`} ${t`Update ${item.verboseName}`} From 30e8408e8509d651ab29e992a4768e1ffcdc0eff Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 10:17:17 +0100 Subject: [PATCH 06/17] web/admin: fix notification unread colours not matching on user and admin interface Signed-off-by: Jens Langhammer --- web/src/elements/PageHeader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/elements/PageHeader.ts b/web/src/elements/PageHeader.ts index 17042ff61..9ead25281 100644 --- a/web/src/elements/PageHeader.ts +++ b/web/src/elements/PageHeader.ts @@ -81,7 +81,7 @@ export class PageHeader extends LitElement { font-size: 24px; } .notification-trigger.has-notifications { - color: #2b9af3; + color: var(--pf-global--active-color--100); } `, ]; From 5123bc13161f6cfecc4dfcc39e9fb3a98b549108 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 10:30:13 +0100 Subject: [PATCH 07/17] root: add sponsors to readme Signed-off-by: Jens Langhammer --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index f4138083e..fe7778212 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,23 @@ See [Development Documentation](https://goauthentik.io/developer-docs/?utm_sourc ## Security See [SECURITY.md](SECURITY.md) + +## Sponsors + +This project is proudly sponsored by: + +

+ + + +

+ +DigitalOcean provides development and testing resources for authentik. + +

+ + Deploys by Netlify + +

+ +Netlify hosts the [goauthentik.io](goauthentik.io) site. From f8aab40e3eecaa56eab5f42e698cdee794989f9c Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 11:00:19 +0100 Subject: [PATCH 08/17] internal: cleanup duplicate and redundant code, properly set sentry SDK scope settings Signed-off-by: Jens Langhammer --- internal/outpost/flow.go | 9 ++-- internal/outpost/ldap/bind/request.go | 7 ++- internal/outpost/ldap/search/request.go | 12 +++-- .../proxyv2/application/application.go | 8 ++++ internal/outpost/proxyv2/proxyv2.go | 2 + internal/utils/web/middleware.go | 4 +- internal/web/middleware_log.go | 29 ------------ internal/web/middleware_sentry.go | 44 ------------------- internal/web/web.go | 16 +++---- 9 files changed, 40 insertions(+), 91 deletions(-) delete mode 100644 internal/web/middleware_log.go delete mode 100644 internal/web/middleware_sentry.go diff --git a/internal/outpost/flow.go b/internal/outpost/flow.go index 830a6ed62..f19d22b0a 100644 --- a/internal/outpost/flow.go +++ b/internal/outpost/flow.go @@ -60,6 +60,7 @@ type FlowExecutor struct { func NewFlowExecutor(ctx context.Context, flowSlug string, refConfig *api.Configuration, logFields log.Fields) *FlowExecutor { rsp := sentry.StartSpan(ctx, "authentik.outposts.flow_executor") + rsp.Description = flowSlug l := log.WithField("flow", flowSlug).WithFields(logFields) jar, err := cookiejar.New(nil) @@ -153,8 +154,8 @@ func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) { } ch := challenge.GetActualInstance().(ChallengeInt) fe.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got challenge") - gcsp.SetTag("ak_challenge", string(ch.GetType())) - gcsp.SetTag("ak_component", ch.GetComponent()) + gcsp.SetTag("authentik.flow.challenge", string(ch.GetType())) + gcsp.SetTag("authentik.flow.component", ch.GetComponent()) gcsp.Finish() FlowTimingGet.With(prometheus.Labels{ "stage": ch.GetComponent(), @@ -202,8 +203,8 @@ func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) { response, _, err := responseReq.Execute() ch = response.GetActualInstance().(ChallengeInt) fe.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got response") - scsp.SetTag("ak_challenge", string(ch.GetType())) - scsp.SetTag("ak_component", ch.GetComponent()) + scsp.SetTag("authentik.flow.challenge", string(ch.GetType())) + scsp.SetTag("authentik.flow.component", ch.GetComponent()) scsp.Finish() switch ch.GetComponent() { diff --git a/internal/outpost/ldap/bind/request.go b/internal/outpost/ldap/bind/request.go index 43d379282..e91c2e70f 100644 --- a/internal/outpost/ldap/bind/request.go +++ b/internal/outpost/ldap/bind/request.go @@ -23,9 +23,14 @@ type Request struct { func NewRequest(bindDN string, bindPW string, conn net.Conn) (*Request, *sentry.Span) { span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.bind", sentry.TransactionName("authentik.providers.ldap.bind")) + span.Description = bindDN rid := uuid.New().String() span.SetTag("request_uid", rid) - span.SetTag("user.username", bindDN) + sentry.GetHubFromContext(span.Context()).Scope().SetUser(sentry.User{ + Username: bindDN, + ID: bindDN, + IPAddress: utils.GetIP(conn.RemoteAddr()), + }) bindDN = strings.ToLower(bindDN) return &Request{ diff --git a/internal/outpost/ldap/search/request.go b/internal/outpost/ldap/search/request.go index 183dba226..31c9fde42 100644 --- a/internal/outpost/ldap/search/request.go +++ b/internal/outpost/ldap/search/request.go @@ -2,6 +2,7 @@ package search import ( "context" + "fmt" "net" "strings" @@ -27,10 +28,15 @@ func NewRequest(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (*Re bindDN = strings.ToLower(bindDN) searchReq.BaseDN = strings.ToLower(searchReq.BaseDN) span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.search", sentry.TransactionName("authentik.providers.ldap.search")) + span.Description = fmt.Sprintf("%s (%s)", searchReq.BaseDN, ldap.ScopeMap[searchReq.Scope]) span.SetTag("request_uid", rid) - span.SetTag("user.username", bindDN) - span.SetTag("ak_filter", searchReq.Filter) - span.SetTag("ak_base_dn", searchReq.BaseDN) + sentry.GetHubFromContext(span.Context()).Scope().SetUser(sentry.User{ + Username: bindDN, + ID: bindDN, + IPAddress: utils.GetIP(conn.RemoteAddr()), + }) + span.SetTag("ldap_filter", searchReq.Filter) + span.SetTag("ldap_base_dn", searchReq.BaseDN) return &Request{ SearchRequest: searchReq, BindDN: bindDN, diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index b500a5773..c048bbd55 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -12,6 +12,8 @@ import ( "time" "github.com/coreos/go-oidc" + "github.com/getsentry/sentry-go" + sentryhttp "github.com/getsentry/sentry-go/http" "github.com/gorilla/mux" "github.com/gorilla/sessions" "github.com/pkg/errors" @@ -109,6 +111,11 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore user := "" if c != nil { user = c.PreferredUsername + sentry.GetHubFromContext(r.Context()).Scope().SetUser(sentry.User{ + Username: user, + ID: c.Sub, + IPAddress: r.RemoteAddr, + }) } before := time.Now() inner.ServeHTTP(rw, r) @@ -124,6 +131,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore }).Observe(float64(after)) }) }) + mux.Use(sentryhttp.New(sentryhttp.Options{}).Handle) // Support /start and /sign_in for backwards compatibility mux.HandleFunc("/akprox/start", a.handleRedirect) diff --git a/internal/outpost/proxyv2/proxyv2.go b/internal/outpost/proxyv2/proxyv2.go index f6cd68ff1..dbf481801 100644 --- a/internal/outpost/proxyv2/proxyv2.go +++ b/internal/outpost/proxyv2/proxyv2.go @@ -10,6 +10,7 @@ import ( "sync" "time" + sentryhttp "github.com/getsentry/sentry-go/http" "github.com/gorilla/mux" "github.com/pires/go-proxyproto" log "github.com/sirupsen/logrus" @@ -52,6 +53,7 @@ func NewProxyServer(ac *ak.APIController, portOffset int) *ProxyServer { globalMux := rootMux.NewRoute().Subrouter() globalMux.Use(web.NewLoggingHandler(l.WithField("logger", "authentik.outpost.proxyv2.http"), nil)) + globalMux.Use(sentryhttp.New(sentryhttp.Options{}).Handle) s := &ProxyServer{ Listen: "0.0.0.0:%d", PortOffset: portOffset, diff --git a/internal/utils/web/middleware.go b/internal/utils/web/middleware.go index 0c5f94f82..2b66e0d05 100644 --- a/internal/utils/web/middleware.go +++ b/internal/utils/web/middleware.go @@ -99,8 +99,8 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { h.handler.ServeHTTP(responseLogger, req) duration := float64(time.Since(t)) / float64(time.Millisecond) h.afterHandler(h.logger.WithFields(log.Fields{ - "host": req.RemoteAddr, - "vhost": GetHost(req), + "remote": req.RemoteAddr, + "host": GetHost(req), "request_protocol": req.Proto, "runtime": fmt.Sprintf("%0.3f", duration), "method": req.Method, diff --git a/internal/web/middleware_log.go b/internal/web/middleware_log.go deleted file mode 100644 index 246bbf452..000000000 --- a/internal/web/middleware_log.go +++ /dev/null @@ -1,29 +0,0 @@ -package web - -import ( - "net/http" - "time" - - "github.com/getsentry/sentry-go" - log "github.com/sirupsen/logrus" - "goauthentik.io/internal/utils/web" -) - -func loggingMiddleware(l *log.Entry) func(next http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - span := sentry.StartSpan(r.Context(), "authentik.go.request") - before := time.Now() - // Call the next handler, which can be another middleware in the chain, or the final handler. - next.ServeHTTP(w, r) - after := time.Now() - l.WithFields(log.Fields{ - "remote": r.RemoteAddr, - "method": r.Method, - "took": after.Sub(before), - "host": web.GetHost(r), - }).Info(r.RequestURI) - span.Finish() - }) - } -} diff --git a/internal/web/middleware_sentry.go b/internal/web/middleware_sentry.go deleted file mode 100644 index 88329e66c..000000000 --- a/internal/web/middleware_sentry.go +++ /dev/null @@ -1,44 +0,0 @@ -package web - -import ( - "encoding/json" - "net/http" - - sentryhttp "github.com/getsentry/sentry-go/http" - log "github.com/sirupsen/logrus" -) - -func recoveryMiddleware() func(next http.Handler) http.Handler { - sentryHandler := sentryhttp.New(sentryhttp.Options{}) - l := log.WithField("logger", "authentik.router.sentry") - return func(next http.Handler) http.Handler { - sentryHandler.Handle(next) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTP(w, r) - defer func() { - re := recover() - if re == nil { - return - } - err := re.(error) - if err != nil { - l.WithError(err).Warning("global panic handler") - jsonBody, _ := json.Marshal(struct { - Successful bool - Error string - }{ - Successful: false, - Error: err.Error(), - }) - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write(jsonBody) - if err != nil { - l.WithError(err).Warning("Failed to write sentry error body") - } - } - }() - }) - } -} diff --git a/internal/web/web.go b/internal/web/web.go index 4096f91dc..5ddd21f72 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -6,6 +6,7 @@ import ( "net" "net/http" + sentryhttp "github.com/getsentry/sentry-go/http" "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/pires/go-proxyproto" @@ -13,6 +14,7 @@ import ( "goauthentik.io/internal/config" "goauthentik.io/internal/gounicorn" "goauthentik.io/internal/outpost/proxyv2" + "goauthentik.io/internal/utils/web" ) type WebServer struct { @@ -34,13 +36,11 @@ type WebServer struct { func NewWebServer(g *gounicorn.GoUnicorn) *WebServer { l := log.WithField("logger", "authentik.router") mainHandler := mux.NewRouter() - if config.G.ErrorReporting.Enabled { - mainHandler.Use(recoveryMiddleware()) - } + mainHandler.Use(sentryhttp.New(sentryhttp.Options{}).Handle) mainHandler.Use(handlers.ProxyHeaders) mainHandler.Use(handlers.CompressHandler) logginRouter := mainHandler.NewRoute().Subrouter() - logginRouter.Use(loggingMiddleware(l)) + logginRouter.Use(web.NewLoggingHandler(l, nil)) ws := &WebServer{ LegacyProxy: true, @@ -72,7 +72,7 @@ func (ws *WebServer) Shutdown() { func (ws *WebServer) listenPlain() { ln, err := net.Listen("tcp", config.G.Web.Listen) if err != nil { - ws.log.WithError(err).Fatalf("failed to listen") + ws.log.WithError(err).Fatal("failed to listen") } ws.log.WithField("listen", config.G.Web.Listen).Info("Listening") @@ -83,7 +83,7 @@ func (ws *WebServer) listenPlain() { err = http.ListenAndServe(config.G.Web.Listen, ws.m) if err != nil && !errors.Is(err, http.ErrServerClosed) { - ws.log.Errorf("ERROR: http.Serve() - %s", err) + ws.log.WithError(err).Error("failed to listen") } } @@ -100,14 +100,14 @@ func (ws *WebServer) serve(listener net.Listener) { // We received an interrupt signal, shut down. if err := srv.Shutdown(context.Background()); err != nil { // Error from closing listeners, or context timeout: - ws.log.Printf("HTTP server Shutdown: %v", err) + ws.log.WithError(err).Warning("HTTP server Shutdown") } close(idleConnsClosed) }() err := srv.Serve(listener) if err != nil && !errors.Is(err, http.ErrServerClosed) { - ws.log.Errorf("ERROR: http.Serve() - %s", err) + ws.log.WithError(err).Error("ERROR: http.Serve()") } <-idleConnsClosed } From 7d6e88061f98cb75c69e2b41cd312db528fa4dcf Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 11:19:57 +0100 Subject: [PATCH 09/17] outposts: check if hub from context is set and fallback Signed-off-by: Jens Langhammer --- internal/outpost/ldap/bind/request.go | 6 +++++- internal/outpost/ldap/search/request.go | 6 +++++- internal/outpost/proxyv2/application/application.go | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/internal/outpost/ldap/bind/request.go b/internal/outpost/ldap/bind/request.go index e91c2e70f..59827105d 100644 --- a/internal/outpost/ldap/bind/request.go +++ b/internal/outpost/ldap/bind/request.go @@ -26,7 +26,11 @@ func NewRequest(bindDN string, bindPW string, conn net.Conn) (*Request, *sentry. span.Description = bindDN rid := uuid.New().String() span.SetTag("request_uid", rid) - sentry.GetHubFromContext(span.Context()).Scope().SetUser(sentry.User{ + hub := sentry.GetHubFromContext(span.Context()) + if hub == nil { + hub = sentry.CurrentHub() + } + hub.Scope().SetUser(sentry.User{ Username: bindDN, ID: bindDN, IPAddress: utils.GetIP(conn.RemoteAddr()), diff --git a/internal/outpost/ldap/search/request.go b/internal/outpost/ldap/search/request.go index 31c9fde42..5f7e9af90 100644 --- a/internal/outpost/ldap/search/request.go +++ b/internal/outpost/ldap/search/request.go @@ -30,7 +30,11 @@ func NewRequest(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (*Re span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.search", sentry.TransactionName("authentik.providers.ldap.search")) span.Description = fmt.Sprintf("%s (%s)", searchReq.BaseDN, ldap.ScopeMap[searchReq.Scope]) span.SetTag("request_uid", rid) - sentry.GetHubFromContext(span.Context()).Scope().SetUser(sentry.User{ + hub := sentry.GetHubFromContext(span.Context()) + if hub == nil { + hub = sentry.CurrentHub() + } + hub.Scope().SetUser(sentry.User{ Username: bindDN, ID: bindDN, IPAddress: utils.GetIP(conn.RemoteAddr()), diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index c048bbd55..f6d48fcc8 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -111,7 +111,11 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore user := "" if c != nil { user = c.PreferredUsername - sentry.GetHubFromContext(r.Context()).Scope().SetUser(sentry.User{ + hub := sentry.GetHubFromContext(r.Context()) + if hub == nil { + hub = sentry.CurrentHub() + } + hub.Scope().SetUser(sentry.User{ Username: user, ID: c.Sub, IPAddress: r.RemoteAddr, From 103e723d8cf57b5e16eb60d7095bca5cb865f2ef Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 12:10:28 +0100 Subject: [PATCH 10/17] web/elements: add support for sidebar on table page Signed-off-by: Jens Langhammer --- web/src/elements/table/TablePage.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/web/src/elements/table/TablePage.ts b/web/src/elements/table/TablePage.ts index a52416a09..8ef5462cc 100644 --- a/web/src/elements/table/TablePage.ts +++ b/web/src/elements/table/TablePage.ts @@ -4,6 +4,7 @@ import { ifDefined } from "lit/directives/if-defined.js"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css"; +import PFSidebar from "@patternfly/patternfly/components/Sidebar/sidebar.css"; import "../../elements/PageHeader"; import { Table } from "./Table"; @@ -14,7 +15,15 @@ export abstract class TablePage extends Table { abstract pageIcon(): string; static get styles(): CSSResult[] { - return super.styles.concat(PFPage, PFContent); + return super.styles.concat(PFPage, PFContent, PFSidebar); + } + + renderSidebarBefore(): TemplateResult { + return html``; + } + + renderSidebarAfter(): TemplateResult { + return html``; } render(): TemplateResult { @@ -25,7 +34,15 @@ export abstract class TablePage extends Table { >
-
${this.renderTable()}
+
+
+ ${this.renderSidebarBefore()} +
+
${this.renderTable()}
+
+ ${this.renderSidebarAfter()} +
+
`; } } From 83089b47d383932e25449bf1c0c2d1876f15c48f Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 12:10:46 +0100 Subject: [PATCH 11/17] web/elements: add Markdown component to improve rendering Signed-off-by: Jens Langhammer --- web/src/elements/Markdown.ts | 25 ++++++++++++++ .../providers/proxy/ProxyProviderViewPage.ts | 34 ++++++++++++++----- 2 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 web/src/elements/Markdown.ts diff --git a/web/src/elements/Markdown.ts b/web/src/elements/Markdown.ts new file mode 100644 index 000000000..c95d302ef --- /dev/null +++ b/web/src/elements/Markdown.ts @@ -0,0 +1,25 @@ +import { CSSResult, LitElement, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { unsafeHTML } from "lit/directives/unsafe-html.js"; + +import AKGlobal from "../authentik.css"; +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFList from "@patternfly/patternfly/components/List/list.css"; + +@customElement("ak-markdown") +export class Markdown extends LitElement { + @property() + md?: string; + + static get styles(): CSSResult[] { + return [PFList, PFContent, AKGlobal]; + } + + render(): TemplateResult { + if (!this.md) { + return html``; + } + const finalHTML = this.md.replace("
    ", `
      `); + return html`${unsafeHTML(finalHTML)}`; + } +} diff --git a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts index 7192fffa7..03a655c15 100644 --- a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts +++ b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts @@ -1,7 +1,6 @@ import { t } from "@lingui/macro"; import { CSSResult, LitElement, TemplateResult, html } from "lit"; -import { unsafeHTML } from "lit-html/directives/unsafe-html.js"; import { customElement, property } from "lit/decorators.js"; import AKGlobal from "../../../authentik.css"; @@ -28,6 +27,7 @@ import { DEFAULT_CONFIG } from "../../../api/Config"; import { EVENT_REFRESH } from "../../../constants"; import "../../../elements/CodeMirror"; import { PFColor } from "../../../elements/Label"; +import "../../../elements/Markdown"; import "../../../elements/Tabs"; import "../../../elements/buttons/ModalButton"; import "../../../elements/buttons/SpinnerButton"; @@ -90,7 +90,7 @@ export class ProxyProviderViewPage extends LitElement { }); } - renderConfigTemplate(tmpl: string): TemplateResult { + renderConfigTemplate(tmpl: string): string { // See website/docs/providers/proxy/forward_auth.mdx let final = ""; if (this.provider?.mode === ProxyMode.ForwardSingle) { @@ -103,7 +103,7 @@ export class ProxyProviderViewPage extends LitElement { .replaceAll("authentik.company", window.location.hostname) .replaceAll("outpost.company", this.provider?.externalHost || ""); } - return html`${unsafeHTML(final)}`; + return final; } render(): TemplateResult { @@ -250,42 +250,58 @@ export class ProxyProviderViewPage extends LitElement { data-tab-title="${t`Nginx (Ingress)`}" class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" > - ${this.renderConfigTemplate(MDNginxIngress.html)} +
      - ${this.renderConfigTemplate(MDNginxPM.html)} +
      - ${this.renderConfigTemplate(MDNginxStandalone.html)} +
      - ${this.renderConfigTemplate(MDTraefikIngres.html)} +
      - ${this.renderConfigTemplate(MDTraefikCompose.html)} +
      - ${this.renderConfigTemplate(MDTraefikStandalone.html)} +
      ` From 59493c02c483e62142adfb3c9154a855426c0d8a Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 12:18:43 +0100 Subject: [PATCH 12/17] web/elements: pass full Markdown object to ak-markdown, get title from metadata Signed-off-by: Jens Langhammer --- web/src/elements/Markdown.ts | 15 ++++++++--- web/src/global.d.ts | 2 +- .../providers/proxy/ProxyProviderViewPage.ts | 26 ++++++++----------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/web/src/elements/Markdown.ts b/web/src/elements/Markdown.ts index c95d302ef..40561a59f 100644 --- a/web/src/elements/Markdown.ts +++ b/web/src/elements/Markdown.ts @@ -6,10 +6,16 @@ import AKGlobal from "../authentik.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFList from "@patternfly/patternfly/components/List/list.css"; +export interface MarkdownDocument { + html: string; + metadata: { [key: string]: string }; + filename: string; +} + @customElement("ak-markdown") export class Markdown extends LitElement { - @property() - md?: string; + @property({ attribute: false }) + md?: MarkdownDocument; static get styles(): CSSResult[] { return [PFList, PFContent, AKGlobal]; @@ -19,7 +25,8 @@ export class Markdown extends LitElement { if (!this.md) { return html``; } - const finalHTML = this.md.replace("
        ", `
          `); - return html`${unsafeHTML(finalHTML)}`; + const finalHTML = this.md?.html.replace("
            ", "
              "); + return html`${this.md?.metadata.title ? html`

              ${this.md.metadata.title}

              ` : html``} + ${unsafeHTML(finalHTML)}`; } } diff --git a/web/src/global.d.ts b/web/src/global.d.ts index 203b51ec2..b7b3dfdf8 100644 --- a/web/src/global.d.ts +++ b/web/src/global.d.ts @@ -1,7 +1,7 @@ declare module "*.css"; declare module "*.md" { const html: string; - const metadata: object; + const metadata: { [key: string]: string }; const filename: string; } diff --git a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts index 03a655c15..b8909bb43 100644 --- a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts +++ b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts @@ -28,6 +28,7 @@ import { EVENT_REFRESH } from "../../../constants"; import "../../../elements/CodeMirror"; import { PFColor } from "../../../elements/Label"; import "../../../elements/Markdown"; +import { MarkdownDocument } from "../../../elements/Markdown"; import "../../../elements/Tabs"; import "../../../elements/buttons/ModalButton"; import "../../../elements/buttons/SpinnerButton"; @@ -90,20 +91,19 @@ export class ProxyProviderViewPage extends LitElement { }); } - renderConfigTemplate(tmpl: string): string { + renderConfigTemplate(markdown: MarkdownDocument): MarkdownDocument { // See website/docs/providers/proxy/forward_auth.mdx - let final = ""; if (this.provider?.mode === ProxyMode.ForwardSingle) { - final = tmpl + markdown.html = markdown.html .replaceAll("authentik.company", window.location.hostname) .replaceAll("outpost.company", window.location.hostname) .replaceAll("app.company", this.provider?.externalHost || ""); } else if (this.provider?.mode == ProxyMode.ForwardDomain) { - final = tmpl + markdown.html = markdown.html .replaceAll("authentik.company", window.location.hostname) .replaceAll("outpost.company", this.provider?.externalHost || ""); } - return final; + return markdown; } render(): TemplateResult { @@ -251,7 +251,7 @@ export class ProxyProviderViewPage extends LitElement { class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" >
              From 7c71c52791a8769c58f213ccab3d3439e653af47 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 12:23:30 +0100 Subject: [PATCH 13/17] web/admin: add sidebar to applications Signed-off-by: Jens Langhammer --- web/src/locales/en.po | 4 ++++ web/src/locales/fr_FR.po | 4 ++++ web/src/locales/pseudo-LOCALE.po | 4 ++++ .../pages/applications/ApplicationListPage.ts | 15 ++++++++++++++ website/docs/core/applications.md | 20 +++++++++---------- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 7ef86c531..5a9f61641 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -122,6 +122,10 @@ msgstr "API Token (can be used to access the API programmatically)" msgid "API request failed" msgstr "API request failed" +#: src/pages/applications/ApplicationListPage.ts +msgid "About applications" +msgstr "About applications" + #: src/pages/sources/oauth/OAuthSourceViewPage.ts msgid "Access Key" msgstr "Access Key" diff --git a/web/src/locales/fr_FR.po b/web/src/locales/fr_FR.po index 7838b5efb..93ca08a80 100644 --- a/web/src/locales/fr_FR.po +++ b/web/src/locales/fr_FR.po @@ -128,6 +128,10 @@ msgstr "Jeton d'API (peut être utilisé pour accéder à l'API via un programme msgid "API request failed" msgstr "Requête d'API échouée" +#: src/pages/applications/ApplicationListPage.ts +msgid "About applications" +msgstr "" + #: src/pages/sources/oauth/OAuthSourceViewPage.ts msgid "Access Key" msgstr "Clé d'accès" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index b024d7e92..521ef15f6 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -122,6 +122,10 @@ msgstr "" msgid "API request failed" msgstr "" +#: src/pages/applications/ApplicationListPage.ts +msgid "About applications" +msgstr "" + #: src/pages/sources/oauth/OAuthSourceViewPage.ts msgid "Access Key" msgstr "" diff --git a/web/src/pages/applications/ApplicationListPage.ts b/web/src/pages/applications/ApplicationListPage.ts index b408ffd54..007f03810 100644 --- a/web/src/pages/applications/ApplicationListPage.ts +++ b/web/src/pages/applications/ApplicationListPage.ts @@ -5,12 +5,15 @@ import { customElement, property } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css"; +import PFCard from "@patternfly/patternfly/components/Card/card.css"; import { Application, CoreApi } from "@goauthentik/api"; +import MDApplication from "../../../../website/docs/core/applications.md"; import { AKResponse } from "../../api/Client"; import { DEFAULT_CONFIG } from "../../api/Config"; import { uiConfig } from "../../common/config"; +import "../../elements/Markdown"; import "../../elements/buttons/SpinnerButton"; import "../../elements/forms/DeleteBulkForm"; import "../../elements/forms/ModalForm"; @@ -52,6 +55,7 @@ export class ApplicationListPage extends TablePage { static get styles(): CSSResult[] { return super.styles.concat( PFAvatar, + PFCard, css` tr td:first-child { width: auto; @@ -74,6 +78,17 @@ export class ApplicationListPage extends TablePage { ]; } + renderSidebarAfter(): TemplateResult { + return html`
              +
              +
              ${t`About applications`}
              +
              + +
              +
              +
              `; + } + renderToolbarSelected(): TemplateResult { const disabled = this.selectedElements.length < 1; return html` Date: Thu, 16 Dec 2021 12:23:44 +0100 Subject: [PATCH 14/17] web/elements: close notification drawer when clearing all notifications Signed-off-by: Jens Langhammer --- web/src/elements/notifications/NotificationDrawer.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web/src/elements/notifications/NotificationDrawer.ts b/web/src/elements/notifications/NotificationDrawer.ts index 175a5ae44..e619a5fbd 100644 --- a/web/src/elements/notifications/NotificationDrawer.ts +++ b/web/src/elements/notifications/NotificationDrawer.ts @@ -183,9 +183,15 @@ export class NotificationDrawer extends LitElement { composed: true, }), ); + this.dispatchEvent( + new CustomEvent(EVENT_NOTIFICATION_DRAWER_TOGGLE, { + bubbles: true, + composed: true, + }), + ); }); }} - class="pf-c-button pf-m-secondary pf-m-block" + class="pf-c-button pf-m-primary pf-m-block" type="button" aria-label=${t`Clear all`} > From 0a2c1eb41930af7a16c34df224507164ac4c892d Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 12:26:14 +0100 Subject: [PATCH 15/17] web/elements: fix linting error Signed-off-by: Jens Langhammer --- web/src/elements/Markdown.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/elements/Markdown.ts b/web/src/elements/Markdown.ts index 40561a59f..d0ff3279a 100644 --- a/web/src/elements/Markdown.ts +++ b/web/src/elements/Markdown.ts @@ -25,7 +25,7 @@ export class Markdown extends LitElement { if (!this.md) { return html``; } - const finalHTML = this.md?.html.replace("
                ", "
                  "); + const finalHTML = this.md?.html.replace("
                    ", "
                      "); return html`${this.md?.metadata.title ? html`

                      ${this.md.metadata.title}

                      ` : html``} ${unsafeHTML(finalHTML)}`; } From f72b652b2443328cd41611a71e9e69e75eba055d Mon Sep 17 00:00:00 2001 From: Sem <86064734+justSem@users.noreply.github.com> Date: Thu, 16 Dec 2021 14:23:00 +0100 Subject: [PATCH 16/17] website/integrations: Updated bookstack integration docs page (#1942) In some cases one might need to define the full SAML property to enable proper group sync. (see: https://github.com/BookStackApp/BookStack/issues/3109 ) --- website/integrations/services/bookstack/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/website/integrations/services/bookstack/index.md b/website/integrations/services/bookstack/index.md index e6466df04..be0923836 100644 --- a/website/integrations/services/bookstack/index.md +++ b/website/integrations/services/bookstack/index.md @@ -101,3 +101,9 @@ BookStack will attempt to match the SAML user to an existing BookStack user base :::note SAML Group Sync is supported by Bookstack. Review the BookStack documentation on the required Environment variables. https://www.bookstackapp.com/docs/admin/saml2-auth/ ::: + +:::note +In some cases you might need to define the full SAML property name. +i.e.: `SAML2_GROUP_ATTRIBUTE="http://schemas.xmlsoap.org/claims/Group"` +See https://github.com/BookStackApp/BookStack/issues/3109 for more details. +::: From 0ca6fbb2248a3eb9b9680431aae81eab14d4484b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 16 Dec 2021 15:48:44 +0100 Subject: [PATCH 17/17] website/docs: final 2021.12.1 release notes Signed-off-by: Jens Langhammer --- website/docs/releases/v2021.12.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/website/docs/releases/v2021.12.md b/website/docs/releases/v2021.12.md index 9854a1895..3a384b1d2 100644 --- a/website/docs/releases/v2021.12.md +++ b/website/docs/releases/v2021.12.md @@ -151,6 +151,19 @@ This release does not have any headline features, and mostly fixes bugs. - web/admin: update overview page - web/flows: fix error when attempting to enroll new webauthn device +## Fixed in 2021.12.1 + +- core: fix error when attempting to provider from cached application +- events: improve app lookup for event creation +- internal: cleanup duplicate and redundant code, properly set sentry SDK scope settings +- lifecycle: add -Ofair to celery +- web/admin: add sidebar to applications +- web/admin: fix notification unread colours not matching on user and admin interface +- web/admin: fix stage related flows not being shown in a list +- web/elements: add Markdown component to improve rendering +- web/elements: add support for sidebar on table page +- web/elements: close notification drawer when clearing all notifications + ## Upgrading This release does not introduce any new requirements.