Added audit stream to HTTP proxy
This commit is contained in:
parent
03f3ae4173
commit
63a6516d99
7 changed files with 65 additions and 43 deletions
37
internal/endpoint/handler/http/audit.go
Normal file
37
internal/endpoint/handler/http/audit.go
Normal 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
|
||||
}
|
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue