From 44ecaf8f838ea5d772690d6f9aa68f8ddc70a157 Mon Sep 17 00:00:00 2001 From: Henning Fleischhauer <18215579+CaptainStandby@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:48:44 +0200 Subject: [PATCH 1/3] feat: emit events for login/logout and registration --- cmd/daemon/serve.go | 4 +++ go.mod | 3 +- go.sum | 6 ++-- selfservice/flow/login/error.go | 8 +++++ selfservice/flow/login/hook.go | 33 +++++++---------- selfservice/flow/logout/handler.go | 22 ++++++++++++ selfservice/flow/registration/error.go | 9 +++++ selfservice/flow/registration/hook.go | 18 ++++------ x/events/events.go | 49 ++++++++++++++++++++++++++ 9 files changed, 116 insertions(+), 36 deletions(-) create mode 100644 x/events/events.go diff --git a/cmd/daemon/serve.go b/cmd/daemon/serve.go index 52a4d69188db..c14f91a2d2eb 100644 --- a/cmd/daemon/serve.go +++ b/cmd/daemon/serve.go @@ -9,6 +9,8 @@ import ( "net/http" "time" + "github.com/ory/x/otelx/semconv" + "github.com/pkg/errors" "github.com/rs/cors" "github.com/spf13/cobra" @@ -87,6 +89,7 @@ func ServePublic(r driver.Registry, cmd *cobra.Command, args []string, slOpts *s publicLogger.ExcludePaths(healthx.AliveCheckPath, healthx.ReadyCheckPath) } + n.UseFunc(semconv.Middleware) n.Use(publicLogger) n.Use(x.HTTPLoaderContextMiddleware(r)) n.Use(sqa(ctx, cmd, r)) @@ -169,6 +172,7 @@ func ServeAdmin(r driver.Registry, cmd *cobra.Command, args []string, slOpts *se if r.Config().DisableAdminHealthRequestLog(ctx) { adminLogger.ExcludePaths(x.AdminPrefix+healthx.AliveCheckPath, x.AdminPrefix+healthx.ReadyCheckPath, x.AdminPrefix+prometheus.MetricsPrometheusPath) } + n.UseFunc(semconv.Middleware) n.Use(adminLogger) n.UseFunc(x.RedirectAdminMiddleware) n.Use(x.HTTPLoaderContextMiddleware(r)) diff --git a/go.mod b/go.mod index 9cf1f7a74783..77641b4e6c8d 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/ory/jsonschema/v3 v3.0.8 github.com/ory/mail/v3 v3.0.0 github.com/ory/nosurf v1.2.7 - github.com/ory/x v0.0.551 + github.com/ory/x v0.0.552 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/pquerna/otp v1.4.0 @@ -152,6 +152,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fullstorydev/grpcurl v1.8.1 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.21.4 // indirect diff --git a/go.sum b/go.sum index 52b9f182c650..87c1e69ff981 100644 --- a/go.sum +++ b/go.sum @@ -377,6 +377,8 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= +github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -1137,8 +1139,8 @@ github.com/ory/nosurf v1.2.7 h1:YrHrbSensQyU6r6HT/V5+HPdVEgrOTMJiLoJABSBOp4= github.com/ory/nosurf v1.2.7/go.mod h1:d4L3ZBa7Amv55bqxCBtCs63wSlyaiCkWVl4vKf3OUxA= github.com/ory/sessions v1.2.2-0.20220110165800-b09c17334dc2 h1:zm6sDvHy/U9XrGpixwHiuAwpp0Ock6khSVHkrv6lQQU= github.com/ory/sessions v1.2.2-0.20220110165800-b09c17334dc2/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/ory/x v0.0.551 h1:U3z2bvSzAwDP0SWmbAdjzfvWPu4k+oWrPctoCdalGk0= -github.com/ory/x v0.0.551/go.mod h1:oRVemI3SQQOLvOCJWIRinHQKlgmay/NbwSyRUIsS/Yk= +github.com/ory/x v0.0.552 h1:vgDw7FFQ7Ama3iyDLbjElY2Um1/ub82iIubK0pUj81M= +github.com/ory/x v0.0.552/go.mod h1:oRVemI3SQQOLvOCJWIRinHQKlgmay/NbwSyRUIsS/Yk= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= diff --git a/selfservice/flow/login/error.go b/selfservice/flow/login/error.go index 9d0dec08fdc6..195e320170b7 100644 --- a/selfservice/flow/login/error.go +++ b/selfservice/flow/login/error.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/ory/kratos/ui/node" + "github.com/ory/kratos/x/events" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/text" @@ -80,6 +81,13 @@ func (s *ErrorHandler) WriteFlowError(w http.ResponseWriter, r *http.Request, f WithField("login_flow", f). Info("Encountered self-service login error.") + var flowType flow.Type + if f != nil { + flowType = f.Type + } + + events.Emit(r.Context(), events.LoginFailed, events.AttrFlowType(flowType)) + if f == nil { s.forward(w, r, nil, err) return diff --git a/selfservice/flow/login/hook.go b/selfservice/flow/login/hook.go index 7517a0107f64..ad1b4caedc77 100644 --- a/selfservice/flow/login/hook.go +++ b/selfservice/flow/login/hook.go @@ -9,9 +9,9 @@ import ( "net/http" "time" + "github.com/ory/kratos/x/events" + "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" "github.com/ory/kratos/driver/config" "github.com/ory/kratos/hydra" @@ -21,7 +21,6 @@ import ( "github.com/ory/kratos/ui/container" "github.com/ory/kratos/ui/node" "github.com/ory/kratos/x" - "github.com/ory/x/httpx" "github.com/ory/x/otelx" "github.com/ory/x/otelx/semconv" ) @@ -178,15 +177,11 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("session_id", s.ID). WithField("identity_id", i.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Token.") - trace.SpanFromContext(r.Context()).AddEvent( - semconv.EventSessionIssued, - trace.WithAttributes( - attribute.String(semconv.AttrIdentityID, i.ID.String()), - attribute.String(semconv.AttrNID, i.NID.String()), - attribute.String(semconv.AttrClientIP, httpx.ClientIP(r)), - attribute.String("flow", string(flow.TypeAPI)), - ), - ) + + events.Emit(r.Context(), events.SessionIssued, + semconv.AttrIdentityID(i.ID), + events.AttrSessionID(s.ID), + events.AttrFlowType(a.Type)) response := &APIFlowResponse{Session: s, Token: s.Token} if required, _ := e.requiresAAL2(r, classified, a); required { @@ -207,15 +202,11 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("identity_id", i.ID). WithField("session_id", s.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Cookie.") - trace.SpanFromContext(r.Context()).AddEvent( - semconv.EventSessionIssued, - trace.WithAttributes( - attribute.String(semconv.AttrIdentityID, i.ID.String()), - attribute.String(semconv.AttrNID, i.NID.String()), - attribute.String(semconv.AttrClientIP, httpx.ClientIP(r)), - attribute.String("flow", string(flow.TypeBrowser)), - ), - ) + + events.Emit(r.Context(), events.SessionIssued, + semconv.AttrIdentityID(i.ID), + events.AttrSessionID(s.ID), + events.AttrFlowType(a.Type)) if x.IsJSONRequest(r) { // Browser flows rely on cookies. Adding tokens in the mix will confuse consumers. diff --git a/selfservice/flow/logout/handler.go b/selfservice/flow/logout/handler.go index 36aec9b2e4bf..a4271335640b 100644 --- a/selfservice/flow/logout/handler.go +++ b/selfservice/flow/logout/handler.go @@ -7,6 +7,10 @@ import ( "net/http" "net/url" + "github.com/ory/kratos/identity" + "github.com/ory/kratos/x/events" + "github.com/ory/x/otelx/semconv" + "github.com/pkg/errors" "github.com/ory/herodot" @@ -198,6 +202,16 @@ func (h *Handler) performNativeLogout(w http.ResponseWriter, r *http.Request, _ h.d.Writer().WriteError(w, r, err) return } + sess, err := h.d.SessionPersister().GetSessionByToken(r.Context(), p.SessionToken, session.ExpandNothing, identity.ExpandNothing) + if err != nil { + if errors.Is(err, sqlcon.ErrNoRows) { + h.d.Writer().WriteError(w, r, errors.WithStack(herodot.ErrForbidden.WithReason("The provided Ory Session Token could not be found, is invalid, or otherwise malformed."))) + return + } + + h.d.Writer().WriteError(w, r, err) + return + } if err := h.d.SessionPersister().RevokeSessionByToken(r.Context(), p.SessionToken); err != nil { if errors.Is(err, sqlcon.ErrNoRows) { @@ -209,6 +223,10 @@ func (h *Handler) performNativeLogout(w http.ResponseWriter, r *http.Request, _ return } + events.Emit(r.Context(), events.SessionRevoked, + semconv.AttrIdentityID(sess.IdentityID), + events.AttrSessionID(sess.ID)) + w.WriteHeader(http.StatusNoContent) } @@ -286,6 +304,10 @@ func (h *Handler) updateLogoutFlow(w http.ResponseWriter, r *http.Request, ps ht return } + events.Emit(r.Context(), events.SessionRevoked, + semconv.AttrIdentityID(sess.IdentityID), + events.AttrSessionID(sess.ID)) + h.completeLogout(w, r) } diff --git a/selfservice/flow/registration/error.go b/selfservice/flow/registration/error.go index ae01ca2850b4..6a6fc1f87780 100644 --- a/selfservice/flow/registration/error.go +++ b/selfservice/flow/registration/error.go @@ -8,6 +8,7 @@ import ( "github.com/ory/kratos/schema" "github.com/ory/kratos/ui/node" + "github.com/ory/kratos/x/events" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/text" @@ -86,6 +87,14 @@ func (s *ErrorHandler) WriteFlowError( WithField("registration_flow", f). Info("Encountered self-service flow error.") + var flowType flow.Type + if f != nil { + flowType = f.Type + } + + events.Emit(r.Context(), events.RegistrationFailed, + events.AttrFlowType(flowType)) + if f == nil { s.forward(w, r, nil, err) return diff --git a/selfservice/flow/registration/hook.go b/selfservice/flow/registration/hook.go index 5c77f0d5f020..5e196dcc4515 100644 --- a/selfservice/flow/registration/hook.go +++ b/selfservice/flow/registration/hook.go @@ -9,11 +9,10 @@ import ( "net/http" "time" + "github.com/ory/kratos/x/events" + "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "github.com/ory/x/httpx" "github.com/ory/x/otelx/semconv" "github.com/ory/x/sqlcon" @@ -169,15 +168,10 @@ func (e *HookExecutor) PostRegistrationHook(w http.ResponseWriter, r *http.Reque WithRequest(r). WithField("identity_id", i.ID). Info("A new identity has registered using self-service registration.") - trace.SpanFromContext(r.Context()).AddEvent( - semconv.EventIdentityCreated, - trace.WithAttributes( - attribute.String(semconv.AttrIdentityID, i.ID.String()), - attribute.String(semconv.AttrNID, i.NID.String()), - attribute.String(semconv.AttrClientIP, httpx.ClientIP(r)), - attribute.String("flow", string(a.Type)), - ), - ) + + events.Emit(r.Context(), events.IdentityCreated, + semconv.AttrIdentityID(i.ID), + events.AttrFlowType(a.Type)) s, err := session.NewActiveSession(r, i, e.d.Config(), time.Now().UTC(), ct, identity.AuthenticatorAssuranceLevel1) if err != nil { diff --git a/x/events/events.go b/x/events/events.go new file mode 100644 index 000000000000..5aa6229b02d2 --- /dev/null +++ b/x/events/events.go @@ -0,0 +1,49 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +package events + +import ( + "context" + + "github.com/gofrs/uuid" + otelattr "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + "github.com/ory/kratos/selfservice/flow" + "github.com/ory/x/otelx/semconv" +) + +const ( + SessionIssued semconv.Event = "SessionIssued" + SessionRevoked semconv.Event = "SessionRevoked" + RegistrationFailed semconv.Event = "RegistrationFailed" + IdentityCreated semconv.Event = "IdentityCreated" + LoginFailed semconv.Event = "LoginFailed" +) + +const ( + attributeKeyFlowType semconv.AttributeKey = "FlowType" + attributeKeySessionID semconv.AttributeKey = "SessionID" +) + +func AttrFlowType(val flow.Type) otelattr.KeyValue { + return otelattr.String(attributeKeyFlowType.String(), string(val)) +} + +func AttrSessionID(val uuid.UUID) otelattr.KeyValue { + return otelattr.String(attributeKeySessionID.String(), val.String()) +} + +// Emit adds an event to the current span in the context. +func Emit(ctx context.Context, event semconv.Event, opt ...otelattr.KeyValue) { + trace.SpanFromContext(ctx).AddEvent( + event.String(), + trace.WithAttributes( + append( + semconv.AttributesFromContext(ctx), + opt..., + )..., + ), + ) +} From bf0a7411aa7abc10bc1cdff44dad603e8fe21cd4 Mon Sep 17 00:00:00 2001 From: Henning Fleischhauer <18215579+CaptainStandby@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:56:24 +0200 Subject: [PATCH 2/3] refactored the way events are emitted --- selfservice/flow/login/error.go | 9 +-- selfservice/flow/login/hook.go | 13 ++-- selfservice/flow/logout/handler.go | 15 ++--- selfservice/flow/registration/error.go | 10 +--- selfservice/flow/registration/hook.go | 7 +-- selfservice/hook/session_issuer.go | 6 ++ x/events/events.go | 83 ++++++++++++++++++++++---- 7 files changed, 98 insertions(+), 45 deletions(-) diff --git a/selfservice/flow/login/error.go b/selfservice/flow/login/error.go index 195e320170b7..b9bae114ab3c 100644 --- a/selfservice/flow/login/error.go +++ b/selfservice/flow/login/error.go @@ -6,6 +6,8 @@ package login import ( "net/http" + "go.opentelemetry.io/otel/trace" + "github.com/ory/kratos/ui/node" "github.com/ory/kratos/x/events" @@ -81,12 +83,7 @@ func (s *ErrorHandler) WriteFlowError(w http.ResponseWriter, r *http.Request, f WithField("login_flow", f). Info("Encountered self-service login error.") - var flowType flow.Type - if f != nil { - flowType = f.Type - } - - events.Emit(r.Context(), events.LoginFailed, events.AttrFlowType(flowType)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewLoginFailed(r.Context(), f)) if f == nil { s.forward(w, r, nil, err) diff --git a/selfservice/flow/login/hook.go b/selfservice/flow/login/hook.go index ad1b4caedc77..7699148af89e 100644 --- a/selfservice/flow/login/hook.go +++ b/selfservice/flow/login/hook.go @@ -9,6 +9,8 @@ import ( "net/http" "time" + "go.opentelemetry.io/otel/trace" + "github.com/ory/kratos/x/events" "github.com/pkg/errors" @@ -22,7 +24,6 @@ import ( "github.com/ory/kratos/ui/node" "github.com/ory/kratos/x" "github.com/ory/x/otelx" - "github.com/ory/x/otelx/semconv" ) type ( @@ -178,10 +179,7 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("identity_id", i.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Token.") - events.Emit(r.Context(), events.SessionIssued, - semconv.AttrIdentityID(i.ID), - events.AttrSessionID(s.ID), - events.AttrFlowType(a.Type)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID, a)) response := &APIFlowResponse{Session: s, Token: s.Token} if required, _ := e.requiresAAL2(r, classified, a); required { @@ -203,10 +201,7 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("session_id", s.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Cookie.") - events.Emit(r.Context(), events.SessionIssued, - semconv.AttrIdentityID(i.ID), - events.AttrSessionID(s.ID), - events.AttrFlowType(a.Type)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID, a)) if x.IsJSONRequest(r) { // Browser flows rely on cookies. Adding tokens in the mix will confuse consumers. diff --git a/selfservice/flow/logout/handler.go b/selfservice/flow/logout/handler.go index a4271335640b..73c0002c0120 100644 --- a/selfservice/flow/logout/handler.go +++ b/selfservice/flow/logout/handler.go @@ -7,12 +7,13 @@ import ( "net/http" "net/url" - "github.com/ory/kratos/identity" - "github.com/ory/kratos/x/events" - "github.com/ory/x/otelx/semconv" + "go.opentelemetry.io/otel/trace" "github.com/pkg/errors" + "github.com/ory/kratos/identity" + "github.com/ory/kratos/x/events" + "github.com/ory/herodot" "github.com/ory/x/decoderx" "github.com/ory/x/sqlcon" @@ -223,9 +224,7 @@ func (h *Handler) performNativeLogout(w http.ResponseWriter, r *http.Request, _ return } - events.Emit(r.Context(), events.SessionRevoked, - semconv.AttrIdentityID(sess.IdentityID), - events.AttrSessionID(sess.ID)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionRevoked(r.Context(), sess.ID, sess.IdentityID)) w.WriteHeader(http.StatusNoContent) } @@ -304,9 +303,7 @@ func (h *Handler) updateLogoutFlow(w http.ResponseWriter, r *http.Request, ps ht return } - events.Emit(r.Context(), events.SessionRevoked, - semconv.AttrIdentityID(sess.IdentityID), - events.AttrSessionID(sess.ID)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionRevoked(r.Context(), sess.ID, sess.IdentityID)) h.completeLogout(w, r) } diff --git a/selfservice/flow/registration/error.go b/selfservice/flow/registration/error.go index 6a6fc1f87780..2c6b4f607d3a 100644 --- a/selfservice/flow/registration/error.go +++ b/selfservice/flow/registration/error.go @@ -6,6 +6,8 @@ package registration import ( "net/http" + "go.opentelemetry.io/otel/trace" + "github.com/ory/kratos/schema" "github.com/ory/kratos/ui/node" "github.com/ory/kratos/x/events" @@ -87,13 +89,7 @@ func (s *ErrorHandler) WriteFlowError( WithField("registration_flow", f). Info("Encountered self-service flow error.") - var flowType flow.Type - if f != nil { - flowType = f.Type - } - - events.Emit(r.Context(), events.RegistrationFailed, - events.AttrFlowType(flowType)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewRegistrationFailed(r.Context(), f)) if f == nil { s.forward(w, r, nil, err) diff --git a/selfservice/flow/registration/hook.go b/selfservice/flow/registration/hook.go index 5e196dcc4515..648200d23995 100644 --- a/selfservice/flow/registration/hook.go +++ b/selfservice/flow/registration/hook.go @@ -9,11 +9,12 @@ import ( "net/http" "time" + "go.opentelemetry.io/otel/trace" + "github.com/ory/kratos/x/events" "github.com/pkg/errors" - "github.com/ory/x/otelx/semconv" "github.com/ory/x/sqlcon" "github.com/ory/kratos/driver/config" @@ -169,9 +170,7 @@ func (e *HookExecutor) PostRegistrationHook(w http.ResponseWriter, r *http.Reque WithField("identity_id", i.ID). Info("A new identity has registered using self-service registration.") - events.Emit(r.Context(), events.IdentityCreated, - semconv.AttrIdentityID(i.ID), - events.AttrFlowType(a.Type)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewIdentityCreated(r.Context(), i.ID, a)) s, err := session.NewActiveSession(r, i, e.d.Config(), time.Now().UTC(), ct, identity.AuthenticatorAssuranceLevel1) if err != nil { diff --git a/selfservice/hook/session_issuer.go b/selfservice/hook/session_issuer.go index 4aed85284cb8..48c191f91545 100644 --- a/selfservice/hook/session_issuer.go +++ b/selfservice/hook/session_issuer.go @@ -8,6 +8,10 @@ import ( "net/http" "time" + "go.opentelemetry.io/otel/trace" + + "github.com/ory/kratos/x/events" + "github.com/pkg/errors" "github.com/ory/kratos/selfservice/flow" @@ -51,6 +55,8 @@ func (e *SessionIssuer) executePostRegistrationPostPersistHook(w http.ResponseWr return err } + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, s.IdentityID, a)) + if a.Type == flow.TypeAPI { a.AddContinueWith(flow.NewContinueWithSetToken(s.Token)) e.r.Writer().Write(w, r, ®istration.APIFlowResponse{ diff --git a/x/events/events.go b/x/events/events.go index 5aa6229b02d2..84b909b1b1ce 100644 --- a/x/events/events.go +++ b/x/events/events.go @@ -5,12 +5,14 @@ package events import ( "context" + "reflect" "github.com/gofrs/uuid" otelattr "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - "github.com/ory/kratos/selfservice/flow" + f "github.com/ory/kratos/selfservice/flow" + "github.com/ory/x/otelx/semconv" ) @@ -27,23 +29,84 @@ const ( attributeKeySessionID semconv.AttributeKey = "SessionID" ) -func AttrFlowType(val flow.Type) otelattr.KeyValue { +func attrFlowType(val f.Type) otelattr.KeyValue { return otelattr.String(attributeKeyFlowType.String(), string(val)) } -func AttrSessionID(val uuid.UUID) otelattr.KeyValue { +func attrSessionID(val uuid.UUID) otelattr.KeyValue { return otelattr.String(attributeKeySessionID.String(), val.String()) } -// Emit adds an event to the current span in the context. -func Emit(ctx context.Context, event semconv.Event, opt ...otelattr.KeyValue) { - trace.SpanFromContext(ctx).AddEvent( - event.String(), +func NewSessionIssued(ctx context.Context, sessionID, identityID uuid.UUID, flow f.Flow) (string, trace.EventOption) { + var flowType f.Type + if flow != nil && !reflect.ValueOf(flow).IsNil() { + flowType = flow.GetType() + } + + return SessionIssued.String(), + trace.WithAttributes( + append( + semconv.AttributesFromContext(ctx), + semconv.AttrIdentityID(identityID), + attrSessionID(sessionID), + attrFlowType(flowType), + )..., + ) +} + +func NewRegistrationFailed(ctx context.Context, flow f.Flow) (string, trace.EventOption) { + var flowType f.Type + if flow != nil && !reflect.ValueOf(flow).IsNil() { + flowType = flow.GetType() + } + + return RegistrationFailed.String(), + trace.WithAttributes( + append( + semconv.AttributesFromContext(ctx), + attrFlowType(flowType), + )..., + ) +} + +func NewIdentityCreated(ctx context.Context, identityID uuid.UUID, flow f.Flow) (string, trace.EventOption) { + var flowType f.Type + if flow != nil && !reflect.ValueOf(flow).IsNil() { + flowType = flow.GetType() + } + + return IdentityCreated.String(), + trace.WithAttributes( + append( + semconv.AttributesFromContext(ctx), + semconv.AttrIdentityID(identityID), + attrFlowType(flowType), + )..., + ) +} + +func NewLoginFailed(ctx context.Context, flow f.Flow) (string, trace.EventOption) { + var flowType f.Type + if flow != nil && !reflect.ValueOf(flow).IsNil() { + flowType = flow.GetType() + } + + return LoginFailed.String(), + trace.WithAttributes( + append( + semconv.AttributesFromContext(ctx), + attrFlowType(flowType), + )..., + ) +} + +func NewSessionRevoked(ctx context.Context, sessionID, identityID uuid.UUID) (string, trace.EventOption) { + return SessionRevoked.String(), trace.WithAttributes( append( semconv.AttributesFromContext(ctx), - opt..., + semconv.AttrIdentityID(identityID), + attrSessionID(sessionID), )..., - ), - ) + ) } From 3dcd585ce8cc1efc53fc5c1760876baad91dbd77 Mon Sep 17 00:00:00 2001 From: Henning Fleischhauer <18215579+CaptainStandby@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:10:28 +0200 Subject: [PATCH 3/3] remove flow from events --- selfservice/flow/login/error.go | 2 +- selfservice/flow/login/hook.go | 4 +-- selfservice/flow/registration/error.go | 2 +- selfservice/flow/registration/hook.go | 2 +- selfservice/hook/session_issuer.go | 2 +- x/events/events.go | 48 ++++---------------------- 6 files changed, 12 insertions(+), 48 deletions(-) diff --git a/selfservice/flow/login/error.go b/selfservice/flow/login/error.go index b9bae114ab3c..cd1bfa652432 100644 --- a/selfservice/flow/login/error.go +++ b/selfservice/flow/login/error.go @@ -83,7 +83,7 @@ func (s *ErrorHandler) WriteFlowError(w http.ResponseWriter, r *http.Request, f WithField("login_flow", f). Info("Encountered self-service login error.") - trace.SpanFromContext(r.Context()).AddEvent(events.NewLoginFailed(r.Context(), f)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewLoginFailed(r.Context())) if f == nil { s.forward(w, r, nil, err) diff --git a/selfservice/flow/login/hook.go b/selfservice/flow/login/hook.go index 7699148af89e..6dc000dbb0e5 100644 --- a/selfservice/flow/login/hook.go +++ b/selfservice/flow/login/hook.go @@ -179,7 +179,7 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("identity_id", i.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Token.") - trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID, a)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID)) response := &APIFlowResponse{Session: s, Token: s.Token} if required, _ := e.requiresAAL2(r, classified, a); required { @@ -201,7 +201,7 @@ func (e *HookExecutor) PostLoginHook(w http.ResponseWriter, r *http.Request, g n WithField("session_id", s.ID). Info("Identity authenticated successfully and was issued an Ory Kratos Session Cookie.") - trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID, a)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, i.ID)) if x.IsJSONRequest(r) { // Browser flows rely on cookies. Adding tokens in the mix will confuse consumers. diff --git a/selfservice/flow/registration/error.go b/selfservice/flow/registration/error.go index 2c6b4f607d3a..c3281c2027cf 100644 --- a/selfservice/flow/registration/error.go +++ b/selfservice/flow/registration/error.go @@ -89,7 +89,7 @@ func (s *ErrorHandler) WriteFlowError( WithField("registration_flow", f). Info("Encountered self-service flow error.") - trace.SpanFromContext(r.Context()).AddEvent(events.NewRegistrationFailed(r.Context(), f)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewRegistrationFailed(r.Context())) if f == nil { s.forward(w, r, nil, err) diff --git a/selfservice/flow/registration/hook.go b/selfservice/flow/registration/hook.go index 648200d23995..d5a3a489e8ec 100644 --- a/selfservice/flow/registration/hook.go +++ b/selfservice/flow/registration/hook.go @@ -170,7 +170,7 @@ func (e *HookExecutor) PostRegistrationHook(w http.ResponseWriter, r *http.Reque WithField("identity_id", i.ID). Info("A new identity has registered using self-service registration.") - trace.SpanFromContext(r.Context()).AddEvent(events.NewIdentityCreated(r.Context(), i.ID, a)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewIdentityCreated(r.Context(), i.ID)) s, err := session.NewActiveSession(r, i, e.d.Config(), time.Now().UTC(), ct, identity.AuthenticatorAssuranceLevel1) if err != nil { diff --git a/selfservice/hook/session_issuer.go b/selfservice/hook/session_issuer.go index 48c191f91545..84177a28b419 100644 --- a/selfservice/hook/session_issuer.go +++ b/selfservice/hook/session_issuer.go @@ -55,7 +55,7 @@ func (e *SessionIssuer) executePostRegistrationPostPersistHook(w http.ResponseWr return err } - trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, s.IdentityID, a)) + trace.SpanFromContext(r.Context()).AddEvent(events.NewSessionIssued(r.Context(), s.ID, s.IdentityID)) if a.Type == flow.TypeAPI { a.AddContinueWith(flow.NewContinueWithSetToken(s.Token)) diff --git a/x/events/events.go b/x/events/events.go index 84b909b1b1ce..ac64d5454b8b 100644 --- a/x/events/events.go +++ b/x/events/events.go @@ -5,14 +5,11 @@ package events import ( "context" - "reflect" "github.com/gofrs/uuid" otelattr "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - f "github.com/ory/kratos/selfservice/flow" - "github.com/ory/x/otelx/semconv" ) @@ -25,78 +22,45 @@ const ( ) const ( - attributeKeyFlowType semconv.AttributeKey = "FlowType" attributeKeySessionID semconv.AttributeKey = "SessionID" ) -func attrFlowType(val f.Type) otelattr.KeyValue { - return otelattr.String(attributeKeyFlowType.String(), string(val)) -} - func attrSessionID(val uuid.UUID) otelattr.KeyValue { return otelattr.String(attributeKeySessionID.String(), val.String()) } -func NewSessionIssued(ctx context.Context, sessionID, identityID uuid.UUID, flow f.Flow) (string, trace.EventOption) { - var flowType f.Type - if flow != nil && !reflect.ValueOf(flow).IsNil() { - flowType = flow.GetType() - } - +func NewSessionIssued(ctx context.Context, sessionID, identityID uuid.UUID) (string, trace.EventOption) { return SessionIssued.String(), trace.WithAttributes( append( semconv.AttributesFromContext(ctx), semconv.AttrIdentityID(identityID), attrSessionID(sessionID), - attrFlowType(flowType), )..., ) } -func NewRegistrationFailed(ctx context.Context, flow f.Flow) (string, trace.EventOption) { - var flowType f.Type - if flow != nil && !reflect.ValueOf(flow).IsNil() { - flowType = flow.GetType() - } - +func NewRegistrationFailed(ctx context.Context) (string, trace.EventOption) { return RegistrationFailed.String(), trace.WithAttributes( - append( - semconv.AttributesFromContext(ctx), - attrFlowType(flowType), - )..., + semconv.AttributesFromContext(ctx)..., ) } -func NewIdentityCreated(ctx context.Context, identityID uuid.UUID, flow f.Flow) (string, trace.EventOption) { - var flowType f.Type - if flow != nil && !reflect.ValueOf(flow).IsNil() { - flowType = flow.GetType() - } - +func NewIdentityCreated(ctx context.Context, identityID uuid.UUID) (string, trace.EventOption) { return IdentityCreated.String(), trace.WithAttributes( append( semconv.AttributesFromContext(ctx), semconv.AttrIdentityID(identityID), - attrFlowType(flowType), )..., ) } -func NewLoginFailed(ctx context.Context, flow f.Flow) (string, trace.EventOption) { - var flowType f.Type - if flow != nil && !reflect.ValueOf(flow).IsNil() { - flowType = flow.GetType() - } - +func NewLoginFailed(ctx context.Context) (string, trace.EventOption) { return LoginFailed.String(), trace.WithAttributes( - append( - semconv.AttributesFromContext(ctx), - attrFlowType(flowType), - )..., + semconv.AttributesFromContext(ctx)..., ) }