From 63a6516d99e76e9257ea1ee9d57ebea577aa8821 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Wed, 20 Jan 2021 19:03:05 +0100 Subject: [PATCH] Added audit stream to HTTP proxy --- internal/endpoint/handler/http/audit.go | 37 +++++++++++++++++++ .../handler/http/{mock => }/conn_context.go | 10 ++--- .../endpoint/handler/http/mock/handler.go | 3 +- .../handler/http/mock/regex_router.go | 25 +------------ .../endpoint/handler/http/proxy/handler.go | 13 +++++-- .../handler/http/proxy/proxy_handler.go | 17 +++------ pkg/audit/event.go | 3 ++ 7 files changed, 65 insertions(+), 43 deletions(-) create mode 100644 internal/endpoint/handler/http/audit.go rename internal/endpoint/handler/http/{mock => }/conn_context.go (58%) diff --git a/internal/endpoint/handler/http/audit.go b/internal/endpoint/handler/http/audit.go new file mode 100644 index 0000000..9d92817 --- /dev/null +++ b/internal/endpoint/handler/http/audit.go @@ -0,0 +1,37 @@ +package http + +import ( + "net/http" + + "gitlab.com/inetmock/inetmock/pkg/audit" + "gitlab.com/inetmock/inetmock/pkg/audit/details" +) + +func EventFromRequest(request *http.Request, app audit.AppProtocol) audit.Event { + httpDetails := details.HTTP{ + Method: request.Method, + Host: request.Host, + URI: request.RequestURI, + Proto: request.Proto, + Headers: request.Header, + } + + ev := audit.Event{ + Transport: audit.TransportProtocol_TCP, + Application: app, + ProtocolDetails: httpDetails, + } + + if request.TLS != nil { + ev.TLS = &audit.TLSDetails{ + Version: request.TLS.Version, + CipherSuite: request.TLS.CipherSuite, + ServerName: request.TLS.ServerName, + } + } + + ev.SetDestinationIPFromAddr(localAddr(request.Context())) + ev.SetSourceIPFromAddr(remoteAddr(request.Context())) + + return ev +} diff --git a/internal/endpoint/handler/http/mock/conn_context.go b/internal/endpoint/handler/http/conn_context.go similarity index 58% rename from internal/endpoint/handler/http/mock/conn_context.go rename to internal/endpoint/handler/http/conn_context.go index 502d104..3f9c6da 100644 --- a/internal/endpoint/handler/http/mock/conn_context.go +++ b/internal/endpoint/handler/http/conn_context.go @@ -1,4 +1,4 @@ -package mock +package http import ( "context" @@ -8,8 +8,8 @@ import ( type httpContextKey string const ( - remoteAddrKey httpContextKey = "RemoteAddr" - localAddrKey httpContextKey = "LocalAddr" + remoteAddrKey httpContextKey = "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http/context/remoteAddr" + localAddrKey httpContextKey = "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http/context/localAddr" ) func StoreConnPropertiesInContext(ctx context.Context, c net.Conn) context.Context { @@ -18,7 +18,7 @@ func StoreConnPropertiesInContext(ctx context.Context, c net.Conn) context.Conte return ctx } -func LocalAddr(ctx context.Context) net.Addr { +func localAddr(ctx context.Context) net.Addr { val := ctx.Value(localAddrKey) if val == nil { return nil @@ -26,7 +26,7 @@ func LocalAddr(ctx context.Context) net.Addr { return val.(net.Addr) } -func RemoteAddr(ctx context.Context) net.Addr { +func remoteAddr(ctx context.Context) net.Addr { val := ctx.Value(remoteAddrKey) if val == nil { return nil diff --git a/internal/endpoint/handler/http/mock/handler.go b/internal/endpoint/handler/http/mock/handler.go index 486b22e..f4ad94d 100644 --- a/internal/endpoint/handler/http/mock/handler.go +++ b/internal/endpoint/handler/http/mock/handler.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" + imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http" "gitlab.com/inetmock/inetmock/pkg/api" "gitlab.com/inetmock/inetmock/pkg/config" "gitlab.com/inetmock/inetmock/pkg/logging" @@ -46,7 +47,7 @@ func (p *httpHandler) Start(ctx api.PluginContext, config config.HandlerConfig) p.server = &http.Server{ Addr: config.ListenAddr(), Handler: router, - ConnContext: StoreConnPropertiesInContext, + ConnContext: imHttp.StoreConnPropertiesInContext, } for _, rule := range options.Rules { diff --git a/internal/endpoint/handler/http/mock/regex_router.go b/internal/endpoint/handler/http/mock/regex_router.go index 4e96329..28f9d8b 100644 --- a/internal/endpoint/handler/http/mock/regex_router.go +++ b/internal/endpoint/handler/http/mock/regex_router.go @@ -5,8 +5,8 @@ import ( "strconv" "github.com/prometheus/client_golang/prometheus" + imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http" "gitlab.com/inetmock/inetmock/pkg/audit" - details "gitlab.com/inetmock/inetmock/pkg/audit/details" "gitlab.com/inetmock/inetmock/pkg/logging" "go.uber.org/zap" ) @@ -63,27 +63,6 @@ type emittingFileHandler struct { } func (f emittingFileHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { - f.emitter.Emit(eventFromRequest(request)) + f.emitter.Emit(imHttp.EventFromRequest(request, audit.AppProtocol_HTTP)) http.ServeFile(writer, request, f.targetPath) } - -func eventFromRequest(request *http.Request) audit.Event { - httpDetails := details.HTTP{ - Method: request.Method, - Host: request.Host, - URI: request.RequestURI, - Proto: request.Proto, - Headers: request.Header, - } - - ev := audit.Event{ - Transport: audit.TransportProtocol_TCP, - Application: audit.AppProtocol_HTTP, - ProtocolDetails: httpDetails, - } - - ev.SetDestinationIPFromAddr(LocalAddr(request.Context())) - ev.SetSourceIPFromAddr(RemoteAddr(request.Context())) - - return ev -} diff --git a/internal/endpoint/handler/http/proxy/handler.go b/internal/endpoint/handler/http/proxy/handler.go index 3eef03a..08c12d5 100644 --- a/internal/endpoint/handler/http/proxy/handler.go +++ b/internal/endpoint/handler/http/proxy/handler.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" + imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http" "gitlab.com/inetmock/inetmock/pkg/api" "gitlab.com/inetmock/inetmock/pkg/config" "gitlab.com/inetmock/inetmock/pkg/logging" @@ -29,7 +30,11 @@ func (h *httpProxy) Start(ctx api.PluginContext, cfg config.HandlerConfig) (err return } listenAddr := cfg.ListenAddr() - h.server = &http.Server{Addr: listenAddr, Handler: h.proxy} + h.server = &http.Server{ + Addr: listenAddr, + Handler: h.proxy, + ConnContext: imHttp.StoreConnPropertiesInContext, + } h.logger = h.logger.With( zap.String("handler_name", cfg.HandlerName), zap.String("address", listenAddr), @@ -41,16 +46,18 @@ func (h *httpProxy) Start(ctx api.PluginContext, cfg config.HandlerConfig) (err handlerName: cfg.HandlerName, options: opts, logger: h.logger, + emitter: ctx.Audit(), } - proxyHttpsHandler := &proxyHttpsHandler{ + proxyHTTPSHandler := &proxyHttpsHandler{ handlerName: cfg.HandlerName, tlsConfig: tlsConfig, logger: h.logger, + emitter: ctx.Audit(), } h.proxy.OnRequest().Do(proxyHandler) - h.proxy.OnRequest().HandleConnect(proxyHttpsHandler) + h.proxy.OnRequest().HandleConnect(proxyHTTPSHandler) go h.startProxy() return } diff --git a/internal/endpoint/handler/http/proxy/proxy_handler.go b/internal/endpoint/handler/http/proxy/proxy_handler.go index d7af5b8..6bdf26e 100644 --- a/internal/endpoint/handler/http/proxy/proxy_handler.go +++ b/internal/endpoint/handler/http/proxy/proxy_handler.go @@ -1,12 +1,13 @@ package proxy import ( - "context" "crypto/tls" "net/http" "net/url" "github.com/prometheus/client_golang/prometheus" + imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http" + "gitlab.com/inetmock/inetmock/pkg/audit" "gitlab.com/inetmock/inetmock/pkg/logging" "go.uber.org/zap" "gopkg.in/elazarl/goproxy.v1" @@ -16,12 +17,14 @@ type proxyHttpHandler struct { handlerName string options httpProxyOptions logger logging.Logger + emitter audit.Emitter } type proxyHttpsHandler struct { handlerName string tlsConfig *tls.Config logger logging.Logger + emitter audit.Emitter } func (p *proxyHttpsHandler) HandleConnect(req string, _ *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { @@ -45,15 +48,7 @@ func (p *proxyHttpHandler) Handle(req *http.Request, ctx *goproxy.ProxyCtx) (ret totalRequestCounter.WithLabelValues(p.handlerName).Inc() retReq = req - p.logger.Info( - "Handling request", - zap.String("source", req.RemoteAddr), - zap.String("host", req.Host), - zap.String("method", req.Method), - zap.String("protocol", req.Proto), - zap.String("path", req.RequestURI), - zap.Reflect("headers", req.Header), - ) + p.emitter.Emit(imHttp.EventFromRequest(req, audit.AppProtocol_HTTP_PROXY)) var err error if resp, err = ctx.RoundTrip(p.redirectHTTPRequest(req)); err != nil { @@ -95,7 +90,7 @@ func (p proxyHttpHandler) redirectHTTPRequest(originalRequest *http.Request) (re MultipartForm: originalRequest.MultipartForm, Trailer: originalRequest.Trailer, } - redirectReq = redirectReq.WithContext(context.Background()) + redirectReq = redirectReq.WithContext(originalRequest.Context()) return } diff --git a/pkg/audit/event.go b/pkg/audit/event.go index 0e7576c..dc9f696 100644 --- a/pkg/audit/event.go +++ b/pkg/audit/event.go @@ -93,6 +93,9 @@ func NewEventFromProto(msg *EventEntity) (ev Event) { } func parseIPPortFromAddr(addr net.Addr) (ip net.IP, port uint16) { + if addr == nil { + return + } switch a := addr.(type) { case *net.TCPAddr: return a.IP, uint16(a.Port)