Skip to content

Commit

Permalink
feat: emit admin recovery code event
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Nov 28, 2024
1 parent f7ddaae commit dfb5543
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 33 deletions.
9 changes: 6 additions & 3 deletions selfservice/strategy/code/strategy_recovery_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import (
"net/http"
"net/url"
"time"

"github.com/gobuffalo/pop/v6"

"go.opentelemetry.io/otel/trace"
"github.com/ory/kratos/x/events"
"github.com/gofrs/uuid"
"github.com/julienschmidt/httprouter"
"github.com/pkg/errors"

"github.com/ory/herodot"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/selfservice/flow"
Expand Down Expand Up @@ -223,6 +222,10 @@ func (s *Strategy) createRecoveryCodeForIdentity(w http.ResponseWriter, r *http.
return
}

trace.SpanFromContext(r.Context()).AddEvent(
events.NewRecoveryCodeCreatedByAdmin(ctx, recoveryFlow.ID, id.ID, flowType.String(), "code"),
)

s.deps.Audit().
WithField("identity_id", id.ID).
WithSensitiveField("recovery_code", rawCode).
Expand Down
20 changes: 12 additions & 8 deletions selfservice/strategy/link/strategy_recovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,19 @@ import (
"net/http"
"net/url"
"time"

"go.opentelemetry.io/otel/trace"
"github.com/ory/kratos/x/events"
"github.com/gobuffalo/pop/v6"

"github.com/gofrs/uuid"
"github.com/julienschmidt/httprouter"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"

"github.com/ory/herodot"
"github.com/ory/x/decoderx"
"github.com/ory/x/otelx"
"github.com/ory/x/sqlcon"
"github.com/ory/x/sqlxx"
"github.com/ory/x/urlx"

"github.com/ory/kratos/identity"
"github.com/ory/kratos/schema"
"github.com/ory/kratos/selfservice/flow"
Expand Down Expand Up @@ -146,13 +144,15 @@ type recoveryLinkForIdentity struct {
// 404: errorGeneric
// default: errorGeneric
func (s *Strategy) createRecoveryLinkForIdentity(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
ctx := r.Context()

var p createRecoveryLinkForIdentityBody
if err := s.dx.Decode(r, &p, decoderx.HTTPJSONDecoder()); err != nil {
s.d.Writer().WriteError(w, r, err)
return
}

expiresIn := s.d.Config().SelfServiceLinkMethodLifespan(r.Context())
expiresIn := s.d.Config().SelfServiceLinkMethodLifespan(ctx)
if len(p.ExpiresIn) > 0 {
var err error
expiresIn, err = time.ParseDuration(p.ExpiresIn)
Expand All @@ -173,7 +173,7 @@ func (s *Strategy) createRecoveryLinkForIdentity(w http.ResponseWriter, r *http.
return
}

id, err := s.d.IdentityPool().GetIdentity(r.Context(), p.IdentityID, identity.ExpandDefault)
id, err := s.d.IdentityPool().GetIdentity(ctx, p.IdentityID, identity.ExpandDefault)
if errors.Is(err, sqlcon.ErrNoRows) {
s.d.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest.WithReasonf("The requested identity id does not exist.").WithWrap(err)))
return
Expand All @@ -183,7 +183,7 @@ func (s *Strategy) createRecoveryLinkForIdentity(w http.ResponseWriter, r *http.
}

token := NewAdminRecoveryToken(id.ID, req.ID, expiresIn)
if err := s.d.TransactionalPersisterProvider().Transaction(r.Context(), func(ctx context.Context, c *pop.Connection) error {
if err := s.d.TransactionalPersisterProvider().Transaction(ctx, func(ctx context.Context, c *pop.Connection) error {
if err := s.d.RecoveryFlowPersister().CreateRecoveryFlow(ctx, req); err != nil {
return err
}
Expand All @@ -194,6 +194,10 @@ func (s *Strategy) createRecoveryLinkForIdentity(w http.ResponseWriter, r *http.
return
}

trace.SpanFromContext(ctx).AddEvent(
events.NewRecoveryCodeCreatedByAdmin(ctx, req.ID, id.ID, req.Type.String(), "link"),
)

s.d.Audit().
WithField("identity_id", id.ID).
WithSensitiveField("recovery_link_token", token).
Expand All @@ -202,7 +206,7 @@ func (s *Strategy) createRecoveryLinkForIdentity(w http.ResponseWriter, r *http.
s.d.Writer().Write(w, r, &recoveryLinkForIdentity{
ExpiresAt: req.ExpiresAt.UTC(),
RecoveryLink: urlx.CopyWithQuery(
urlx.AppendPaths(s.d.Config().SelfPublicURL(r.Context()), recovery.RouteSubmitFlow),
urlx.AppendPaths(s.d.Config().SelfPublicURL(ctx), recovery.RouteSubmitFlow),
url.Values{
"token": {token.Token},
"flow": {req.ID.String()},
Expand Down
56 changes: 34 additions & 22 deletions x/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,29 @@ import (
)

const (
SessionIssued semconv.Event = "SessionIssued"
SessionChanged semconv.Event = "SessionChanged"
SessionLifespanExtended semconv.Event = "SessionLifespanExtended"
SessionRevoked semconv.Event = "SessionRevoked"
SessionChecked semconv.Event = "SessionChecked"
SessionTokenizedAsJWT semconv.Event = "SessionTokenizedAsJWT"
RegistrationFailed semconv.Event = "RegistrationFailed"
RegistrationSucceeded semconv.Event = "RegistrationSucceeded"
LoginFailed semconv.Event = "LoginFailed"
LoginSucceeded semconv.Event = "LoginSucceeded"
SettingsFailed semconv.Event = "SettingsFailed"
SettingsSucceeded semconv.Event = "SettingsSucceeded"
RecoveryFailed semconv.Event = "RecoveryFailed"
RecoverySucceeded semconv.Event = "RecoverySucceeded"
VerificationFailed semconv.Event = "VerificationFailed"
VerificationSucceeded semconv.Event = "VerificationSucceeded"
IdentityCreated semconv.Event = "IdentityCreated"
IdentityUpdated semconv.Event = "IdentityUpdated"
IdentityDeleted semconv.Event = "IdentityDeleted"
WebhookDelivered semconv.Event = "WebhookDelivered"
WebhookSucceeded semconv.Event = "WebhookSucceeded"
WebhookFailed semconv.Event = "WebhookFailed"
SessionIssued semconv.Event = "SessionIssued"
SessionChanged semconv.Event = "SessionChanged"
SessionLifespanExtended semconv.Event = "SessionLifespanExtended"
SessionRevoked semconv.Event = "SessionRevoked"
SessionChecked semconv.Event = "SessionChecked"
SessionTokenizedAsJWT semconv.Event = "SessionTokenizedAsJWT"
RegistrationFailed semconv.Event = "RegistrationFailed"
RegistrationSucceeded semconv.Event = "RegistrationSucceeded"
LoginFailed semconv.Event = "LoginFailed"
LoginSucceeded semconv.Event = "LoginSucceeded"
SettingsFailed semconv.Event = "SettingsFailed"
SettingsSucceeded semconv.Event = "SettingsSucceeded"
RecoveryFailed semconv.Event = "RecoveryFailed"
RecoverySucceeded semconv.Event = "RecoverySucceeded"
RecoveryCodeCreatedByAdmin semconv.Event = "RecoveryCodeCreatedByAdmin"
VerificationFailed semconv.Event = "VerificationFailed"
VerificationSucceeded semconv.Event = "VerificationSucceeded"
IdentityCreated semconv.Event = "IdentityCreated"
IdentityUpdated semconv.Event = "IdentityUpdated"
IdentityDeleted semconv.Event = "IdentityDeleted"
WebhookDelivered semconv.Event = "WebhookDelivered"
WebhookSucceeded semconv.Event = "WebhookSucceeded"
WebhookFailed semconv.Event = "WebhookFailed"
)

const (
Expand Down Expand Up @@ -223,6 +224,17 @@ func NewRecoverySucceeded(ctx context.Context, flowID, identityID uuid.UUID, flo
)...)
}

func NewRecoveryCodeCreatedByAdmin(ctx context.Context, flowID, identityID uuid.UUID, flowType, method string) (string, trace.EventOption) {
return RecoveryCodeCreatedByAdmin.String(),
trace.WithAttributes(append(
semconv.AttributesFromContext(ctx),
attrSelfServiceFlowType(flowType),
semconv.AttrIdentityID(identityID),
attrSelfServiceMethodUsed(method),
attrFlowID(flowID),
)...)
}

func NewSettingsSucceeded(ctx context.Context, flowID, identityID uuid.UUID, flowType, method string) (string, trace.EventOption) {
return SettingsSucceeded.String(),
trace.WithAttributes(append(
Expand Down

0 comments on commit dfb5543

Please sign in to comment.