Added audit stream to HTTP proxy

This commit is contained in:
Peter 2021-01-20 19:03:05 +01:00
parent 03f3ae4173
commit 63a6516d99
Signed by: prskr
GPG key ID: C1DB5D2E8DB512F9
7 changed files with 65 additions and 43 deletions

View file

@ -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
}

View file

@ -1,4 +1,4 @@
package mock package http
import ( import (
"context" "context"
@ -8,8 +8,8 @@ import (
type httpContextKey string type httpContextKey string
const ( const (
remoteAddrKey httpContextKey = "RemoteAddr" remoteAddrKey httpContextKey = "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http/context/remoteAddr"
localAddrKey httpContextKey = "LocalAddr" localAddrKey httpContextKey = "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http/context/localAddr"
) )
func StoreConnPropertiesInContext(ctx context.Context, c net.Conn) context.Context { 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 return ctx
} }
func LocalAddr(ctx context.Context) net.Addr { func localAddr(ctx context.Context) net.Addr {
val := ctx.Value(localAddrKey) val := ctx.Value(localAddrKey)
if val == nil { if val == nil {
return nil return nil
@ -26,7 +26,7 @@ func LocalAddr(ctx context.Context) net.Addr {
return val.(net.Addr) return val.(net.Addr)
} }
func RemoteAddr(ctx context.Context) net.Addr { func remoteAddr(ctx context.Context) net.Addr {
val := ctx.Value(remoteAddrKey) val := ctx.Value(remoteAddrKey)
if val == nil { if val == nil {
return nil return nil

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http"
"gitlab.com/inetmock/inetmock/pkg/api" "gitlab.com/inetmock/inetmock/pkg/api"
"gitlab.com/inetmock/inetmock/pkg/config" "gitlab.com/inetmock/inetmock/pkg/config"
"gitlab.com/inetmock/inetmock/pkg/logging" "gitlab.com/inetmock/inetmock/pkg/logging"
@ -46,7 +47,7 @@ func (p *httpHandler) Start(ctx api.PluginContext, config config.HandlerConfig)
p.server = &http.Server{ p.server = &http.Server{
Addr: config.ListenAddr(), Addr: config.ListenAddr(),
Handler: router, Handler: router,
ConnContext: StoreConnPropertiesInContext, ConnContext: imHttp.StoreConnPropertiesInContext,
} }
for _, rule := range options.Rules { for _, rule := range options.Rules {

View file

@ -5,8 +5,8 @@ import (
"strconv" "strconv"
"github.com/prometheus/client_golang/prometheus" "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/audit"
details "gitlab.com/inetmock/inetmock/pkg/audit/details"
"gitlab.com/inetmock/inetmock/pkg/logging" "gitlab.com/inetmock/inetmock/pkg/logging"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -63,27 +63,6 @@ type emittingFileHandler struct {
} }
func (f emittingFileHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { 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) 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
}

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http"
"gitlab.com/inetmock/inetmock/pkg/api" "gitlab.com/inetmock/inetmock/pkg/api"
"gitlab.com/inetmock/inetmock/pkg/config" "gitlab.com/inetmock/inetmock/pkg/config"
"gitlab.com/inetmock/inetmock/pkg/logging" "gitlab.com/inetmock/inetmock/pkg/logging"
@ -29,7 +30,11 @@ func (h *httpProxy) Start(ctx api.PluginContext, cfg config.HandlerConfig) (err
return return
} }
listenAddr := cfg.ListenAddr() 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( h.logger = h.logger.With(
zap.String("handler_name", cfg.HandlerName), zap.String("handler_name", cfg.HandlerName),
zap.String("address", listenAddr), zap.String("address", listenAddr),
@ -41,16 +46,18 @@ func (h *httpProxy) Start(ctx api.PluginContext, cfg config.HandlerConfig) (err
handlerName: cfg.HandlerName, handlerName: cfg.HandlerName,
options: opts, options: opts,
logger: h.logger, logger: h.logger,
emitter: ctx.Audit(),
} }
proxyHttpsHandler := &proxyHttpsHandler{ proxyHTTPSHandler := &proxyHttpsHandler{
handlerName: cfg.HandlerName, handlerName: cfg.HandlerName,
tlsConfig: tlsConfig, tlsConfig: tlsConfig,
logger: h.logger, logger: h.logger,
emitter: ctx.Audit(),
} }
h.proxy.OnRequest().Do(proxyHandler) h.proxy.OnRequest().Do(proxyHandler)
h.proxy.OnRequest().HandleConnect(proxyHttpsHandler) h.proxy.OnRequest().HandleConnect(proxyHTTPSHandler)
go h.startProxy() go h.startProxy()
return return
} }

View file

@ -1,12 +1,13 @@
package proxy package proxy
import ( import (
"context"
"crypto/tls" "crypto/tls"
"net/http" "net/http"
"net/url" "net/url"
"github.com/prometheus/client_golang/prometheus" "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" "gitlab.com/inetmock/inetmock/pkg/logging"
"go.uber.org/zap" "go.uber.org/zap"
"gopkg.in/elazarl/goproxy.v1" "gopkg.in/elazarl/goproxy.v1"
@ -16,12 +17,14 @@ type proxyHttpHandler struct {
handlerName string handlerName string
options httpProxyOptions options httpProxyOptions
logger logging.Logger logger logging.Logger
emitter audit.Emitter
} }
type proxyHttpsHandler struct { type proxyHttpsHandler struct {
handlerName string handlerName string
tlsConfig *tls.Config tlsConfig *tls.Config
logger logging.Logger logger logging.Logger
emitter audit.Emitter
} }
func (p *proxyHttpsHandler) HandleConnect(req string, _ *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { 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() totalRequestCounter.WithLabelValues(p.handlerName).Inc()
retReq = req retReq = req
p.logger.Info( p.emitter.Emit(imHttp.EventFromRequest(req, audit.AppProtocol_HTTP_PROXY))
"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),
)
var err error var err error
if resp, err = ctx.RoundTrip(p.redirectHTTPRequest(req)); err != nil { 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, MultipartForm: originalRequest.MultipartForm,
Trailer: originalRequest.Trailer, Trailer: originalRequest.Trailer,
} }
redirectReq = redirectReq.WithContext(context.Background()) redirectReq = redirectReq.WithContext(originalRequest.Context())
return return
} }

View file

@ -93,6 +93,9 @@ func NewEventFromProto(msg *EventEntity) (ev Event) {
} }
func parseIPPortFromAddr(addr net.Addr) (ip net.IP, port uint16) { func parseIPPortFromAddr(addr net.Addr) (ip net.IP, port uint16) {
if addr == nil {
return
}
switch a := addr.(type) { switch a := addr.(type) {
case *net.TCPAddr: case *net.TCPAddr:
return a.IP, uint16(a.Port) return a.IP, uint16(a.Port)