123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- package s3err
- import (
- "encoding/json"
- "fmt"
- "github.com/chrislusf/seaweedfs/weed/glog"
- xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
- "github.com/fluent/fluent-logger-golang/fluent"
- "net/http"
- "os"
- "time"
- )
- type AccessLogExtend struct {
- AccessLog
- AccessLogHTTP
- }
- type AccessLog struct {
- 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"
- 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
- hostname = os.Getenv("HOSTNAME")
- environment = os.Getenv("ENVIRONMENT")
- )
- func InitAuditLog(config string) {
- configContent, readErr := os.ReadFile(config)
- if readErr != nil {
- glog.Errorf("fail to read fluent config %s : %v", config, readErr)
- return
- }
- fluentConfig := &fluent.Config{}
- if err := json.Unmarshal(configContent, fluentConfig); err != nil {
- glog.Errorf("fail to parse fluent config %s : %v", string(configContent), err)
- return
- }
- if len(fluentConfig.TagPrefix) == 0 && len(environment) > 0 {
- fluentConfig.TagPrefix = environment
- }
- fluentConfig.Async = true
- fluentConfig.AsyncResultCallback = func(data []byte, err error) {
- if err != nil {
- glog.Warning("Error while posting log: ", err)
- }
- }
- var err error
- Logger, err = fluent.New(*fluentConfig)
- if err != nil {
- glog.Errorf("fail to load fluent config: %v", err)
- }
- }
- func getREST(httpMetod string, resourceType string) string {
- return fmt.Sprintf("REST.%s.%s", httpMetod, resourceType)
- }
- 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":
- return getREST(metod, "OBJECTTAGGING"), true
- case "lifecycle":
- return getREST(metod, "LIFECYCLECONFIGURATION"), true
- case "acl":
- return getREST(metod, "ACCESSCONTROLPOLICY"), true
- case "policy":
- return getREST(metod, "BUCKETPOLICY"), true
- default:
- return getREST(metod, "BUCKET"), false
- }
- } else {
- switch query_key {
- case "tagging":
- return getREST(metod, "OBJECTTAGGING"), true
- default:
- return getREST(metod, "OBJECT"), false
- }
- }
- }
- func getOperation(object string, r *http.Request) string {
- queries := r.URL.Query()
- var operation string
- var queryFound bool
- 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 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
- }
- remoteIP := r.Header.Get("X-Real-IP")
- if len(remoteIP) == 0 {
- remoteIP = r.RemoteAddr
- }
- hostHeader := r.Header.Get("X-Forwarded-Host")
- if len(hostHeader) == 0 {
- hostHeader = r.Host
- }
- return &AccessLog{
- HostHeader: hostHeader,
- RequestID: r.Header.Get("X-Request-ID"),
- RemoteIP: remoteIP,
- Requester: r.Header.Get(xhttp.AmzIdentityId),
- SignatureVersion: r.Header.Get(xhttp.AmzAuthType),
- UserAgent: r.Header.Get("user-agent"),
- HostId: hostname,
- Bucket: bucket,
- HTTPStatus: HTTPStatusCode,
- Time: time.Now().Unix(),
- Key: key,
- Operation: getOperation(key, r),
- ErrorCode: errorCode,
- }
- }
- func PostLog(r *http.Request, HTTPStatusCode int, errorCode ErrorCode) {
- if Logger == nil {
- return
- }
- 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 || len(log.Key) == 0 {
- return
- }
- if err := Logger.Post(tag, log); err != nil {
- glog.Warning("Error while posting log: ", err)
- }
- }
|