github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/api/server/middleware/debug.go (about) 1 package middleware // import "github.com/docker/docker/api/server/middleware" 2 3 import ( 4 "bufio" 5 "context" 6 "encoding/json" 7 "io" 8 "net/http" 9 "strings" 10 11 "github.com/docker/docker/api/server/httputils" 12 "github.com/docker/docker/pkg/ioutils" 13 "github.com/sirupsen/logrus" 14 ) 15 16 // DebugRequestMiddleware dumps the request to logger 17 func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 18 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 19 logrus.Debugf("Calling %s %s", r.Method, r.RequestURI) 20 21 if r.Method != http.MethodPost { 22 return handler(ctx, w, r, vars) 23 } 24 if err := httputils.CheckForJSON(r); err != nil { 25 return handler(ctx, w, r, vars) 26 } 27 maxBodySize := 4096 // 4KB 28 if r.ContentLength > int64(maxBodySize) { 29 return handler(ctx, w, r, vars) 30 } 31 32 body := r.Body 33 bufReader := bufio.NewReaderSize(body, maxBodySize) 34 r.Body = ioutils.NewReadCloserWrapper(bufReader, func() error { return body.Close() }) 35 36 b, err := bufReader.Peek(maxBodySize) 37 if err != io.EOF { 38 // either there was an error reading, or the buffer is full (in which case the request is too large) 39 return handler(ctx, w, r, vars) 40 } 41 42 var postForm map[string]interface{} 43 if err := json.Unmarshal(b, &postForm); err == nil { 44 maskSecretKeys(postForm) 45 formStr, errMarshal := json.Marshal(postForm) 46 if errMarshal == nil { 47 logrus.Debugf("form data: %s", string(formStr)) 48 } else { 49 logrus.Debugf("form data: %q", postForm) 50 } 51 } 52 53 return handler(ctx, w, r, vars) 54 } 55 } 56 57 func maskSecretKeys(inp interface{}) { 58 if arr, ok := inp.([]interface{}); ok { 59 for _, f := range arr { 60 maskSecretKeys(f) 61 } 62 return 63 } 64 65 if form, ok := inp.(map[string]interface{}); ok { 66 scrub := []string{ 67 // Note: The Data field contains the base64-encoded secret in 'secret' 68 // and 'config' create and update requests. Currently, no other POST 69 // API endpoints use a data field, so we scrub this field unconditionally. 70 // Change this handling to be conditional if a new endpoint is added 71 // in future where this field should not be scrubbed. 72 "data", 73 "jointoken", 74 "password", 75 "secret", 76 "signingcakey", 77 "unlockkey", 78 } 79 loop0: 80 for k, v := range form { 81 for _, m := range scrub { 82 if strings.EqualFold(m, k) { 83 form[k] = "*****" 84 continue loop0 85 } 86 } 87 maskSecretKeys(v) 88 } 89 } 90 }