You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.2 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package s3err
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/glog"
  6. xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
  7. "github.com/fluent/fluent-logger-golang/fluent"
  8. "net/http"
  9. "os"
  10. "time"
  11. )
  12. type AccessLogExtend struct {
  13. AccessLog
  14. AccessLogHTTP
  15. }
  16. type AccessLog struct {
  17. Bucket string `msg:"bucket" json:"bucket"` // awsexamplebucket1
  18. Time int64 `msg:"time" json:"time"` // [06/Feb/2019:00:00:38 +0000]
  19. RemoteIP string `msg:"remote_ip" json:"remote_ip,omitempty"` // 192.0.2.3
  20. Requester string `msg:"requester" json:"requester,omitempty"` // IAM user id
  21. RequestID string `msg:"request_id" json:"request_id,omitempty"` // 3E57427F33A59F07
  22. Operation string `msg:"operation" json:"operation,omitempty"` // REST.HTTP_method.resource_type REST.PUT.OBJECT
  23. Key string `msg:"key" json:"key,omitempty"` // /photos/2019/08/puppy.jpg
  24. ErrorCode string `msg:"error_code" json:"error_code,omitempty"`
  25. HostId string `msg:"host_id" json:"host_id,omitempty"`
  26. HostHeader string `msg:"host_header" json:"host_header,omitempty"` // s3.us-west-2.amazonaws.com
  27. UserAgent string `msg:"user_agent" json:"user_agent,omitempty"`
  28. HTTPStatus int `msg:"status" json:"status,omitempty"`
  29. SignatureVersion string `msg:"signature_version" json:"signature_version,omitempty"`
  30. }
  31. type AccessLogHTTP struct {
  32. RequestURI string `json:"request_uri,omitempty"` // "GET /awsexamplebucket1/photos/2019/08/puppy.jpg?x-foo=bar HTTP/1.1"
  33. BytesSent string `json:"bytes_sent,omitempty"`
  34. ObjectSize string `json:"object_size,omitempty"`
  35. TotalTime int `json:"total_time,omitempty"`
  36. TurnAroundTime int `json:"turn_around_time,omitempty"`
  37. Referer string `json:"Referer,omitempty"`
  38. VersionId string `json:"version_id,omitempty"`
  39. CipherSuite string `json:"cipher_suite,omitempty"`
  40. AuthenticationType string `json:"auth_type,omitempty"`
  41. TLSVersion string `json:"TLS_version,omitempty"`
  42. }
  43. const tag = "s3.access"
  44. var (
  45. Logger *fluent.Fluent
  46. hostname = os.Getenv("HOSTNAME")
  47. )
  48. func InitAuditLog(config string) {
  49. configContent, readErr := os.ReadFile(config)
  50. if readErr != nil {
  51. glog.Fatalf("fail to read fluent config %s : %v", config, readErr)
  52. }
  53. var fluentConfig fluent.Config
  54. if err := json.Unmarshal(configContent, &fluentConfig); err != nil {
  55. glog.Fatalf("fail to parse fluent config %s : %v", config, err)
  56. }
  57. var err error
  58. Logger, err = fluent.New(fluentConfig)
  59. if err != nil {
  60. glog.Fatalf("fail to load fluent config: %v", err)
  61. }
  62. }
  63. func getREST(httpMetod string, resourceType string) string {
  64. return fmt.Sprintf("REST.%s.%s", httpMetod, resourceType)
  65. }
  66. func getResourceType(object string, query_key string, metod string) (string, bool) {
  67. if object == "/" {
  68. switch query_key {
  69. case "delete":
  70. return "BATCH.DELETE.OBJECT", true
  71. case "tagging":
  72. return getREST(metod, "OBJECTTAGGING"), true
  73. case "lifecycle":
  74. return getREST(metod, "LIFECYCLECONFIGURATION"), true
  75. case "acl":
  76. return getREST(metod, "ACCESSCONTROLPOLICY"), true
  77. case "policy":
  78. return getREST(metod, "BUCKETPOLICY"), true
  79. default:
  80. return getREST(metod, "BUCKET"), false
  81. }
  82. } else {
  83. switch query_key {
  84. case "tagging":
  85. return getREST(metod, "OBJECTTAGGING"), true
  86. default:
  87. return getREST(metod, "OBJECT"), false
  88. }
  89. }
  90. }
  91. func getOperation(object string, r *http.Request) string {
  92. queries := r.URL.Query()
  93. var operation string
  94. var queryFound bool
  95. for key, _ := range queries {
  96. operation, queryFound = getResourceType(object, key, r.Method)
  97. if queryFound {
  98. return operation
  99. }
  100. }
  101. if len(queries) == 0 {
  102. operation, _ = getResourceType(object, "", r.Method)
  103. }
  104. return operation
  105. }
  106. func GetAccessHttpLog(r *http.Request, statusCode int, s3errCode ErrorCode) AccessLogHTTP {
  107. return AccessLogHTTP{
  108. RequestURI: r.RequestURI,
  109. Referer: r.Header.Get("Referer"),
  110. }
  111. }
  112. func GetAccessLog(r *http.Request, HTTPStatusCode int, s3errCode ErrorCode) *AccessLog {
  113. bucket, key := xhttp.GetBucketAndObject(r)
  114. var errorCode string
  115. if s3errCode != ErrNone {
  116. errorCode = GetAPIError(s3errCode).Code
  117. }
  118. remoteIP := r.Header.Get("X-Real-IP")
  119. if len(remoteIP) == 0 {
  120. remoteIP = r.RemoteAddr
  121. }
  122. hostHeader := r.Header.Get("Host")
  123. if len(hostHeader) == 0 {
  124. hostHeader = r.URL.Hostname()
  125. }
  126. return &AccessLog{
  127. HostHeader: hostHeader,
  128. RequestID: r.Header.Get("X-Request-ID"),
  129. RemoteIP: remoteIP,
  130. Requester: r.Header.Get(xhttp.AmzIdentityId),
  131. UserAgent: r.Header.Get("UserAgent"),
  132. HostId: hostname,
  133. Bucket: bucket,
  134. HTTPStatus: HTTPStatusCode,
  135. Time: time.Now().Unix(),
  136. Key: key,
  137. Operation: getOperation(key, r),
  138. ErrorCode: errorCode,
  139. }
  140. }
  141. func PostLog(r *http.Request, HTTPStatusCode int, errorCode ErrorCode) {
  142. if Logger == nil {
  143. return
  144. }
  145. if err := Logger.Post(tag, *GetAccessLog(r, HTTPStatusCode, errorCode)); err != nil {
  146. glog.Warning("Error while posting log: ", err)
  147. }
  148. }
  149. func PostAccessLog(log *AccessLog) {
  150. if Logger == nil || log == nil {
  151. return
  152. }
  153. if err := Logger.Post(tag, *log); err != nil {
  154. glog.Warning("Error while posting log: ", err)
  155. }
  156. }