feat: add tracing interceptors to login and oidc (#764)

* add tracing interceptors to login and oidc

* add some tracing spans

* trace login calls

* add some spans

* add some spans (change password)

* add some more tracing in oauth/oidc

* revert org exists

* Merge branch 'master' into http-tracing

# Conflicts:
#	internal/api/oidc/auth_request.go
#	internal/api/oidc/client.go
#	internal/auth/repository/eventsourcing/eventstore/auth_request.go
#	internal/auth/repository/eventsourcing/eventstore/user.go
#	internal/authz/repository/eventsourcing/eventstore/token_verifier.go
#	internal/authz/repository/eventsourcing/view/token.go
#	internal/user/repository/eventsourcing/eventstore.go
This commit is contained in:
Livio Amstutz 2020-10-21 10:18:34 +02:00 committed by GitHub
parent 6e602e6b8d
commit b3f68c8f48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 228 additions and 75 deletions

View File

@ -7,14 +7,18 @@ import (
"strings"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
const (
authenticated = "authenticated"
)
func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID string, verifier *TokenVerifier, authConfig Config, requiredAuthOption Option, method string) (context.Context, error) {
ctx, err := VerifyTokenAndWriteCtxData(ctx, token, orgID, verifier, method)
func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID string, verifier *TokenVerifier, authConfig Config, requiredAuthOption Option, method string) (_ context.Context, err error) {
ctx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }()
ctx, err = VerifyTokenAndWriteCtxData(ctx, token, orgID, verifier, method)
if err != nil {
return nil, err
}
@ -29,7 +33,9 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
return nil, err
}
ctx, userPermissionSpan := tracing.NewNamedSpan(ctx, "checkUserPermissions")
err = checkUserPermissions(req, perms, requiredAuthOption)
userPermissionSpan.EndWithError(err)
if err != nil {
return nil, err
}

View File

@ -6,6 +6,7 @@ import (
"github.com/caos/zitadel/internal/api/grpc"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
type key int
@ -36,6 +37,9 @@ type Grant struct {
}
func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t *TokenVerifier, method string) (_ context.Context, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
if orgID != "" {
err = t.ExistsOrg(ctx, orgID)
if err != nil {

View File

@ -4,9 +4,13 @@ import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (context.Context, []string, error) {
func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (_ context.Context, _ []string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
ctxData := GetCtxData(ctx)
if ctxData.IsZero() {
return nil, nil, errors.ThrowUnauthenticated(nil, "AUTH-rKLWEH", "context missing")

View File

@ -6,6 +6,7 @@ import (
"sync"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
const (
@ -62,7 +63,10 @@ func prefixFromMethod(method string) (string, bool) {
return parts[1], true
}
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (string, error) {
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (_ string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
prefix, ok := prefixFromMethod(method)
if !ok {
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-GRD2Q", "Errors.Internal")
@ -71,7 +75,6 @@ func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (
if !ok {
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-G2qrh", "Errors.Internal")
}
var err error
c := app.(*client)
if c.id != "" {
return c.id, nil
@ -84,15 +87,22 @@ func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (
return c.id, nil
}
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (*Grant, error) {
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (_ *Grant, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ResolveGrants(ctx)
}
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (_ string, _ []string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ProjectIDAndOriginsByClientID(ctx, clientID)
}
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) error {
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ExistsOrg(ctx, orgID)
}
@ -102,6 +112,9 @@ func (v *TokenVerifier) CheckAuthMethod(method string) (Option, bool) {
}
func verifyAccessToken(ctx context.Context, token string, t *TokenVerifier, method string) (userID, clientID, agentID, prefLang string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
parts := strings.Split(token, BearerPrefix)
if len(parts) != 2 {
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header")

View File

@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
"github.com/caos/zitadel/internal/api/http"
grpc_utils "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/tracing"
)
@ -29,7 +29,7 @@ func TracingStatsClient(ignoredMethods ...GRPCMethod) grpc.DialOption {
}
func DefaultTracingStatsClient() grpc.DialOption {
return TracingStatsClient(http.Healthz, http.Readiness, http.Validation)
return TracingStatsClient(grpc_utils.Healthz, grpc_utils.Readiness, grpc_utils.Validation)
}
type tracingClientHandler struct {

View File

@ -30,6 +30,9 @@ func CaosToGRPCError(ctx context.Context, err error) error {
}
func ExtractCaosError(err error) (c codes.Code, msg, id string, ok bool) {
if err == nil {
return codes.OK, "", "", false
}
switch caosErr := err.(type) {
case *caos_errs.AlreadyExistsError:
return codes.AlreadyExists, caosErr.GetMessage(), caosErr.GetID(), true

View File

@ -0,0 +1,11 @@
package grpc
const (
Healthz = "/Healthz"
Readiness = "/Ready"
Validation = "/Validate"
)
var (
Probes = []string{Healthz, Readiness, Validation}
)

View File

@ -10,6 +10,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/tracing"
)
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor {
@ -18,9 +19,13 @@ func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Co
}
}
func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier *authz.TokenVerifier, authConfig authz.Config) (interface{}, error) {
func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier *authz.TokenVerifier, authConfig authz.Config) (_ interface{}, err error) {
ctx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }()
authOpt, needsToken := verifier.CheckAuthMethod(info.FullMethod)
if !needsToken {
span.End()
return handler(ctx, req)
}
@ -31,10 +36,10 @@ func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
orgID := grpc_util.GetHeader(ctx, http.ZitadelOrgID)
ctx, err := authz.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt, info.FullMethod)
ctx, err = authz.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt, info.FullMethod)
if err != nil {
return nil, err
}
span.End()
return handler(ctx, req)
}

View File

@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
"github.com/caos/zitadel/internal/api/http"
grpc_utils "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/tracing"
)
@ -30,7 +30,7 @@ func TracingStatsServer(ignoredMethods ...GRPCMethod) grpc.ServerOption {
}
func DefaultTracingStatsServer() grpc.ServerOption {
return TracingStatsServer(http.Healthz, http.Readiness, http.Validation)
return TracingStatsServer(grpc_utils.Healthz, grpc_utils.Readiness, grpc_utils.Validation)
}
type tracingServerHandler struct {

View File

@ -27,7 +27,7 @@ type Server interface {
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server {
return grpc.NewServer(
middleware.TracingStatsServer(http.Healthz, http.Readiness, http.Validation),
middleware.DefaultTracingStatsServer(),
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer(
middleware.ErrorHandler(),

View File

@ -10,3 +10,9 @@ import (
func DefaultTraceHandler(handler http.Handler) http.Handler {
return tracing.TraceHandler(handler, http_utils.Probes...)
}
func TraceHandler(ignoredMethods ...string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return tracing.TraceHandler(handler, ignoredMethods...)
}
}

View File

@ -1,9 +1,9 @@
package http
const (
Healthz = "/Healthz"
Readiness = "/Ready"
Validation = "/Validate"
Healthz = "/healthz"
Readiness = "/ready"
Validation = "/validate"
)
var (

View File

@ -13,10 +13,13 @@ import (
"github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/errors"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/tracing"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)
func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, userID string) (op.AuthRequest, error) {
func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, userID string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
@ -37,7 +40,9 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (op.AuthRequest, error) {
func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-D3g21", "no user agent id")
@ -49,7 +54,9 @@ func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (op.AuthRequ
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (op.AuthRequest, error) {
func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
resp, err := o.repo.AuthRequestByCode(ctx, code)
if err != nil {
return nil, err
@ -57,7 +64,9 @@ func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (op.Auth
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) error {
func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return errors.ThrowPreconditionFailed(nil, "OIDC-Dgus2", "no user agent id")
@ -65,11 +74,15 @@ func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) error {
return o.repo.SaveAuthCode(ctx, id, code, userAgentID)
}
func (o *OPStorage) DeleteAuthRequest(ctx context.Context, id string) error {
func (o *OPStorage) DeleteAuthRequest(ctx context.Context, id string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return o.repo.DeleteAuthRequest(ctx, id)
}
func (o *OPStorage) CreateToken(ctx context.Context, req op.TokenRequest) (string, time.Time, error) {
func (o *OPStorage) CreateToken(ctx context.Context, req op.TokenRequest) (_ string, _ time.Time, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
var userAgentID, applicationID string
authReq, ok := req.(*AuthRequest)
if ok {
@ -93,7 +106,9 @@ func grantsToScopes(grants []*grant_model.UserGrantView) []string {
return scopes
}
func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID string) error {
func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return errors.ThrowPreconditionFailed(nil, "OIDC-fso7F", "no user agent id")
@ -105,7 +120,9 @@ func (o *OPStorage) GetSigningKey(ctx context.Context, keyCh chan<- jose.Signing
o.repo.GetSigningKey(ctx, keyCh, errCh, timer)
}
func (o *OPStorage) GetKeySet(ctx context.Context) (*jose.JSONWebKeySet, error) {
func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return o.repo.GetKeySet(ctx)
}

View File

@ -15,6 +15,7 @@ import (
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)
@ -32,7 +33,9 @@ const (
oidcCtx = "oidc"
)
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (op.Client, error) {
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Client, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
client, err := o.repo.ApplicationByClientID(ctx, id)
if err != nil {
return nil, err
@ -51,7 +54,9 @@ func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (op.Clie
return ClientFromBusiness(client, o.defaultLoginURL, o.defaultAccessTokenLifetime, o.defaultIdTokenLifetime, allowedScopes)
}
func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (*jose.JSONWebKey, error) {
func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (_ *jose.JSONWebKey, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
key, err := o.repo.MachineKeyByID(ctx, keyID)
if err != nil {
return nil, err
@ -70,7 +75,9 @@ func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID strin
}, nil
}
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) error {
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
ctx = authz.SetCtxData(ctx, authz.CtxData{
UserID: oidcCtx,
OrgID: oidcCtx,
@ -78,7 +85,9 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr
return o.repo.AuthorizeOIDCApplication(ctx, id, secret)
}
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, subject, origin string) (oidc.UserInfo, error) {
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, subject, origin string) (_ oidc.UserInfo, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
token, err := o.repo.TokenByID(ctx, subject, tokenID)
if err != nil {
return nil, errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
@ -95,7 +104,9 @@ func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, subject,
return o.GetUserinfoFromScopes(ctx, token.UserID, token.ApplicationID, token.Scopes)
}
func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID, applicationID string, scopes []string) (oidc.UserInfo, error) {
func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID, applicationID string, scopes []string) (_ oidc.UserInfo, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
user, err := o.repo.UserByID(ctx, userID)
if err != nil {
return nil, err

View File

@ -59,6 +59,7 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, repo repository.Re
config.OPConfig,
newStorage(config.StorageConfig, repo),
op.WithHttpInterceptors(
middleware.TraceHandler(),
middleware.NoCacheInterceptor,
cookieHandler,
http_utils.CopyHeadersToContext,

View File

@ -21,6 +21,7 @@ import (
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
project_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
"github.com/caos/zitadel/internal/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@ -91,7 +92,9 @@ func (repo *AuthRequestRepo) Health(ctx context.Context) error {
return repo.AuthRequests.Health(ctx)
}
func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *model.AuthRequest) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *model.AuthRequest) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
reqID, err := repo.IdGenerator.Next()
if err != nil {
return nil, err
@ -117,15 +120,21 @@ func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *mod
return request, nil
}
func (repo *AuthRequestRepo) AuthRequestByID(ctx context.Context, id, userAgentID string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByID(ctx context.Context, id, userAgentID string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.getAuthRequestNextSteps(ctx, id, userAgentID, false)
}
func (repo *AuthRequestRepo) AuthRequestByIDCheckLoggedIn(ctx context.Context, id, userAgentID string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByIDCheckLoggedIn(ctx context.Context, id, userAgentID string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.getAuthRequestNextSteps(ctx, id, userAgentID, true)
}
func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAgentID string) error {
func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@ -134,7 +143,9 @@ func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAge
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.AuthRequests.GetAuthRequestByCode(ctx, code)
if err != nil {
return nil, err
@ -147,11 +158,15 @@ func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string)
return request, nil
}
func (repo *AuthRequestRepo) DeleteAuthRequest(ctx context.Context, id string) error {
func (repo *AuthRequestRepo) DeleteAuthRequest(ctx context.Context, id string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.AuthRequests.DeleteAuthRequest(ctx, id)
}
func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName, userAgentID string) error {
func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@ -163,7 +178,9 @@ func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName,
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error {
func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@ -175,7 +192,9 @@ func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, i
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, externalUser *model.ExternalUser, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, externalUser *model.ExternalUser, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@ -203,7 +222,9 @@ func (repo *AuthRequestRepo) setLinkingUser(ctx context.Context, request *model.
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAgentID string) error {
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@ -216,7 +237,9 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, password, userAgentID string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, password, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@ -227,7 +250,9 @@ func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, pas
return repo.UserEvents.CheckPassword(ctx, userID, password, request.WithCurrentInfo(info))
}
func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, userID, code, userAgentID string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, userID, code, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authRequestID, userAgentID)
if err != nil {
return err
@ -238,7 +263,9 @@ func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, us
return repo.UserEvents.CheckMfaOTP(ctx, userID, code, request.WithCurrentInfo(info))
}
func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, userAgentID string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@ -265,7 +292,9 @@ func (repo *AuthRequestRepo) ResetLinkingUsers(ctx context.Context, authReqID, u
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, registerUser *user_model.User, externalIDP *user_model.ExternalIDP, orgMember *org_model.OrgMember, authReqID, userAgentID, resourceOwner string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, registerUser *user_model.User, externalIDP *user_model.ExternalIDP, orgMember *org_model.OrgMember, authReqID, userAgentID, resourceOwner string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err

View File

@ -2,6 +2,7 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
@ -15,6 +16,7 @@ import (
"github.com/caos/zitadel/internal/eventstore/sdk"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@ -236,7 +238,9 @@ func (repo *UserRepo) ChangeMyPassword(ctx context.Context, old, new string) err
return err
}
func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new string) error {
func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)

View File

@ -14,6 +14,7 @@ import (
caos_errs "github.com/caos/zitadel/internal/errors"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/tracing"
)
type TokenVerifierRepo struct {
@ -59,6 +60,8 @@ func (repo *TokenVerifierRepo) TokenByID(ctx context.Context, tokenID, userID st
}
func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenString, clientID string) (userID string, agentID string, prefLang string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
//TODO: use real key
tokenIDSubject, err := crypto.DecryptAESString(tokenString, string(repo.TokenVerificationKey[:32]))
if err != nil {
@ -98,12 +101,15 @@ func (repo *TokenVerifierRepo) ExistsOrg(ctx context.Context, orgID string) erro
return err
}
func (repo *TokenVerifierRepo) VerifierClientID(ctx context.Context, appName string) (string, error) {
func (repo *TokenVerifierRepo) VerifierClientID(ctx context.Context, appName string) (_ string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
iam, err := repo.IAMEvents.IAMByID(ctx, repo.IAMID)
if err != nil {
return "", err
}
app, err := repo.View.ApplicationByProjecIDAndAppName(iam.IAMProjectID, appName)
app, err := repo.View.ApplicationByProjecIDAndAppName(ctx, iam.IAMProjectID, appName)
if err != nil {
return "", err
}

View File

@ -1,9 +1,12 @@
package view
import (
"context"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/project/repository/view"
"github.com/caos/zitadel/internal/project/repository/view/model"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/view/repository"
)
@ -19,7 +22,10 @@ func (v *View) ApplicationByOIDCClientID(clientID string) (*model.ApplicationVie
return view.ApplicationByOIDCClientID(v.Db, applicationTable, clientID)
}
func (v *View) ApplicationByProjecIDAndAppName(projectID, appName string) (*model.ApplicationView, error) {
func (v *View) ApplicationByProjecIDAndAppName(ctx context.Context, projectID, appName string) (_ *model.ApplicationView, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return view.ApplicationByProjectIDAndAppName(v.Db, applicationTable, projectID, appName)
}

View File

@ -13,6 +13,7 @@ import (
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/tracing"
)
type IAMEventstore struct {
@ -45,7 +46,10 @@ func StartIAM(conf IAMConfig, systemDefaults sd.SystemDefaults) (*IAMEventstore,
}, nil
}
func (es *IAMEventstore) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) {
func (es *IAMEventstore) IAMByID(ctx context.Context, id string) (_ *iam_model.IAM, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
iam := es.iamCache.getIAM(id)
query, err := IAMByIDQuery(iam.AggregateID, iam.Sequence)

View File

@ -1,11 +1,12 @@
package view
import (
"github.com/jinzhu/gorm"
caos_errs "github.com/caos/zitadel/internal/errors"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
"github.com/jinzhu/gorm"
)
func OrgByID(db *gorm.DB, table, orgID string) (*model.OrgView, error) {

View File

@ -8,9 +8,7 @@ import (
"go.opencensus.io/trace"
)
func TraceHandler(handler http.Handler, ignoredMethods ...string) http.Handler {
healthEndpoints := strings.Join(ignoredMethods, ";;")
func TraceHandler(handler http.Handler, ignoredEndpoints ...string) http.Handler {
return &ochttp.Handler{
Handler: handler,
FormatSpanName: func(r *http.Request) string {
@ -23,8 +21,12 @@ func TraceHandler(handler http.Handler, ignoredMethods ...string) http.Handler {
StartOptions: trace.StartOptions{Sampler: Sampler()},
IsHealthEndpoint: func(r *http.Request) bool {
n := strings.Contains(healthEndpoints, r.URL.RequestURI())
return n
for _, endpoint := range ignoredEndpoints {
if strings.HasPrefix(r.URL.RequestURI(), endpoint) {
return true
}
}
return false
},
}
}

View File

@ -38,6 +38,13 @@ func NewSpan(ctx context.Context) (context.Context, *Span) {
return T.NewSpan(ctx, GetCaller())
}
func NewNamedSpan(ctx context.Context, name string) (context.Context, *Span) {
if T == nil {
return ctx, CreateSpan(nil)
}
return T.NewSpan(ctx, name)
}
func NewClientSpan(ctx context.Context) (context.Context, *Span) {
if T == nil {
return ctx, CreateSpan(nil)
@ -52,18 +59,18 @@ func NewServerSpan(ctx context.Context) (context.Context, *Span) {
return T.NewServerSpan(ctx, GetCaller())
}
func NewClientInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) {
func NewClientInterceptorSpan(ctx context.Context) (context.Context, *Span) {
if T == nil {
return ctx, CreateSpan(nil)
}
return T.NewClientInterceptorSpan(ctx, name)
return T.NewClientInterceptorSpan(ctx, GetCaller())
}
func NewServerInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) {
func NewServerInterceptorSpan(ctx context.Context) (context.Context, *Span) {
if T == nil {
return ctx, CreateSpan(nil)
}
return T.NewServerInterceptorSpan(ctx, name)
return T.NewServerInterceptorSpan(ctx, GetCaller())
}
func NewSpanHTTP(r *http.Request) (*http.Request, *Span) {

View File

@ -19,7 +19,6 @@ import (
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/form"
"github.com/caos/zitadel/internal/id"
_ "github.com/caos/zitadel/internal/ui/login/statik"
)
@ -83,7 +82,7 @@ func CreateLogin(config Config, authRepo *eventsourcing.EsRepository, systemDefa
security := middleware.SecurityHeaders(csp(), login.cspErrorHandler)
userAgentCookie, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode)
logging.Log("CONFI-Dvwf2").OnError(err).Panic("unable to create userAgentInterceptor")
login.router = CreateRouter(login, statikFS, csrf, cache, security, userAgentCookie)
login.router = CreateRouter(login, statikFS, csrf, cache, security, userAgentCookie, middleware.TraceHandler(EndpointResources))
login.renderer = CreateRenderer(prefix, statikFS, config.LanguageCookieName, config.DefaultLanguage)
login.parser = form.NewParser()
return login, handlerPrefix

View File

@ -3,25 +3,25 @@ package eventsourcing
import (
"context"
"fmt"
iam_model "github.com/caos/zitadel/internal/iam/model"
"time"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/id"
"github.com/pquerna/otp/totp"
req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/cache/config"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/id"
global_model "github.com/caos/zitadel/internal/model"
"github.com/caos/zitadel/internal/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
@ -554,7 +554,9 @@ func (es *UserEventstore) UserPasswordByID(ctx context.Context, userID string) (
return nil, caos_errs.ThrowNotFound(nil, "EVENT-d8e2", "Errors.User.Password.NotFound")
}
func (es *UserEventstore) CheckPassword(ctx context.Context, userID, password string, authRequest *req_model.AuthRequest) error {
func (es *UserEventstore) CheckPassword(ctx context.Context, userID, password string, authRequest *req_model.AuthRequest) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
user, err := es.UserByID(ctx, userID)
if err != nil {
return err
@ -565,7 +567,10 @@ func (es *UserEventstore) CheckPassword(ctx context.Context, userID, password st
if user.Password == nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-s35Fa", "Errors.User.Password.Empty")
}
if err := crypto.CompareHash(user.Password.SecretCrypto, []byte(password), es.PasswordAlg); err == nil {
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
err = crypto.CompareHash(user.Password.SecretCrypto, []byte(password), es.PasswordAlg)
spanPasswordComparison.EndWithError(err)
if err == nil {
return es.setPasswordCheckResult(ctx, user, authRequest, PasswordCheckSucceededAggregate)
}
if err := es.setPasswordCheckResult(ctx, user, authRequest, PasswordCheckFailedAggregate); err != nil {
@ -574,11 +579,13 @@ func (es *UserEventstore) CheckPassword(ctx context.Context, userID, password st
return caos_errs.ThrowInvalidArgument(nil, "EVENT-452ad", "Errors.User.Password.Invalid")
}
func (es *UserEventstore) setPasswordCheckResult(ctx context.Context, user *usr_model.User, authRequest *req_model.AuthRequest, check func(*es_models.AggregateCreator, *model.User, *model.AuthRequest) es_sdk.AggregateFunc) error {
func (es *UserEventstore) setPasswordCheckResult(ctx context.Context, user *usr_model.User, authRequest *req_model.AuthRequest, check func(*es_models.AggregateCreator, *model.User, *model.AuthRequest) es_sdk.AggregateFunc) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
repoUser := model.UserFromModel(user)
repoAuthRequest := model.AuthRequestFromModel(authRequest)
agg := check(es.AggregateCreator(), repoUser, repoAuthRequest)
err := es_sdk.Push(ctx, es.PushAggregates, repoUser.AppendEvents, agg)
err = es_sdk.Push(ctx, es.PushAggregates, repoUser.AppendEvents, agg)
if err != nil {
return err
}
@ -677,7 +684,9 @@ func (es *UserEventstore) ChangeMachine(ctx context.Context, machine *usr_model.
return model.MachineToModel(repoUser.Machine), nil
}
func (es *UserEventstore) ChangePassword(ctx context.Context, policy *iam_model.PasswordComplexityPolicyView, userID, old, new string) (*usr_model.Password, error) {
func (es *UserEventstore) ChangePassword(ctx context.Context, policy *iam_model.PasswordComplexityPolicyView, userID, old, new string) (_ *usr_model.Password, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
user, err := es.UserByID(ctx, userID)
if err != nil {
return nil, err
@ -688,15 +697,20 @@ func (es *UserEventstore) ChangePassword(ctx context.Context, policy *iam_model.
if user.Password == nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-Fds3s", "Errors.User.Password.Empty")
}
if err := crypto.CompareHash(user.Password.SecretCrypto, []byte(old), es.PasswordAlg); err != nil {
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
err = crypto.CompareHash(user.Password.SecretCrypto, []byte(old), es.PasswordAlg)
spanPasswordComparison.EndWithError(err)
if err != nil {
return nil, caos_errs.ThrowInvalidArgument(nil, "EVENT-s56a3", "Errors.User.Password.Invalid")
}
return es.changedPassword(ctx, user, policy, new, false)
}
func (es *UserEventstore) changedPassword(ctx context.Context, user *usr_model.User, policy *iam_model.PasswordComplexityPolicyView, password string, onetime bool) (*usr_model.Password, error) {
func (es *UserEventstore) changedPassword(ctx context.Context, user *usr_model.User, policy *iam_model.PasswordComplexityPolicyView, password string, onetime bool) (_ *usr_model.Password, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
pw := &usr_model.Password{SecretString: password}
err := pw.HashPasswordIfExisting(policy, es.PasswordAlg, onetime)
err = pw.HashPasswordIfExisting(policy, es.PasswordAlg, onetime)
if err != nil {
return nil, err
}