feat: Add authenticating ID and user ID to request logging (#24474) (#24479)

To allow rudimentary security auditing of logs,
add the authenticating ID and the user ID when
possible to the request logs. When a request is
authorized for V1 or V2 API, store the authorizer
object to be used by the logger up the call stack.

closes https://github.com/influxdata/influxdb/issues/24473

(cherry picked from commit 13cf6be49e)

closes https://github.com/influxdata/influxdb/issues/24475
pull/24480/head
davidby-influx 2023-11-22 14:24:56 -08:00 committed by GitHub
parent 19e5c0e1b7
commit 6159c85f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 1 deletions

View File

@ -12,7 +12,8 @@ import (
type contextKey string
const (
authorizerCtxKey contextKey = "influx/authorizer/v1"
authorizerCtxKey contextKey = "influx/authorizer/v1"
authorizerCtxPtrKey contextKey = "influx/authorizer/pointer"
)
// SetAuthorizer sets an authorizer on context.
@ -68,3 +69,22 @@ func GetUserID(ctx context.Context) (platform.ID, error) {
}
return a.GetUserID(), nil
}
// ProvideAuthorizerStorage puts a pointer to an Authorizer in the context.
// This is used to pass an Authorizer up the stack for logging purposes
func ProvideAuthorizerStorage(ctx context.Context, ap *influxdb.Authorizer) context.Context {
return context.WithValue(ctx, authorizerCtxPtrKey, ap)
}
// StoreAuthorizer stores an Authorizer in a pointer from the Context.
// This permits functions deep in the stack to set the pointer to return
// values up the call chain
func StoreAuthorizer(ctx context.Context, auth influxdb.Authorizer) bool {
ap, ok := ctx.Value(authorizerCtxPtrKey).(*influxdb.Authorizer)
if ok && (ap != nil) {
(*ap) = auth
return true
} else {
return false
}
}

View File

@ -108,6 +108,9 @@ func (h *AuthenticationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
return
}
// Set the Authorizer pointer for use in logging high up the call stack
platcontext.StoreAuthorizer(ctx, auth)
// jwt based auth is permission based rather than identity based
// and therefor has no associated user. if the user ID is invalid
// disregard the user active check

View File

@ -49,6 +49,10 @@ func (h *Influx1xAuthenticationHandler) ServeHTTP(w http.ResponseWriter, r *http
}
auth, err := h.auth.Authorize(ctx, creds)
// Set the Authorizer pointer for use in logging high up the call stack
platcontext.StoreAuthorizer(ctx, auth)
if err != nil {
var erri *errors2.Error
if errors.As(err, &erri) {

View File

@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/influxdata/influxdb/v2"
platcontext "github.com/influxdata/influxdb/v2/context"
kithttp "github.com/influxdata/influxdb/v2/kit/transport/http"
"go.uber.org/zap"
)
@ -25,6 +27,10 @@ func LoggingMW(log *zap.Logger) kithttp.Middleware {
teedR: io.TeeReader(r.Body, &buf),
}
var auth influxdb.Authorizer
r = r.WithContext(platcontext.ProvideAuthorizerStorage(r.Context(), &auth))
defer func(start time.Time) {
errField := zap.Skip()
if errStr := w.Header().Get(kithttp.PlatformErrorCodeHeader); errStr != "" {
@ -36,6 +42,12 @@ func LoggingMW(log *zap.Logger) kithttp.Middleware {
errReferenceField = zap.String("error_code", errReference)
}
var id, userid string
if auth != nil {
id = auth.Identifier().String()
userid = auth.GetUserID().String()
}
fields := []zap.Field{
zap.String("method", r.Method),
zap.String("host", r.Host),
@ -48,6 +60,8 @@ func LoggingMW(log *zap.Logger) kithttp.Middleware {
zap.String("referrer", r.Referer()),
zap.String("remote", r.RemoteAddr),
zap.String("user_agent", kithttp.UserAgent(r)),
zap.String("authenticated_id", id),
zap.String("user_id", userid),
zap.Duration("took", time.Since(start)),
errField,
errReferenceField,