diff --git a/http/middleware/session/HLS.go b/http/middleware/session/HLS.go index 51d8c1f6..1486d6b9 100644 --- a/http/middleware/session/HLS.go +++ b/http/middleware/session/HLS.go @@ -94,6 +94,8 @@ func NewHLSWithConfig(config HLSConfig) echo.MiddlewareFunc { func (h *hls) handleIngress(c echo.Context, next echo.HandlerFunc) error { req := c.Request() + ctxuser := util.DefaultContext(c, "user", "") + path := req.URL.Path if strings.HasSuffix(path, ".m3u8") { @@ -113,10 +115,15 @@ func (h *hls) handleIngress(c echo.Context, next echo.HandlerFunc) error { } if !h.ingressCollector.IsKnownSession(path) { + ip, _ := net.AnonymizeIPString(c.RealIP()) + // Register a new session reference := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) - h.ingressCollector.RegisterAndActivate(path, reference, path, "") + h.ingressCollector.RegisterAndActivate(path, reference, path, ip) + h.ingressCollector.Extra(path, map[string]interface{}{ + "name": ctxuser, + "ip": ip, "user_agent": req.Header.Get("User-Agent"), }) } diff --git a/http/middleware/session/HTTP.go b/http/middleware/session/HTTP.go index 17142066..dedeaba1 100644 --- a/http/middleware/session/HTTP.go +++ b/http/middleware/session/HTTP.go @@ -4,8 +4,13 @@ import ( "io" "net" "net/http" + "net/url" + "github.com/datarhei/core/v16/glob" + "github.com/datarhei/core/v16/http/api" + "github.com/datarhei/core/v16/http/handler/util" "github.com/datarhei/core/v16/session" + "github.com/lithammer/shortuuid/v4" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" @@ -43,6 +48,8 @@ func NewHTTPWithConfig(config HTTPConfig) echo.MiddlewareFunc { return next(c) } + ctxuser := util.DefaultContext(c, "user", "") + req := c.Request() res := c.Response() @@ -51,32 +58,91 @@ func NewHTTPWithConfig(config HTTPConfig) echo.MiddlewareFunc { host = "" } + path := req.URL.Path + + location := path + req.URL.RawQuery + remote := req.RemoteAddr + + id := shortuuid.New() + + data := map[string]interface{}{} + + e := util.DefaultContext[interface{}](c, "session", nil) + if e != nil { + var ok bool + data, ok = e.(map[string]interface{}) + if !ok { + return api.Err(http.StatusForbidden, "", "invalid session data, cast") + } + + if match, ok := data["match"].(string); ok { + if ok, err := glob.Match(match, path, '/'); !ok { + if err != nil { + return api.Err(http.StatusForbidden, "", "no match for '%s' in %s: %s", match, path, err.Error()) + } + + return api.Err(http.StatusForbidden, "", "no match for '%s' in %s", match, path) + } + } + + referrer := req.Header.Get("Referer") + if u, err := url.Parse(referrer); err == nil { + referrer = u.Host + } + + if remote, ok := data["remote"].([]string); ok && len(remote) != 0 { + match := false + for _, r := range remote { + if referrer == r { + match = true + break + } + } + + if !match { + return api.Err(http.StatusForbidden, "", "remote not allowed") + } + } + } + + data["name"] = ctxuser + data["method"] = req.Method + data["code"] = 0 + reader := req.Body r := &fakeReader{ reader: req.Body, } req.Body = r - defer func() { - req.Body = reader - - if config.Collector.IsCollectableIP(host) { - config.Collector.RegisterAndActivate("HTTP", "", "any", "any") - config.Collector.Ingress("HTTP", r.size+headerSize(req.Header)) - } - }() - writer := res.Writer w := &fakeWriter{ ResponseWriter: res.Writer, } res.Writer = w + if config.Collector.IsCollectableIP(host) { + config.Collector.RegisterAndActivate(id, "", location, remote) + config.Collector.Extra(id, data) + } + + defer config.Collector.Close(id) + + defer func() { + req.Body = reader + + if config.Collector.IsCollectableIP(host) { + config.Collector.Ingress(id, r.size+headerSize(req.Header)) + } + }() + defer func() { res.Writer = writer if config.Collector.IsCollectableIP(host) { - config.Collector.Egress("HTTP", w.size+headerSize(res.Header())) + config.Collector.Egress(id, w.size+headerSize(res.Header())) + data["code"] = res.Status + config.Collector.Extra(id, data) } }() @@ -104,6 +170,13 @@ func (r *fakeReader) Close() error { type fakeWriter struct { http.ResponseWriter size int64 + code int +} + +func (w *fakeWriter) WriteHeader(statusCode int) { + w.ResponseWriter.WriteHeader(statusCode) + + w.code = statusCode } func (w *fakeWriter) Write(body []byte) (int, error) { diff --git a/http/server.go b/http/server.go index b540c508..497cf5af 100644 --- a/http/server.go +++ b/http/server.go @@ -371,9 +371,6 @@ func NewServer(config Config) (Server, error) { return nil }, })) - s.router.Use(mwsession.NewHTTPWithConfig(mwsession.HTTPConfig{ - Collector: config.Sessions.Collector("http"), - })) s.router.HideBanner = true s.router.HidePort = true @@ -386,6 +383,10 @@ func NewServer(config Config) (Server, error) { s.router.Use(s.middleware.iam) + s.router.Use(mwsession.NewHTTPWithConfig(mwsession.HTTPConfig{ + Collector: config.Sessions.Collector("http"), + })) + // Add static routes if path, target := config.Router.StaticRoute(); len(target) != 0 { group := s.router.Group(path) diff --git a/session/registry.go b/session/registry.go index 8317453c..1e859ac8 100644 --- a/session/registry.go +++ b/session/registry.go @@ -314,7 +314,7 @@ func (r *registry) Register(id string, conf CollectorConfig) (Collector, error) return nil, fmt.Errorf("a collector with the ID '%s' already exists", id) } - m, err := newCollector(id, r.persist.sessionsCh, r.logger.WithComponent(id), conf) + m, err := newCollector(id, r.persist.sessionsCh, r.logger, conf) if err != nil { return nil, err }