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 (
|
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
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue