github.com/minio/console@v1.4.1/pkg/logger/message/audit/entry.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package audit 18 19 import ( 20 "net/http" 21 "os" 22 "strings" 23 "time" 24 25 "github.com/google/uuid" 26 27 "github.com/golang-jwt/jwt/v4" 28 29 "github.com/minio/console/pkg/utils" 30 31 xhttp "github.com/minio/console/pkg/http" 32 ) 33 34 // Version - represents the current version of audit log structure. 35 const Version = "1" 36 37 // ObjectVersion object version key/versionId 38 type ObjectVersion struct { 39 ObjectName string `json:"objectName"` 40 VersionID string `json:"versionId,omitempty"` 41 } 42 43 // Entry - audit entry logs. 44 type Entry struct { 45 Version string `json:"version"` 46 DeploymentID string `json:"deploymentid,omitempty"` 47 Time time.Time `json:"time"` 48 Trigger string `json:"trigger"` 49 API struct { 50 Path string `json:"path,omitempty"` 51 Status string `json:"status,omitempty"` 52 Method string `json:"method"` 53 StatusCode int `json:"statusCode,omitempty"` 54 InputBytes int64 `json:"rx"` 55 OutputBytes int64 `json:"tx"` 56 TimeToFirstByte string `json:"timeToFirstByte,omitempty"` 57 TimeToResponse string `json:"timeToResponse,omitempty"` 58 } `json:"api"` 59 RemoteHost string `json:"remotehost,omitempty"` 60 RequestID string `json:"requestID,omitempty"` 61 SessionID string `json:"sessionID,omitempty"` 62 UserAgent string `json:"userAgent,omitempty"` 63 ReqClaims map[string]interface{} `json:"requestClaims,omitempty"` 64 ReqQuery map[string]string `json:"requestQuery,omitempty"` 65 ReqHeader map[string]string `json:"requestHeader,omitempty"` 66 RespHeader map[string]string `json:"responseHeader,omitempty"` 67 Tags map[string]interface{} `json:"tags,omitempty"` 68 } 69 70 // NewEntry - constructs an audit entry object with some fields filled 71 func NewEntry(deploymentID string) Entry { 72 return Entry{ 73 Version: Version, 74 DeploymentID: deploymentID, 75 Time: time.Now().UTC(), 76 } 77 } 78 79 // ToEntry - constructs an audit entry from a http request 80 func ToEntry(w http.ResponseWriter, r *http.Request, reqClaims map[string]interface{}, deploymentID string) Entry { 81 entry := NewEntry(deploymentID) 82 83 entry.RemoteHost = r.RemoteAddr 84 entry.UserAgent = r.UserAgent() 85 entry.ReqClaims = reqClaims 86 87 q := r.URL.Query() 88 reqQuery := make(map[string]string, len(q)) 89 for k, v := range q { 90 reqQuery[k] = strings.Join(v, ",") 91 } 92 entry.ReqQuery = reqQuery 93 94 reqHeader := make(map[string]string, len(r.Header)) 95 for k, v := range r.Header { 96 reqHeader[k] = strings.Join(v, ",") 97 } 98 entry.ReqHeader = reqHeader 99 100 wh := w.Header() 101 102 var requestID interface{} 103 requestID = r.Context().Value(utils.ContextRequestID) 104 if requestID == nil { 105 requestID = uuid.NewString() 106 } 107 entry.RequestID = requestID.(string) 108 109 if val := r.Context().Value(utils.ContextRequestUserID); val != nil { 110 sessionID := val.(string) 111 if os.Getenv("CONSOLE_OPERATOR_MODE") != "" && os.Getenv("CONSOLE_OPERATOR_MODE") == "on" { 112 claims := jwt.MapClaims{} 113 _, _ = jwt.ParseWithClaims(sessionID, claims, nil) 114 if sub, ok := claims["sub"]; ok { 115 sessionID = sub.(string) 116 } 117 } 118 entry.SessionID = sessionID 119 } 120 121 respHeader := make(map[string]string, len(wh)) 122 for k, v := range wh { 123 respHeader[k] = strings.Join(v, ",") 124 } 125 entry.RespHeader = respHeader 126 127 if etag := respHeader[xhttp.ETag]; etag != "" { 128 respHeader[xhttp.ETag] = strings.Trim(etag, `"`) 129 } 130 131 return entry 132 }