2021-12-07 15:13:21 +08:00
|
|
|
package s3err
|
|
|
|
|
|
|
|
import (
|
|
|
|
"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"
|
|
|
|
)
|
|
|
|
|
2021-12-07 15:15:48 +08:00
|
|
|
type AccessLogExtend struct {
|
2021-12-07 15:13:21 +08:00
|
|
|
AccessLog
|
|
|
|
AccessLogHTTP
|
|
|
|
}
|
|
|
|
|
2021-12-07 15:15:48 +08:00
|
|
|
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"`
|
2021-12-07 15:13:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type AccessLogHTTP struct {
|
2021-12-07 15:15:48 +08:00
|
|
|
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"`
|
2021-12-07 15:13:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const tag = "s3.access"
|
|
|
|
|
|
|
|
var (
|
2021-12-07 15:15:48 +08:00
|
|
|
logger *fluent.Fluent
|
2021-12-07 15:13:21 +08:00
|
|
|
hostname = os.Getenv("HOSTNAME")
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
var err error
|
2021-12-07 15:15:48 +08:00
|
|
|
|
2021-12-07 15:13:21 +08:00
|
|
|
logger, err = fluent.New(fluent.Config{})
|
|
|
|
if err != nil {
|
|
|
|
glog.Fatalf("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 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 {
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-07 15:15:48 +08:00
|
|
|
func getOperation(object string, r *http.Request) string {
|
2021-12-07 15:13:21 +08:00
|
|
|
queries := r.URL.Query()
|
|
|
|
var operation string
|
|
|
|
var queryFound bool
|
|
|
|
for query, _ := range queries {
|
|
|
|
if operation, queryFound = getResourceType(object, query, r.Method); queryFound {
|
|
|
|
return operation
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return operation
|
|
|
|
}
|
|
|
|
|
2021-12-07 15:15:48 +08:00
|
|
|
func GetAccessLog(r *http.Request, s3errCode ErrorCode) AccessLog {
|
2021-12-07 15:13:21 +08:00
|
|
|
bucket, key := xhttp.GetBucketAndObject(r)
|
|
|
|
var errorCode string
|
2021-12-07 15:15:48 +08:00
|
|
|
if s3errCode != ErrNone {
|
|
|
|
errorCode = GetAPIError(s3errCode).Code
|
2021-12-07 15:13:21 +08:00
|
|
|
}
|
|
|
|
return AccessLog{
|
|
|
|
HostHeader: r.Header.Get("Host"),
|
2021-12-07 15:15:48 +08:00
|
|
|
RequestID: r.Header.Get("X-Request-ID"),
|
|
|
|
RemoteIP: r.Header.Get("X-Real-IP"),
|
2021-12-07 15:13:21 +08:00
|
|
|
Requester: r.Header.Get(xhttp.AmzIdentityId),
|
2021-12-07 15:15:48 +08:00
|
|
|
HostId: hostname,
|
|
|
|
Bucket: bucket,
|
|
|
|
Time: time.Now(),
|
|
|
|
Key: key,
|
|
|
|
Operation: getOperation(key, r),
|
|
|
|
ErrorCode: errorCode,
|
2021-12-07 15:13:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-07 15:15:48 +08:00
|
|
|
func PostLog(r *http.Request, errorCode ErrorCode) {
|
2021-12-07 15:13:21 +08:00
|
|
|
if logger == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err := logger.Post(tag, GetAccessLog(r, errorCode))
|
|
|
|
if err != nil {
|
|
|
|
glog.Error("Error while posting log: ", err)
|
|
|
|
}
|
2021-12-07 15:15:48 +08:00
|
|
|
}
|