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.

134 lines
3.8 KiB

3 years ago
  1. package s3err
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
  6. // "github.com/chrislusf/seaweedfs/weed/s3api/s3err"
  7. //"github.com/chrislusf/seaweedfs/weed/s3api/s3err"
  8. "github.com/fluent/fluent-logger-golang/fluent"
  9. "net/http"
  10. "os"
  11. "time"
  12. )
  13. type AccessLogExtend struct {
  14. AccessLog
  15. AccessLogHTTP
  16. }
  17. type AccessLog struct {
  18. Bucket string `json:"bucket"` // awsexamplebucket1
  19. Time time.Time `json:"time"` // [06/Feb/2019:00:00:38 +0000]
  20. RemoteIP string `json:"remote_ip,omitempty"` // 192.0.2.3
  21. Requester string `json:"requester,omitempty"` // IAM user id
  22. RequestID string `json:"request_id,omitempty"` // 3E57427F33A59F07
  23. Operation string `json:"operation,omitempty"` // REST.HTTP_method.resource_type REST.PUT.OBJECT
  24. Key string `json:"Key,omitempty"` // /photos/2019/08/puppy.jpg
  25. ErrorCode string `json:"error_code,omitempty"`
  26. HostId string `json:"host_id,omitempty"`
  27. HostHeader string `json:"host_header,omitempty"` // s3.us-west-2.amazonaws.com
  28. SignatureVersion string `json:"signature_version,omitempty"`
  29. }
  30. type AccessLogHTTP struct {
  31. RequestURI string `json:"request_uri,omitempty"` // "GET /awsexamplebucket1/photos/2019/08/puppy.jpg?x-foo=bar HTTP/1.1"
  32. HTTPStatus int `json:"HTTP_status,omitempty"`
  33. BytesSent string `json:"bytes_sent,omitempty"`
  34. ObjectSize string `json:"object_size,omitempty"`
  35. TotalTime time.Duration `json:"total_time,omitempty"`
  36. TurnAroundTime time.Duration `json:"turn_around_time,omitempty"`
  37. Referer string `json:"Referer,omitempty"`
  38. UserAgent string `json:"user_agent,omitempty"`
  39. VersionId string `json:"version_id,omitempty"`
  40. CipherSuite string `json:"cipher_suite,omitempty"`
  41. AuthenticationType string `json:"auth_type,omitempty"`
  42. TLSVersion string `json:"TLS_version,omitempty"`
  43. }
  44. const tag = "s3.access"
  45. var (
  46. logger *fluent.Fluent
  47. hostname = os.Getenv("HOSTNAME")
  48. )
  49. func init() {
  50. var err error
  51. logger, err = fluent.New(fluent.Config{})
  52. if err != nil {
  53. glog.Fatalf("fail to load fluent config: %v", err)
  54. }
  55. }
  56. func getREST(httpMetod string, resourceType string) string {
  57. return fmt.Sprintf("REST.%s.%s", httpMetod, resourceType)
  58. }
  59. func getResourceType(object string, query string, metod string) (string, bool) {
  60. if len(object) > 0 {
  61. switch query {
  62. case "tagging":
  63. return getREST(metod, "OBJECTTAGGING"), true
  64. default:
  65. return getREST(metod, "OBJECT"), false
  66. }
  67. } else {
  68. switch query {
  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. }
  83. }
  84. func getOperation(object string , r *http.Request) string {
  85. queries := r.URL.Query()
  86. var operation string
  87. var queryFound bool
  88. for query, _ := range queries {
  89. if operation, queryFound = getResourceType(object, query, r.Method); queryFound {
  90. return operation
  91. }
  92. }
  93. return operation
  94. }
  95. func GetAccessLog (r *http.Request, s3errCode s3err.ErrorCode) AccessLog {
  96. bucket, key := xhttp.GetBucketAndObject(r)
  97. var errorCode string
  98. if s3errCode != s3err.ErrNone {
  99. errorCode = s3err.GetAPIError(s3errCode).Code
  100. }
  101. return AccessLog{
  102. HostHeader: r.Header.Get("Host"),
  103. RequestID: r.Header.Get("X-Request-ID"),
  104. RemoteIP: r.Header.Get("X-Real-IP"),
  105. Requester: r.Header.Get(xhttp.AmzIdentityId),
  106. HostId: hostname,
  107. Bucket: bucket,
  108. Time: time.Now(),
  109. Key: key,
  110. Operation: getOperation(key, r),
  111. ErrorCode: errorCode,
  112. }
  113. }
  114. func Post(r *http.Request, errorCode s3err.ErrorCode) {
  115. if logger == nil {
  116. return
  117. }
  118. err := logger.Post(tag, GetAccessLog(r, errorCode))
  119. if err != nil {
  120. glog.Error("Error while posting log: ", err)
  121. }
  122. }