aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/s3err/audit_fluent.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/s3api/s3err/audit_fluent.go')
-rw-r--r--weed/s3api/s3err/audit_fluent.go135
1 files changed, 86 insertions, 49 deletions
diff --git a/weed/s3api/s3err/audit_fluent.go b/weed/s3api/s3err/audit_fluent.go
index ef8b49827..bf935c8d8 100644
--- a/weed/s3api/s3err/audit_fluent.go
+++ b/weed/s3api/s3err/audit_fluent.go
@@ -1,6 +1,7 @@
package s3err
import (
+ "encoding/json"
"fmt"
"github.com/chrislusf/seaweedfs/weed/glog"
xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
@@ -16,45 +17,52 @@ type AccessLogExtend struct {
}
type AccessLog struct {
- Bucket string `json:"bucket"` // awsexamplebucket1
- Time time.Time `json:"time"` // [06/Feb/2019:00:00:38 +0000]
- RemoteIP string `json:"remote_ip,omitempty"` // 192.0.2.3
- Requester string `json:"requester,omitempty"` // IAM user id
- RequestID string `json:"request_id,omitempty"` // 3E57427F33A59F07
- Operation string `json:"operation,omitempty"` // REST.HTTP_method.resource_type REST.PUT.OBJECT
- Key string `json:"Key,omitempty"` // /photos/2019/08/puppy.jpg
- ErrorCode string `json:"error_code,omitempty"`
- HostId string `json:"host_id,omitempty"`
- HostHeader string `json:"host_header,omitempty"` // s3.us-west-2.amazonaws.com
- SignatureVersion string `json:"signature_version,omitempty"`
+ Bucket string `msg:"bucket" json:"bucket"` // awsexamplebucket1
+ Time int64 `msg:"time" json:"time"` // [06/Feb/2019:00:00:38 +0000]
+ RemoteIP string `msg:"remote_ip" json:"remote_ip,omitempty"` // 192.0.2.3
+ Requester string `msg:"requester" json:"requester,omitempty"` // IAM user id
+ RequestID string `msg:"request_id" json:"request_id,omitempty"` // 3E57427F33A59F07
+ Operation string `msg:"operation" json:"operation,omitempty"` // REST.HTTP_method.resource_type REST.PUT.OBJECT
+ Key string `msg:"key" json:"key,omitempty"` // /photos/2019/08/puppy.jpg
+ ErrorCode string `msg:"error_code" json:"error_code,omitempty"`
+ HostId string `msg:"host_id" json:"host_id,omitempty"`
+ HostHeader string `msg:"host_header" json:"host_header,omitempty"` // s3.us-west-2.amazonaws.com
+ UserAgent string `msg:"user_agent" json:"user_agent,omitempty"`
+ HTTPStatus int `msg:"status" json:"status,omitempty"`
+ SignatureVersion string `msg:"signature_version" json:"signature_version,omitempty"`
}
type AccessLogHTTP struct {
- RequestURI string `json:"request_uri,omitempty"` // "GET /awsexamplebucket1/photos/2019/08/puppy.jpg?x-foo=bar HTTP/1.1"
- HTTPStatus int `json:"HTTP_status,omitempty"`
- BytesSent string `json:"bytes_sent,omitempty"`
- ObjectSize string `json:"object_size,omitempty"`
- TotalTime time.Duration `json:"total_time,omitempty"`
- TurnAroundTime time.Duration `json:"turn_around_time,omitempty"`
- Referer string `json:"Referer,omitempty"`
- UserAgent string `json:"user_agent,omitempty"`
- VersionId string `json:"version_id,omitempty"`
- CipherSuite string `json:"cipher_suite,omitempty"`
- AuthenticationType string `json:"auth_type,omitempty"`
- TLSVersion string `json:"TLS_version,omitempty"`
+ RequestURI string `json:"request_uri,omitempty"` // "GET /awsexamplebucket1/photos/2019/08/puppy.jpg?x-foo=bar HTTP/1.1"
+ BytesSent string `json:"bytes_sent,omitempty"`
+ ObjectSize string `json:"object_size,omitempty"`
+ TotalTime int `json:"total_time,omitempty"`
+ TurnAroundTime int `json:"turn_around_time,omitempty"`
+ Referer string `json:"Referer,omitempty"`
+ VersionId string `json:"version_id,omitempty"`
+ CipherSuite string `json:"cipher_suite,omitempty"`
+ AuthenticationType string `json:"auth_type,omitempty"`
+ TLSVersion string `json:"TLS_version,omitempty"`
}
const tag = "s3.access"
var (
- logger *fluent.Fluent
+ Logger *fluent.Fluent
hostname = os.Getenv("HOSTNAME")
)
-func init() {
+func InitAuditLog(config string) {
+ configContent, readErr := os.ReadFile(config)
+ if readErr != nil {
+ glog.Fatalf("fail to read fluent config %s : %v", config, readErr)
+ }
+ var fluentConfig fluent.Config
+ if err := json.Unmarshal(configContent, &fluentConfig); err != nil {
+ glog.Fatalf("fail to parse fluent config %s : %v", config, err)
+ }
var err error
-
- logger, err = fluent.New(fluent.Config{})
+ Logger, err = fluent.New(fluentConfig)
if err != nil {
glog.Fatalf("fail to load fluent config: %v", err)
}
@@ -64,16 +72,9 @@ func getREST(httpMetod string, resourceType string) string {
return fmt.Sprintf("REST.%s.%s", httpMetod, resourceType)
}
-func getResourceType(object string, query string, metod string) (string, bool) {
- if len(object) > 0 {
- switch query {
- case "tagging":
- return getREST(metod, "OBJECTTAGGING"), true
- default:
- return getREST(metod, "OBJECT"), false
- }
- } else {
- switch query {
+func getResourceType(object string, query_key string, metod string) (string, bool) {
+ if object == "/" {
+ switch query_key {
case "delete":
return "BATCH.DELETE.OBJECT", true
case "tagging":
@@ -87,6 +88,13 @@ func getResourceType(object string, query string, metod string) (string, bool) {
default:
return getREST(metod, "BUCKET"), false
}
+ } else {
+ switch query_key {
+ case "tagging":
+ return getREST(metod, "OBJECTTAGGING"), true
+ default:
+ return getREST(metod, "OBJECT"), false
+ }
}
}
@@ -94,40 +102,69 @@ func getOperation(object string, r *http.Request) string {
queries := r.URL.Query()
var operation string
var queryFound bool
- for query, _ := range queries {
- if operation, queryFound = getResourceType(object, query, r.Method); queryFound {
+ for key, _ := range queries {
+ operation, queryFound = getResourceType(object, key, r.Method)
+ if queryFound {
return operation
}
}
+ if len(queries) == 0 {
+ operation, _ = getResourceType(object, "", r.Method)
+ }
return operation
}
-func GetAccessLog(r *http.Request, s3errCode ErrorCode) AccessLog {
+func GetAccessHttpLog(r *http.Request, statusCode int, s3errCode ErrorCode) AccessLogHTTP {
+ return AccessLogHTTP{
+ RequestURI: r.RequestURI,
+ Referer: r.Header.Get("Referer"),
+ }
+}
+
+func GetAccessLog(r *http.Request, HTTPStatusCode int, s3errCode ErrorCode) *AccessLog {
bucket, key := xhttp.GetBucketAndObject(r)
var errorCode string
if s3errCode != ErrNone {
errorCode = GetAPIError(s3errCode).Code
}
- return AccessLog{
- HostHeader: r.Header.Get("Host"),
+ remoteIP := r.Header.Get("X-Real-IP")
+ if len(remoteIP) == 0 {
+ remoteIP = r.RemoteAddr
+ }
+ hostHeader := r.Header.Get("Host")
+ if len(hostHeader) == 0 {
+ hostHeader = r.URL.Hostname()
+ }
+ return &AccessLog{
+ HostHeader: hostHeader,
RequestID: r.Header.Get("X-Request-ID"),
- RemoteIP: r.Header.Get("X-Real-IP"),
+ RemoteIP: remoteIP,
Requester: r.Header.Get(xhttp.AmzIdentityId),
+ UserAgent: r.Header.Get("UserAgent"),
HostId: hostname,
Bucket: bucket,
- Time: time.Now(),
+ HTTPStatus: HTTPStatusCode,
+ Time: time.Now().Unix(),
Key: key,
Operation: getOperation(key, r),
ErrorCode: errorCode,
}
}
-func PostLog(r *http.Request, errorCode ErrorCode) {
- if logger == nil {
+func PostLog(r *http.Request, HTTPStatusCode int, errorCode ErrorCode) {
+ if Logger == nil {
return
}
- err := logger.Post(tag, GetAccessLog(r, errorCode))
- if err != nil {
- glog.Error("Error while posting log: ", err)
+ if err := Logger.Post(tag, *GetAccessLog(r, HTTPStatusCode, errorCode)); err != nil {
+ glog.Warning("Error while posting log: ", err)
+ }
+}
+
+func PostAccessLog(log *AccessLog) {
+ if Logger == nil || log == nil {
+ return
+ }
+ if err := Logger.Post(tag, *log); err != nil {
+ glog.Warning("Error while posting log: ", err)
}
}