forked from TrueCloudLab/frostfs-s3-gw
[#498] middleware: Add spans to detail the trace
Spans are added only to the following middleware: * PolicyCheck * Auth * FrostfsIDValidation This is done this way because these middleware are basic and they interact with frostfs-storage. Also, an explicit context has been added to many functions so that the middleware spans do not include all subsequent spans. Signed-off-by: Roman Loginov <r.loginov@yadro.com>
This commit is contained in:
parent
c2c062b778
commit
ac0140506c
6 changed files with 51 additions and 33 deletions
|
@ -1,12 +1,14 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||
apierr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
|
@ -30,7 +32,9 @@ type (
|
|||
Center interface {
|
||||
// Authenticate validate and authenticate request.
|
||||
// Must return ErrNoAuthorizationHeader if auth header is missed.
|
||||
Authenticate(request *http.Request) (*Box, error)
|
||||
// Authenticate uses a separate context so that the authorization
|
||||
// span middleware does not contain all subsequent spans.
|
||||
Authenticate(ctx context.Context, request *http.Request) (*Box, error)
|
||||
}
|
||||
|
||||
//nolint:revive
|
||||
|
@ -47,34 +51,38 @@ var ErrNoAuthorizationHeader = errors.New("no authorization header")
|
|||
func Auth(center Center, log *zap.Logger) Func {
|
||||
return func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
reqInfo := GetReqInfo(ctx)
|
||||
reqCtx := r.Context()
|
||||
ctx, span := tracing.StartSpanFromContext(reqCtx, "middleware.Auth")
|
||||
|
||||
reqInfo := GetReqInfo(reqCtx)
|
||||
reqInfo.User = "anon"
|
||||
box, err := center.Authenticate(r)
|
||||
box, err := center.Authenticate(ctx, r)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoAuthorizationHeader) {
|
||||
reqLogOrDefault(ctx, log).Debug(logs.CouldntReceiveAccessBoxForGateKeyRandomKeyWillBeUsed, zap.Error(err), logs.TagField(logs.TagDatapath))
|
||||
reqLogOrDefault(reqCtx, log).Debug(logs.CouldntReceiveAccessBoxForGateKeyRandomKeyWillBeUsed, zap.Error(err), logs.TagField(logs.TagDatapath))
|
||||
} else {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FailedToPassAuthentication, zap.Error(err), logs.TagField(logs.TagDatapath))
|
||||
reqLogOrDefault(reqCtx, log).Error(logs.FailedToPassAuthentication, zap.Error(err), logs.TagField(logs.TagDatapath))
|
||||
err = apierr.TransformToS3Error(err)
|
||||
if err.(apierr.Error).ErrCode == apierr.ErrInternalError {
|
||||
err = apierr.GetAPIError(apierr.ErrAccessDenied)
|
||||
}
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr), logs.TagField(logs.TagDatapath))
|
||||
reqLogOrDefault(reqCtx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr), logs.TagField(logs.TagDatapath))
|
||||
}
|
||||
span.End()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ctx = SetBox(ctx, box)
|
||||
reqCtx = SetBox(reqCtx, box)
|
||||
|
||||
if box.AccessBox.Gate.BearerToken != nil {
|
||||
reqInfo.User = bearer.ResolveIssuer(*box.AccessBox.Gate.BearerToken).String()
|
||||
}
|
||||
reqLogOrDefault(ctx, log).Debug(logs.SuccessfulAuth, zap.String("accessKeyID", box.AuthHeaders.AccessKeyID), logs.TagField(logs.TagDatapath))
|
||||
reqLogOrDefault(reqCtx, log).Debug(logs.SuccessfulAuth, zap.String("accessKeyID", box.AuthHeaders.AccessKeyID), logs.TagField(logs.TagDatapath))
|
||||
}
|
||||
|
||||
h.ServeHTTP(w, r.WithContext(ctx))
|
||||
span.End()
|
||||
h.ServeHTTP(w, r.WithContext(reqCtx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -86,22 +94,26 @@ type FrostFSIDValidator interface {
|
|||
func FrostfsIDValidation(frostfsID FrostFSIDValidator, log *zap.Logger) Func {
|
||||
return func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ctx, span := tracing.StartSpanFromContext(r.Context(), "middleware.FrostfsIDValidation")
|
||||
|
||||
bd, err := GetBoxData(ctx)
|
||||
if err != nil || bd.Gate.BearerToken == nil {
|
||||
reqLogOrDefault(ctx, log).Debug(logs.AnonRequestSkipFrostfsIDValidation, logs.TagField(logs.TagDatapath))
|
||||
span.End()
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err = validateBearerToken(frostfsID, bd.Gate.BearerToken); err != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FrostfsIDValidationFailed, zap.Error(err), logs.TagField(logs.TagDatapath))
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil {
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(ctx), err); wrErr != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr), logs.TagField(logs.TagDatapath))
|
||||
}
|
||||
span.End()
|
||||
return
|
||||
}
|
||||
|
||||
span.End()
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue