mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-04-10 04:37:24 +00:00
Compare commits
4 Commits
35.0-dev7
...
35.0-dev11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2df9fb49db | ||
|
|
c1b2cda468 | ||
|
|
cf91f3dab4 | ||
|
|
1ebc51b45e |
@@ -54,14 +54,14 @@ ENV BPF_TARGET=arm64 BPF_CFLAGS="-O2 -g -D__TARGET_ARCH_arm64"
|
|||||||
|
|
||||||
|
|
||||||
### Builder image for x86-64 to AArch64 cross-compilation
|
### Builder image for x86-64 to AArch64 cross-compilation
|
||||||
FROM up9inc/linux-arm64-musl-go-libpcap-capstone-bpf AS builder-from-amd64-to-arm64v8
|
FROM up9inc/linux-arm64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2 AS builder-from-amd64-to-arm64v8
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
ENV GOARCH=arm64 CGO_CFLAGS="-I/work/libpcap -I/work/capstone/include"
|
ENV GOARCH=arm64 CGO_CFLAGS="-I/work/libpcap -I/work/capstone/include"
|
||||||
ENV BPF_TARGET=arm64 BPF_CFLAGS="-O2 -g -D__TARGET_ARCH_arm64 -I/usr/xcc/aarch64-linux-musl-cross/aarch64-linux-musl/include/"
|
ENV BPF_TARGET=arm64 BPF_CFLAGS="-O2 -g -D__TARGET_ARCH_arm64 -I/usr/xcc/aarch64-linux-musl-cross/aarch64-linux-musl/include/"
|
||||||
|
|
||||||
|
|
||||||
### Builder image for AArch64 to x86-64 cross-compilation
|
### Builder image for AArch64 to x86-64 cross-compilation
|
||||||
FROM up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf AS builder-from-arm64v8-to-amd64
|
FROM up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2 AS builder-from-arm64v8-to-amd64
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
ENV GOARCH=amd64 CGO_CFLAGS="-I/libpcap -I/capstone/include"
|
ENV GOARCH=amd64 CGO_CFLAGS="-I/libpcap -I/capstone/include"
|
||||||
ENV BPF_TARGET=amd64 BPF_CFLAGS="-O2 -g -D__TARGET_ARCH_x86 -I/usr/local/musl/x86_64-unknown-linux-musl/include/"
|
ENV BPF_TARGET=amd64 BPF_CFLAGS="-O2 -g -D__TARGET_ARCH_x86 -I/usr/local/musl/x86_64-unknown-linux-musl/include/"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ require (
|
|||||||
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
||||||
github.com/chanced/openapi v0.0.8
|
github.com/chanced/openapi v0.0.8
|
||||||
github.com/djherbis/atime v1.1.0
|
github.com/djherbis/atime v1.1.0
|
||||||
github.com/getkin/kin-openapi v0.89.0
|
|
||||||
github.com/gin-contrib/pprof v1.3.0
|
github.com/gin-contrib/pprof v1.3.0
|
||||||
github.com/gin-contrib/static v0.0.1
|
github.com/gin-contrib/static v0.0.1
|
||||||
github.com/gin-gonic/gin v1.7.7
|
github.com/gin-gonic/gin v1.7.7
|
||||||
@@ -59,7 +58,6 @@ require (
|
|||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fatih/camelcase v1.0.0 // indirect
|
github.com/fatih/camelcase v1.0.0 // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.2 // indirect
|
github.com/go-logr/logr v1.2.2 // indirect
|
||||||
@@ -85,7 +83,7 @@ require (
|
|||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e // indirect
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
|
|||||||
@@ -211,9 +211,6 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
|
|||||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/getkin/kin-openapi v0.89.0 h1:p4nagHchUKGn85z/f+pse4aSh50nIBOYjOhMIku2hiA=
|
|
||||||
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
||||||
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
||||||
@@ -373,7 +370,6 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c
|
|||||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
@@ -457,8 +453,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||||||
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
||||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e h1:6J5obSn9umEThiYzWzndcPOZR0Qj/sVCZpH6V1G7yNE=
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9 h1:1KszOoXSFt0aRQ6wxxcKm7QKgfLPI0TWO47UcY/f+vA=
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e/go.mod h1:1K5hEzsMBLTPdRJKEHqBFJ8Zt2VRqDhomcQ11KH0WW4=
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9/go.mod h1:1K5hEzsMBLTPdRJKEHqBFJ8Zt2VRqDhomcQ11KH0WW4=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
"github.com/getkin/kin-openapi/openapi3filter"
|
|
||||||
"github.com/getkin/kin-openapi/routers"
|
|
||||||
legacyrouter "github.com/getkin/kin-openapi/routers/legacy"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ContractNotApplicable api.ContractStatus = 0
|
|
||||||
ContractPassed api.ContractStatus = 1
|
|
||||||
ContractFailed api.ContractStatus = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
func loadOAS(ctx context.Context) (doc *openapi3.T, contractContent string, router routers.Router, err error) {
|
|
||||||
path := fmt.Sprintf("%s%s", shared.ConfigDirPath, shared.ContractFileName)
|
|
||||||
bytesValue, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
contractContent = string(bytesValue)
|
|
||||||
loader := &openapi3.Loader{Context: ctx}
|
|
||||||
doc, _ = loader.LoadFromData(bytesValue)
|
|
||||||
err = doc.Validate(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
router, _ = legacyrouter.NewRouter(doc)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response) (isValid bool, reqErr error, resErr error) {
|
|
||||||
isValid = true
|
|
||||||
reqErr = nil
|
|
||||||
resErr = nil
|
|
||||||
|
|
||||||
// Find route
|
|
||||||
route, pathParams, err := router.FindRoute(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate request
|
|
||||||
requestValidationInput := &openapi3filter.RequestValidationInput{
|
|
||||||
Request: req,
|
|
||||||
PathParams: pathParams,
|
|
||||||
Route: route,
|
|
||||||
}
|
|
||||||
if reqErr = openapi3filter.ValidateRequest(ctx, requestValidationInput); reqErr != nil {
|
|
||||||
isValid = false
|
|
||||||
}
|
|
||||||
|
|
||||||
responseValidationInput := &openapi3filter.ResponseValidationInput{
|
|
||||||
RequestValidationInput: requestValidationInput,
|
|
||||||
Status: res.StatusCode,
|
|
||||||
Header: res.Header,
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Body != nil {
|
|
||||||
body, _ := ioutil.ReadAll(res.Body)
|
|
||||||
res.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
responseValidationInput.SetBodyBytes(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate response.
|
|
||||||
if resErr = openapi3filter.ValidateResponse(ctx, responseValidationInput); resErr != nil {
|
|
||||||
isValid = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response, contractContent string) (contract api.Contract) {
|
|
||||||
contract = api.Contract{
|
|
||||||
Content: contractContent,
|
|
||||||
Status: ContractNotApplicable,
|
|
||||||
}
|
|
||||||
|
|
||||||
isValid, reqErr, resErr := validateOAS(ctx, doc, router, req, res)
|
|
||||||
if isValid {
|
|
||||||
contract.Status = ContractPassed
|
|
||||||
} else {
|
|
||||||
contract.Status = ContractFailed
|
|
||||||
if reqErr != nil {
|
|
||||||
contract.RequestReason = reqErr.Error()
|
|
||||||
} else {
|
|
||||||
contract.RequestReason = ""
|
|
||||||
}
|
|
||||||
if resErr != nil {
|
|
||||||
contract.ResponseReason = resErr.Error()
|
|
||||||
} else {
|
|
||||||
contract.ResponseReason = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,16 @@ func (e *DefaultEntryStreamerSocketConnector) SendEntry(socketId int, entry *tap
|
|||||||
if params.EnableFullEntries {
|
if params.EnableFullEntries {
|
||||||
message, _ = models.CreateFullEntryWebSocketMessage(entry)
|
message, _ = models.CreateFullEntryWebSocketMessage(entry)
|
||||||
} else {
|
} else {
|
||||||
extension := extensionsMap[entry.Protocol.Name]
|
protocol, ok := protocolsMap[entry.ProtocolId]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("protocol not found, protocol: %v", protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension, ok := extensionsMap[protocol.Name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("extension not found, extension: %v", protocol.Name)
|
||||||
|
}
|
||||||
|
|
||||||
base := extension.Dissector.Summarize(entry)
|
base := extension.Dissector.Summarize(entry)
|
||||||
message, _ = models.CreateBaseEntryWebSocketMessage(base)
|
message, _ = models.CreateBaseEntryWebSocketMessage(base)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,14 +99,6 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
panic("Channel of captured messages is nil")
|
panic("Channel of captured messages is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
disableOASValidation := false
|
|
||||||
ctx := context.Background()
|
|
||||||
doc, contractContent, router, err := loadOAS(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Infof("Disabled OAS validation: %s", err.Error())
|
|
||||||
disableOASValidation = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for item := range outputItems {
|
for item := range outputItems {
|
||||||
extension := extensionsMap[item.Protocol.Name]
|
extension := extensionsMap[item.Protocol.Name]
|
||||||
resolvedSource, resolvedDestionation, namespace := resolveIP(item.ConnectionInfo)
|
resolvedSource, resolvedDestionation, namespace := resolveIP(item.ConnectionInfo)
|
||||||
@@ -117,19 +109,6 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
|
|
||||||
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestionation, namespace)
|
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestionation, namespace)
|
||||||
if extension.Protocol.Name == "http" {
|
if extension.Protocol.Name == "http" {
|
||||||
if !disableOASValidation {
|
|
||||||
var httpPair tapApi.HTTPRequestResponsePair
|
|
||||||
if err := json.Unmarshal([]byte(mizuEntry.HTTPPair), &httpPair); err != nil {
|
|
||||||
logger.Log.Error(err)
|
|
||||||
} else {
|
|
||||||
contract := handleOAS(ctx, doc, router, httpPair.Request.Payload.RawRequest, httpPair.Response.Payload.RawResponse, contractContent)
|
|
||||||
mizuEntry.ContractStatus = contract.Status
|
|
||||||
mizuEntry.ContractRequestReason = contract.RequestReason
|
|
||||||
mizuEntry.ContractResponseReason = contract.ResponseReason
|
|
||||||
mizuEntry.ContractContent = contract.Content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
harEntry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
harEntry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rules, _, _ := models.RunValidationRulesState(*harEntry, mizuEntry.Destination.Name)
|
rules, _, _ := models.RunValidationRulesState(*harEntry, mizuEntry.Destination.Name)
|
||||||
@@ -155,7 +134,7 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
serviceMapGenerator.NewTCPEntry(mizuEntry.Source, mizuEntry.Destination, &item.Protocol)
|
serviceMapGenerator.NewTCPEntry(mizuEntry.Source, mizuEntry.Destination, &item.Protocol)
|
||||||
|
|
||||||
oasGenerator := dependency.GetInstance(dependency.OasGeneratorDependency).(oas.OasGeneratorSink)
|
oasGenerator := dependency.GetInstance(dependency.OasGeneratorDependency).(oas.OasGeneratorSink)
|
||||||
oasGenerator.HandleEntry(mizuEntry)
|
oasGenerator.HandleEntry(mizuEntry, &item.Protocol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ import (
|
|||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var extensionsMap map[string]*tapApi.Extension // global
|
var (
|
||||||
|
extensionsMap map[string]*tapApi.Extension // global
|
||||||
|
protocolsMap map[string]*tapApi.Protocol //global
|
||||||
|
)
|
||||||
|
|
||||||
func InitExtensionsMap(ref map[string]*tapApi.Extension) {
|
func InitMaps(extensions map[string]*tapApi.Extension, protocols map[string]*tapApi.Protocol) {
|
||||||
extensionsMap = ref
|
extensionsMap = extensions
|
||||||
|
protocolsMap = protocols
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventHandlers interface {
|
type EventHandlers interface {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/up9inc/mizu/agent/pkg/api"
|
"github.com/up9inc/mizu/agent/pkg/api"
|
||||||
"github.com/up9inc/mizu/agent/pkg/utils"
|
"github.com/up9inc/mizu/agent/pkg/utils"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/dbgctl"
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
amqpExt "github.com/up9inc/mizu/tap/extensions/amqp"
|
amqpExt "github.com/up9inc/mizu/tap/extensions/amqp"
|
||||||
httpExt "github.com/up9inc/mizu/tap/extensions/http"
|
httpExt "github.com/up9inc/mizu/tap/extensions/http"
|
||||||
kafkaExt "github.com/up9inc/mizu/tap/extensions/kafka"
|
kafkaExt "github.com/up9inc/mizu/tap/extensions/kafka"
|
||||||
@@ -22,11 +22,13 @@ import (
|
|||||||
var (
|
var (
|
||||||
Extensions []*tapApi.Extension // global
|
Extensions []*tapApi.Extension // global
|
||||||
ExtensionsMap map[string]*tapApi.Extension // global
|
ExtensionsMap map[string]*tapApi.Extension // global
|
||||||
|
ProtocolsMap map[string]*tapApi.Protocol //global
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadExtensions() {
|
func LoadExtensions() {
|
||||||
Extensions = make([]*tapApi.Extension, 0)
|
Extensions = make([]*tapApi.Extension, 0)
|
||||||
ExtensionsMap = make(map[string]*tapApi.Extension)
|
ExtensionsMap = make(map[string]*tapApi.Extension)
|
||||||
|
ProtocolsMap = make(map[string]*tapApi.Protocol)
|
||||||
|
|
||||||
extensionHttp := &tapApi.Extension{}
|
extensionHttp := &tapApi.Extension{}
|
||||||
dissectorHttp := httpExt.NewDissector()
|
dissectorHttp := httpExt.NewDissector()
|
||||||
@@ -34,6 +36,10 @@ func LoadExtensions() {
|
|||||||
extensionHttp.Dissector = dissectorHttp
|
extensionHttp.Dissector = dissectorHttp
|
||||||
Extensions = append(Extensions, extensionHttp)
|
Extensions = append(Extensions, extensionHttp)
|
||||||
ExtensionsMap[extensionHttp.Protocol.Name] = extensionHttp
|
ExtensionsMap[extensionHttp.Protocol.Name] = extensionHttp
|
||||||
|
protocolsHttp := dissectorHttp.GetProtocols()
|
||||||
|
for k, v := range protocolsHttp {
|
||||||
|
ProtocolsMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
if !dbgctl.MizuTapperDisableNonHttpExtensions {
|
if !dbgctl.MizuTapperDisableNonHttpExtensions {
|
||||||
extensionAmqp := &tapApi.Extension{}
|
extensionAmqp := &tapApi.Extension{}
|
||||||
@@ -42,6 +48,10 @@ func LoadExtensions() {
|
|||||||
extensionAmqp.Dissector = dissectorAmqp
|
extensionAmqp.Dissector = dissectorAmqp
|
||||||
Extensions = append(Extensions, extensionAmqp)
|
Extensions = append(Extensions, extensionAmqp)
|
||||||
ExtensionsMap[extensionAmqp.Protocol.Name] = extensionAmqp
|
ExtensionsMap[extensionAmqp.Protocol.Name] = extensionAmqp
|
||||||
|
protocolsAmqp := dissectorAmqp.GetProtocols()
|
||||||
|
for k, v := range protocolsAmqp {
|
||||||
|
ProtocolsMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
extensionKafka := &tapApi.Extension{}
|
extensionKafka := &tapApi.Extension{}
|
||||||
dissectorKafka := kafkaExt.NewDissector()
|
dissectorKafka := kafkaExt.NewDissector()
|
||||||
@@ -49,6 +59,10 @@ func LoadExtensions() {
|
|||||||
extensionKafka.Dissector = dissectorKafka
|
extensionKafka.Dissector = dissectorKafka
|
||||||
Extensions = append(Extensions, extensionKafka)
|
Extensions = append(Extensions, extensionKafka)
|
||||||
ExtensionsMap[extensionKafka.Protocol.Name] = extensionKafka
|
ExtensionsMap[extensionKafka.Protocol.Name] = extensionKafka
|
||||||
|
protocolsKafka := dissectorKafka.GetProtocols()
|
||||||
|
for k, v := range protocolsKafka {
|
||||||
|
ProtocolsMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
extensionRedis := &tapApi.Extension{}
|
extensionRedis := &tapApi.Extension{}
|
||||||
dissectorRedis := redisExt.NewDissector()
|
dissectorRedis := redisExt.NewDissector()
|
||||||
@@ -56,13 +70,17 @@ func LoadExtensions() {
|
|||||||
extensionRedis.Dissector = dissectorRedis
|
extensionRedis.Dissector = dissectorRedis
|
||||||
Extensions = append(Extensions, extensionRedis)
|
Extensions = append(Extensions, extensionRedis)
|
||||||
ExtensionsMap[extensionRedis.Protocol.Name] = extensionRedis
|
ExtensionsMap[extensionRedis.Protocol.Name] = extensionRedis
|
||||||
|
protocolsRedis := dissectorRedis.GetProtocols()
|
||||||
|
for k, v := range protocolsRedis {
|
||||||
|
ProtocolsMap[k] = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(Extensions, func(i, j int) bool {
|
sort.Slice(Extensions, func(i, j int) bool {
|
||||||
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
||||||
})
|
})
|
||||||
|
|
||||||
api.InitExtensionsMap(ExtensionsMap)
|
api.InitMaps(ExtensionsMap, ProtocolsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfigureBasenineServer(host string, port string, dbSize int64, logLevel logging.Level, insertionFilter string) {
|
func ConfigureBasenineServer(host string, port string, dbSize int64, logLevel logging.Level, insertionFilter string) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package entries
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
@@ -38,11 +39,20 @@ func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesReque
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
extension := app.ExtensionsMap[entry.Protocol.Name]
|
protocol, ok := app.ProtocolsMap[entry.ProtocolId]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("protocol not found, protocol: %v", protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension, ok := app.ExtensionsMap[protocol.Name]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("extension not found, extension: %v", protocol.Name)
|
||||||
|
}
|
||||||
|
|
||||||
base := extension.Dissector.Summarize(entry)
|
base := extension.Dissector.Summarize(entry)
|
||||||
|
|
||||||
dataSlice = append(dataSlice, &tapApi.EntryWrapper{
|
dataSlice = append(dataSlice, &tapApi.EntryWrapper{
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocol,
|
||||||
Data: entry,
|
Data: entry,
|
||||||
Base: base,
|
Base: base,
|
||||||
})
|
})
|
||||||
@@ -68,7 +78,16 @@ func (e *BasenineEntriesProvider) GetEntry(singleEntryRequest *models.SingleEntr
|
|||||||
return nil, errors.New(string(bytes))
|
return nil, errors.New(string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
extension := app.ExtensionsMap[entry.Protocol.Name]
|
protocol, ok := app.ProtocolsMap[entry.ProtocolId]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("protocol not found, protocol: %v", protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension, ok := app.ExtensionsMap[protocol.Name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("extension not found, extension: %v", protocol.Name)
|
||||||
|
}
|
||||||
|
|
||||||
base := extension.Dissector.Summarize(entry)
|
base := extension.Dissector.Summarize(entry)
|
||||||
var representation []byte
|
var representation []byte
|
||||||
representation, err = extension.Dissector.Represent(entry.Request, entry.Response)
|
representation, err = extension.Dissector.Represent(entry.Request, entry.Response)
|
||||||
@@ -78,7 +97,7 @@ func (e *BasenineEntriesProvider) GetEntry(singleEntryRequest *models.SingleEntr
|
|||||||
|
|
||||||
var rules []map[string]interface{}
|
var rules []map[string]interface{}
|
||||||
var isRulesEnabled bool
|
var isRulesEnabled bool
|
||||||
if entry.Protocol.Name == "http" {
|
if protocol.Name == "http" {
|
||||||
harEntry, _ := har.NewEntry(entry.Request, entry.Response, entry.StartTime, entry.ElapsedTime)
|
harEntry, _ := har.NewEntry(entry.Request, entry.Response, entry.StartTime, entry.ElapsedTime)
|
||||||
_, rulesMatched, _isRulesEnabled := models.RunValidationRulesState(*harEntry, entry.Destination.Name)
|
_, rulesMatched, _isRulesEnabled := models.RunValidationRulesState(*harEntry, entry.Destination.Name)
|
||||||
isRulesEnabled = _isRulesEnabled
|
isRulesEnabled = _isRulesEnabled
|
||||||
@@ -89,7 +108,7 @@ func (e *BasenineEntriesProvider) GetEntry(singleEntryRequest *models.SingleEntr
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &tapApi.EntryWrapper{
|
return &tapApi.EntryWrapper{
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocol,
|
||||||
Representation: string(representation),
|
Representation: string(representation),
|
||||||
Data: entry,
|
Data: entry,
|
||||||
Base: base,
|
Base: base,
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
"github.com/up9inc/mizu/agent/pkg/har"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
|
"github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -17,7 +16,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type OasGeneratorSink interface {
|
type OasGeneratorSink interface {
|
||||||
HandleEntry(mizuEntry *api.Entry)
|
HandleEntry(mizuEntry *api.Entry, protocol *api.Protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
type OasGenerator interface {
|
type OasGenerator interface {
|
||||||
@@ -59,12 +58,12 @@ func (g *defaultOasGenerator) IsStarted() bool {
|
|||||||
return g.started
|
return g.started
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) HandleEntry(mizuEntry *api.Entry) {
|
func (g *defaultOasGenerator) HandleEntry(mizuEntry *api.Entry, protocol *api.Protocol) {
|
||||||
if !g.started {
|
if !g.started {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if mizuEntry.Protocol.Name == "http" {
|
if protocol.Name == "http" {
|
||||||
dest := mizuEntry.Destination.Name
|
dest := mizuEntry.Destination.Name
|
||||||
if dest == "" {
|
if dest == "" {
|
||||||
logger.Log.Debugf("OAS: Unresolved entry %d", mizuEntry.Id)
|
logger.Log.Debugf("OAS: Unresolved entry %d", mizuEntry.Id)
|
||||||
@@ -86,7 +85,7 @@ func (g *defaultOasGenerator) HandleEntry(mizuEntry *api.Entry) {
|
|||||||
|
|
||||||
g.handleHARWithSource(entryWSource)
|
g.handleHARWithSource(entryWSource)
|
||||||
} else {
|
} else {
|
||||||
logger.Log.Debugf("OAS: Unsupported protocol in entry %d: %s", mizuEntry.Id, mizuEntry.Protocol.Name)
|
logger.Log.Debugf("OAS: Unsupported protocol in entry %d: %s", mizuEntry.Id, protocol.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ func init() {
|
|||||||
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
||||||
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
||||||
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
||||||
tapCmd.Flags().String(configStructs.ContractFile, defaultTapConfig.ContractFile, "OAS/Swagger file to validate to monitor the contracts")
|
|
||||||
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
||||||
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
||||||
tapCmd.Flags().Bool(configStructs.ProfilerName, defaultTapConfig.Profiler, "Run pprof server")
|
tapCmd.Flags().Bool(configStructs.ProfilerName, defaultTapConfig.Profiler, "Run pprof server")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -13,7 +12,6 @@ import (
|
|||||||
"github.com/up9inc/mizu/cli/telemetry"
|
"github.com/up9inc/mizu/cli/telemetry"
|
||||||
"github.com/up9inc/mizu/cli/utils"
|
"github.com/up9inc/mizu/cli/utils"
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@@ -57,30 +55,6 @@ func RunMizuTap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and validate the OAS file
|
|
||||||
var serializedContract string
|
|
||||||
if config.Config.Tap.ContractFile != "" {
|
|
||||||
bytes, err := ioutil.ReadFile(config.Config.Tap.ContractFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error reading contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
serializedContract = string(bytes)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
loader := &openapi3.Loader{Context: ctx}
|
|
||||||
doc, err := loader.LoadFromData(bytes)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error loading contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = doc.Validate(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error validating contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubernetesProvider, err := getKubernetesProviderForCli()
|
kubernetesProvider, err := getKubernetesProviderForCli()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -124,7 +98,7 @@ func RunMizuTap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
||||||
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedValidationRules, serializedContract, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel(), config.Config.Tap.Profiler); err != nil {
|
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedValidationRules, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel(), config.Config.Tap.Profiler); err != nil {
|
||||||
var statusError *k8serrors.StatusError
|
var statusError *k8serrors.StatusError
|
||||||
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
||||||
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ const (
|
|||||||
InsertionFilterName = "insertion-filter"
|
InsertionFilterName = "insertion-filter"
|
||||||
DryRunTapName = "dry-run"
|
DryRunTapName = "dry-run"
|
||||||
EnforcePolicyFile = "traffic-validation-file"
|
EnforcePolicyFile = "traffic-validation-file"
|
||||||
ContractFile = "contract"
|
|
||||||
ServiceMeshName = "service-mesh"
|
ServiceMeshName = "service-mesh"
|
||||||
TlsName = "tls"
|
TlsName = "tls"
|
||||||
ProfilerName = "profiler"
|
ProfilerName = "profiler"
|
||||||
@@ -43,7 +42,6 @@ type TapConfig struct {
|
|||||||
InsertionFilter string `yaml:"insertion-filter" default:""`
|
InsertionFilter string `yaml:"insertion-filter" default:""`
|
||||||
DryRun bool `yaml:"dry-run" default:"false"`
|
DryRun bool `yaml:"dry-run" default:"false"`
|
||||||
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
||||||
ContractFile string `yaml:"contract"`
|
|
||||||
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
||||||
TapperResources shared.Resources `yaml:"tapper-resources"`
|
TapperResources shared.Resources `yaml:"tapper-resources"`
|
||||||
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
||||||
|
|||||||
@@ -5,16 +5,13 @@ go 1.17
|
|||||||
require (
|
require (
|
||||||
github.com/creasty/defaults v1.5.2
|
github.com/creasty/defaults v1.5.2
|
||||||
github.com/denisbrodbeck/machineid v1.0.1
|
github.com/denisbrodbeck/machineid v1.0.1
|
||||||
github.com/getkin/kin-openapi v0.89.0
|
|
||||||
github.com/google/go-github/v37 v37.0.0
|
github.com/google/go-github/v37 v37.0.0
|
||||||
github.com/google/uuid v1.3.0
|
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/spf13/cobra v1.3.0
|
github.com/spf13/cobra v1.3.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger v0.0.0
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery v0.23.3
|
||||||
@@ -39,7 +36,6 @@ require (
|
|||||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.2 // indirect
|
github.com/go-logr/logr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
@@ -52,8 +48,8 @@ require (
|
|||||||
github.com/google/go-cmp v0.5.7 // indirect
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
@@ -79,6 +75,7 @@ require (
|
|||||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
|||||||
@@ -190,9 +190,6 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
|
|||||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/getkin/kin-openapi v0.89.0 h1:p4nagHchUKGn85z/f+pse4aSh50nIBOYjOhMIku2hiA=
|
|
||||||
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
@@ -294,7 +291,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedContract string, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level, profiler bool) (bool, error) {
|
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level, profiler bool) (bool, error) {
|
||||||
if !isNsRestrictedMode {
|
if !isNsRestrictedMode {
|
||||||
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createMizuConfigmap(ctx, kubernetesProvider, serializedValidationRules, serializedContract, serializedMizuConfig, mizuResourcesNamespace); err != nil {
|
if err := createMizuConfigmap(ctx, kubernetesProvider, serializedValidationRules, serializedMizuConfig, mizuResourcesNamespace); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +71,8 @@ func createMizuNamespace(ctx context.Context, kubernetesProvider *kubernetes.Pro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMizuConfigmap(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedContract string, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
func createMizuConfigmap(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
||||||
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedValidationRules, serializedContract, serializedMizuConfig)
|
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedValidationRules, serializedMizuConfig)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ if (( $EUID != 0 )); then
|
|||||||
SUDO='sudo'
|
SUDO='sudo'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
curl https://github.com/capstone-engine/capstone/releases/download/5.0-rc2/capstone-5.0-rc2.tar.xz -Lo ./capstone.tar.xz \
|
||||||
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone \
|
&& tar -xf capstone.tar.xz && mv ./capstone-* ./capstone \
|
||||||
&& cd capstone \
|
&& cd capstone \
|
||||||
&& CAPSTONE_ARCHS="aarch64 x86" ./make.sh \
|
&& CAPSTONE_ARCHS="aarch64 x86" ./make.sh \
|
||||||
&& $SUDO ./make.sh install
|
&& $SUDO ./make.sh install
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ RUN ./configure --host=arm && make \
|
|||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
# Build and install Capstone from source
|
# Build and install Capstone from source
|
||||||
RUN curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
RUN curl https://github.com/capstone-engine/capstone/releases/download/5.0-rc2/capstone-5.0-rc2.tar.xz -Lo ./capstone.tar.xz \
|
||||||
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone
|
&& tar -xf capstone.tar.xz && mv ./capstone-* ./capstone
|
||||||
WORKDIR /work/capstone
|
WORKDIR /work/capstone
|
||||||
RUN CAPSTONE_ARCHS="aarch64" CAPSTONE_STATIC=yes ./make.sh \
|
RUN CAPSTONE_ARCHS="aarch64" CAPSTONE_STATIC=yes ./make.sh \
|
||||||
&& cp /work/capstone/libcapstone.a /usr/xcc/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/*/
|
&& cp /work/capstone/libcapstone.a /usr/xcc/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/*/
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
docker build . -t up9inc/linux-arm64-musl-go-libpcap-capstone-bpf && docker push up9inc/linux-arm64-musl-go-libpcap-capstone-bpf
|
# Build it on x86_64
|
||||||
|
docker build . -t up9inc/linux-arm64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2 && docker push up9inc/linux-arm64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ RUN ./configure --host=x86_64 && make \
|
|||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
# Build and install Capstone from source
|
# Build and install Capstone from source
|
||||||
RUN curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
RUN curl https://github.com/capstone-engine/capstone/releases/download/5.0-rc2/capstone-5.0-rc2.tar.xz -Lo ./capstone.tar.xz \
|
||||||
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone
|
&& tar -xf capstone.tar.xz && mv ./capstone-* ./capstone
|
||||||
WORKDIR /capstone
|
WORKDIR /capstone
|
||||||
RUN CAPSTONE_ARCHS="x86" CAPSTONE_STATIC=yes ./make.sh \
|
RUN CAPSTONE_ARCHS="x86" CAPSTONE_STATIC=yes ./make.sh \
|
||||||
&& cp /capstone/libcapstone.a /usr/local/musl/lib/gcc/x86_64-unknown-linux-musl/*/
|
&& cp /capstone/libcapstone.a /usr/local/musl/lib/gcc/x86_64-unknown-linux-musl/*/
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
docker build . -t up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf && docker push up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf
|
# Build it on arm64
|
||||||
|
docker build . -t up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2 && docker push up9inc/linux-x86_64-musl-go-libpcap-capstone-bpf:capstone-5.0-rc2
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ const (
|
|||||||
ConfigDirPath = "/app/config/"
|
ConfigDirPath = "/app/config/"
|
||||||
DataDirPath = "/app/data/"
|
DataDirPath = "/app/data/"
|
||||||
ValidationRulesFileName = "validation-rules.yaml"
|
ValidationRulesFileName = "validation-rules.yaml"
|
||||||
ContractFileName = "contract-oas.yaml"
|
|
||||||
ConfigFileName = "mizu-config.json"
|
ConfigFileName = "mizu-config.json"
|
||||||
DefaultApiServerPort = 8899
|
DefaultApiServerPort = 8899
|
||||||
LogLevelEnvVar = "LOG_LEVEL"
|
LogLevelEnvVar = "LOG_LEVEL"
|
||||||
|
|||||||
@@ -684,14 +684,11 @@ func (provider *Provider) handleRemovalError(err error) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedValidationRules string, serializedContract string, serializedMizuConfig string) error {
|
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedValidationRules string, serializedMizuConfig string) error {
|
||||||
configMapData := make(map[string]string)
|
configMapData := make(map[string]string)
|
||||||
if serializedValidationRules != "" {
|
if serializedValidationRules != "" {
|
||||||
configMapData[shared.ValidationRulesFileName] = serializedValidationRules
|
configMapData[shared.ValidationRulesFileName] = serializedValidationRules
|
||||||
}
|
}
|
||||||
if serializedContract != "" {
|
|
||||||
configMapData[shared.ContractFileName] = serializedContract
|
|
||||||
}
|
|
||||||
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
||||||
|
|
||||||
configMap := &core.ConfigMap{
|
configMap := &core.ConfigMap{
|
||||||
|
|||||||
252
tap/api/api.go
252
tap/api/api.go
@@ -2,24 +2,13 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/martian/har"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/tap/dbgctl"
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const mizuTestEnvVar = "MIZU_TEST"
|
|
||||||
const UnknownNamespace = ""
|
const UnknownNamespace = ""
|
||||||
|
|
||||||
var UnknownIp = net.IP{0, 0, 0, 0}
|
var UnknownIp = net.IP{0, 0, 0, 0}
|
||||||
@@ -102,7 +91,6 @@ type OutputChannelItem struct {
|
|||||||
Timestamp int64
|
Timestamp int64
|
||||||
ConnectionInfo *ConnectionInfo
|
ConnectionInfo *ConnectionInfo
|
||||||
Pair *RequestResponsePair
|
Pair *RequestResponsePair
|
||||||
Summary *BaseEntry
|
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +115,7 @@ func (p *ReadProgress) Reset() {
|
|||||||
|
|
||||||
type Dissector interface {
|
type Dissector interface {
|
||||||
Register(*Extension)
|
Register(*Extension)
|
||||||
|
GetProtocols() map[string]*Protocol
|
||||||
Ping()
|
Ping()
|
||||||
Dissect(b *bufio.Reader, reader TcpReader, options *TrafficFilteringOptions) error
|
Dissect(b *bufio.Reader, reader TcpReader, options *TrafficFilteringOptions) error
|
||||||
Analyze(item *OutputChannelItem, resolvedSource string, resolvedDestination string, namespace string) *Entry
|
Analyze(item *OutputChannelItem, resolvedSource string, resolvedDestination string, namespace string) *Entry
|
||||||
@@ -161,26 +150,21 @@ func (e *Emitting) Emit(item *OutputChannelItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Protocol Protocol `json:"proto"`
|
ProtocolId string `json:"protocol"`
|
||||||
Capture Capture `json:"capture"`
|
Capture Capture `json:"capture"`
|
||||||
Source *TCP `json:"src"`
|
Source *TCP `json:"src"`
|
||||||
Destination *TCP `json:"dst"`
|
Destination *TCP `json:"dst"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
Outgoing bool `json:"outgoing"`
|
Outgoing bool `json:"outgoing"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
StartTime time.Time `json:"startTime"`
|
StartTime time.Time `json:"startTime"`
|
||||||
Request map[string]interface{} `json:"request"`
|
Request map[string]interface{} `json:"request"`
|
||||||
Response map[string]interface{} `json:"response"`
|
Response map[string]interface{} `json:"response"`
|
||||||
RequestSize int `json:"requestSize"`
|
RequestSize int `json:"requestSize"`
|
||||||
ResponseSize int `json:"responseSize"`
|
ResponseSize int `json:"responseSize"`
|
||||||
ElapsedTime int64 `json:"elapsedTime"`
|
ElapsedTime int64 `json:"elapsedTime"`
|
||||||
Rules ApplicableRules `json:"rules,omitempty"`
|
Rules ApplicableRules `json:"rules,omitempty"`
|
||||||
ContractStatus ContractStatus `json:"contractStatus,omitempty"`
|
|
||||||
ContractRequestReason string `json:"contractRequestReason,omitempty"`
|
|
||||||
ContractResponseReason string `json:"contractResponseReason,omitempty"`
|
|
||||||
ContractContent string `json:"contractContent,omitempty"`
|
|
||||||
HTTPPair string `json:"httpPair,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntryWrapper struct {
|
type EntryWrapper struct {
|
||||||
@@ -193,22 +177,21 @@ type EntryWrapper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BaseEntry struct {
|
type BaseEntry struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Protocol Protocol `json:"proto,omitempty"`
|
Protocol Protocol `json:"proto,omitempty"`
|
||||||
Capture Capture `json:"capture"`
|
Capture Capture `json:"capture"`
|
||||||
Summary string `json:"summary,omitempty"`
|
Summary string `json:"summary,omitempty"`
|
||||||
SummaryQuery string `json:"summaryQuery,omitempty"`
|
SummaryQuery string `json:"summaryQuery,omitempty"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
StatusQuery string `json:"statusQuery"`
|
StatusQuery string `json:"statusQuery"`
|
||||||
Method string `json:"method,omitempty"`
|
Method string `json:"method,omitempty"`
|
||||||
MethodQuery string `json:"methodQuery,omitempty"`
|
MethodQuery string `json:"methodQuery,omitempty"`
|
||||||
Timestamp int64 `json:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
Source *TCP `json:"src"`
|
Source *TCP `json:"src"`
|
||||||
Destination *TCP `json:"dst"`
|
Destination *TCP `json:"dst"`
|
||||||
IsOutgoing bool `json:"isOutgoing,omitempty"`
|
IsOutgoing bool `json:"isOutgoing,omitempty"`
|
||||||
Latency int64 `json:"latency"`
|
Latency int64 `json:"latency"`
|
||||||
Rules ApplicableRules `json:"rules,omitempty"`
|
Rules ApplicableRules `json:"rules,omitempty"`
|
||||||
ContractStatus ContractStatus `json:"contractStatus"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplicableRules struct {
|
type ApplicableRules struct {
|
||||||
@@ -217,15 +200,6 @@ type ApplicableRules struct {
|
|||||||
NumberOfRules int `json:"numberOfRules,omitempty"`
|
NumberOfRules int `json:"numberOfRules,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContractStatus int
|
|
||||||
|
|
||||||
type Contract struct {
|
|
||||||
Status ContractStatus `json:"status"`
|
|
||||||
RequestReason string `json:"requestReason"`
|
|
||||||
ResponseReason string `json:"responseReason"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TABLE string = "table"
|
TABLE string = "table"
|
||||||
BODY string = "body"
|
BODY string = "body"
|
||||||
@@ -246,170 +220,6 @@ type TableData struct {
|
|||||||
Selector string `json:"selector"`
|
Selector string `json:"selector"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
TypeHttpRequest = iota
|
|
||||||
TypeHttpResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
type HTTPPayload struct {
|
|
||||||
Type uint8
|
|
||||||
Data interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPPayloader interface {
|
|
||||||
MarshalJSON() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPWrapper struct {
|
|
||||||
Method string `json:"method"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Details interface{} `json:"details"`
|
|
||||||
RawRequest *HTTPRequestWrapper `json:"rawRequest"`
|
|
||||||
RawResponse *HTTPResponseWrapper `json:"rawResponse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h HTTPPayload) MarshalJSON() ([]byte, error) {
|
|
||||||
_, testEnvEnabled := os.LookupEnv(mizuTestEnvVar)
|
|
||||||
switch h.Type {
|
|
||||||
case TypeHttpRequest:
|
|
||||||
harRequest, err := har.NewRequest(h.Data.(*http.Request), true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed converting request to HAR")
|
|
||||||
}
|
|
||||||
sort.Slice(harRequest.Headers, func(i, j int) bool {
|
|
||||||
if harRequest.Headers[i].Name < harRequest.Headers[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.Headers[i].Name > harRequest.Headers[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.Headers[i].Value < harRequest.Headers[j].Value
|
|
||||||
})
|
|
||||||
sort.Slice(harRequest.QueryString, func(i, j int) bool {
|
|
||||||
if harRequest.QueryString[i].Name < harRequest.QueryString[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.QueryString[i].Name > harRequest.QueryString[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.QueryString[i].Value < harRequest.QueryString[j].Value
|
|
||||||
})
|
|
||||||
if harRequest.PostData != nil {
|
|
||||||
sort.Slice(harRequest.PostData.Params, func(i, j int) bool {
|
|
||||||
if harRequest.PostData.Params[i].Name < harRequest.PostData.Params[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.PostData.Params[i].Name > harRequest.PostData.Params[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.PostData.Params[i].Value < harRequest.PostData.Params[j].Value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if testEnvEnabled {
|
|
||||||
harRequest.URL = ""
|
|
||||||
}
|
|
||||||
var reqWrapper *HTTPRequestWrapper
|
|
||||||
if !testEnvEnabled {
|
|
||||||
reqWrapper = &HTTPRequestWrapper{Request: h.Data.(*http.Request)}
|
|
||||||
}
|
|
||||||
return json.Marshal(&HTTPWrapper{
|
|
||||||
Method: harRequest.Method,
|
|
||||||
Details: harRequest,
|
|
||||||
RawRequest: reqWrapper,
|
|
||||||
})
|
|
||||||
case TypeHttpResponse:
|
|
||||||
harResponse, err := har.NewResponse(h.Data.(*http.Response), true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed converting response to HAR")
|
|
||||||
}
|
|
||||||
sort.Slice(harResponse.Headers, func(i, j int) bool {
|
|
||||||
if harResponse.Headers[i].Name < harResponse.Headers[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harResponse.Headers[i].Name > harResponse.Headers[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harResponse.Headers[i].Value < harResponse.Headers[j].Value
|
|
||||||
})
|
|
||||||
sort.Slice(harResponse.Cookies, func(i, j int) bool {
|
|
||||||
if harResponse.Cookies[i].Name < harResponse.Cookies[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harResponse.Cookies[i].Name > harResponse.Cookies[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harResponse.Cookies[i].Value < harResponse.Cookies[j].Value
|
|
||||||
})
|
|
||||||
var resWrapper *HTTPResponseWrapper
|
|
||||||
if !testEnvEnabled {
|
|
||||||
resWrapper = &HTTPResponseWrapper{Response: h.Data.(*http.Response)}
|
|
||||||
}
|
|
||||||
return json.Marshal(&HTTPWrapper{
|
|
||||||
Method: "",
|
|
||||||
Url: "",
|
|
||||||
Details: harResponse,
|
|
||||||
RawResponse: resWrapper,
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("HTTP payload cannot be marshaled: %v", h.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPWrapperTricky struct {
|
|
||||||
Method string `json:"method"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Details interface{} `json:"details"`
|
|
||||||
RawRequest *http.Request `json:"rawRequest"`
|
|
||||||
RawResponse *http.Response `json:"rawResponse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPMessage struct {
|
|
||||||
IsRequest bool `json:"isRequest"`
|
|
||||||
CaptureTime time.Time `json:"captureTime"`
|
|
||||||
Payload HTTPWrapperTricky `json:"payload"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPRequestResponsePair struct {
|
|
||||||
Request HTTPMessage `json:"request"`
|
|
||||||
Response HTTPMessage `json:"response"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPRequestWrapper struct {
|
|
||||||
*http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HTTPRequestWrapper) MarshalJSON() ([]byte, error) {
|
|
||||||
body, _ := ioutil.ReadAll(r.Request.Body)
|
|
||||||
r.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
return json.Marshal(&struct { //nolint
|
|
||||||
Body string `json:"Body,omitempty"`
|
|
||||||
GetBody string `json:"GetBody,omitempty"`
|
|
||||||
Cancel string `json:"Cancel,omitempty"`
|
|
||||||
*http.Request
|
|
||||||
}{
|
|
||||||
Body: string(body),
|
|
||||||
Request: r.Request,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPResponseWrapper struct {
|
|
||||||
*http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HTTPResponseWrapper) MarshalJSON() ([]byte, error) {
|
|
||||||
body, _ := ioutil.ReadAll(r.Response.Body)
|
|
||||||
r.Response.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
return json.Marshal(&struct { //nolint
|
|
||||||
Body string `json:"Body,omitempty"`
|
|
||||||
GetBody string `json:"GetBody,omitempty"`
|
|
||||||
Cancel string `json:"Cancel,omitempty"`
|
|
||||||
*http.Response
|
|
||||||
}{
|
|
||||||
Body: string(body),
|
|
||||||
Response: r.Response,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TcpReaderDataMsg interface {
|
type TcpReaderDataMsg interface {
|
||||||
GetBytes() []byte
|
GetBytes() []byte
|
||||||
GetTimestamp() time.Time
|
GetTimestamp() time.Time
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ module github.com/up9inc/mizu/tap/api
|
|||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
||||||
github.com/google/martian v2.1.0+incompatible
|
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../dbgctl
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../dbgctl
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect8/amqp/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/amqp/\* expect
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|||||||
@@ -26,12 +26,20 @@ var protocol = api.Protocol{
|
|||||||
Priority: 1,
|
Priority: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var protocolsMap = map[string]*api.Protocol{
|
||||||
|
fmt.Sprintf("%s/%s/%s", protocol.Name, protocol.Version, protocol.Abbreviation): &protocol,
|
||||||
|
}
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
extension.Protocol = &protocol
|
extension.Protocol = &protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d dissecting) GetProtocols() map[string]*api.Protocol {
|
||||||
|
return protocolsMap
|
||||||
|
}
|
||||||
|
|
||||||
func (d dissecting) Ping() {
|
func (d dissecting) Ping() {
|
||||||
log.Printf("pong %s", protocol.Name)
|
log.Printf("pong %s", protocol.Name)
|
||||||
}
|
}
|
||||||
@@ -214,8 +222,8 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
|
|
||||||
reqDetails["method"] = request["method"]
|
reqDetails["method"] = request["method"]
|
||||||
return &api.Entry{
|
return &api.Entry{
|
||||||
Protocol: protocol,
|
ProtocolId: fmt.Sprintf("%s/%s/%s", protocol.Name, protocol.Version, protocol.Abbreviation),
|
||||||
Capture: item.Capture,
|
Capture: item.Capture,
|
||||||
Source: &api.TCP{
|
Source: &api.TCP{
|
||||||
Name: resolvedSource,
|
Name: resolvedSource,
|
||||||
IP: item.ConnectionInfo.ClientIP,
|
IP: item.ConnectionInfo.ClientIP,
|
||||||
@@ -276,22 +284,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocolsMap[entry.ProtocolId],
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
StatusQuery: "",
|
StatusQuery: "",
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +330,7 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
|
|||||||
|
|
||||||
func (d dissecting) Macros() map[string]string {
|
func (d dissecting) Macros() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
`amqp`: fmt.Sprintf(`proto.name == "%s"`, protocol.Name),
|
`amqp`: fmt.Sprintf(`protocol == "%s/%s/%s"`, protocol.Name, protocol.Version, protocol.Abbreviation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func TestRegister(t *testing.T) {
|
|||||||
|
|
||||||
func TestMacros(t *testing.T) {
|
func TestMacros(t *testing.T) {
|
||||||
expectedMacros := map[string]string{
|
expectedMacros := map[string]string{
|
||||||
"amqp": `proto.name == "amqp"`,
|
"amqp": `protocol == "amqp/0-9-1/AMQP"`,
|
||||||
}
|
}
|
||||||
dissector := NewDissector()
|
dissector := NewDissector()
|
||||||
macros := dissector.Macros()
|
macros := dissector.Macros()
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect10/http/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/http/\* expect
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
|
github.com/google/martian v2.1.0+incompatible
|
||||||
github.com/mertyildiran/gqlparser/v2 v2.4.6
|
github.com/mertyildiran/gqlparser/v2 v2.4.6
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
@@ -12,7 +13,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func replaceForwardedFor(item *api.OutputChannelItem) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
|
|
||||||
forwardedFor := request.Header.Get("X-Forwarded-For")
|
forwardedFor := request.Header.Get("X-Forwarded-For")
|
||||||
if forwardedFor == "" {
|
if forwardedFor == "" {
|
||||||
|
|||||||
@@ -98,6 +98,15 @@ var graphQL2Protocol = api.Protocol{
|
|||||||
Priority: 0,
|
Priority: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var protocolsMap = map[string]*api.Protocol{
|
||||||
|
fmt.Sprintf("%s/%s/%s", http10protocol.Name, http10protocol.Version, http10protocol.Abbreviation): &http10protocol,
|
||||||
|
fmt.Sprintf("%s/%s/%s", http11protocol.Name, http11protocol.Version, http11protocol.Abbreviation): &http11protocol,
|
||||||
|
fmt.Sprintf("%s/%s/%s", http2Protocol.Name, http2Protocol.Version, http2Protocol.Abbreviation): &http2Protocol,
|
||||||
|
fmt.Sprintf("%s/%s/%s", grpcProtocol.Name, grpcProtocol.Version, grpcProtocol.Abbreviation): &grpcProtocol,
|
||||||
|
fmt.Sprintf("%s/%s/%s", graphQL1Protocol.Name, graphQL1Protocol.Version, graphQL1Protocol.Abbreviation): &graphQL1Protocol,
|
||||||
|
fmt.Sprintf("%s/%s/%s", graphQL2Protocol.Name, graphQL2Protocol.Version, graphQL2Protocol.Abbreviation): &graphQL2Protocol,
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeHttpRequest = iota
|
TypeHttpRequest = iota
|
||||||
TypeHttpResponse
|
TypeHttpResponse
|
||||||
@@ -109,6 +118,10 @@ func (d dissecting) Register(extension *api.Extension) {
|
|||||||
extension.Protocol = &http11protocol
|
extension.Protocol = &http11protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d dissecting) GetProtocols() map[string]*api.Protocol {
|
||||||
|
return protocolsMap
|
||||||
|
}
|
||||||
|
|
||||||
func (d dissecting) Ping() {
|
func (d dissecting) Ping() {
|
||||||
log.Printf("pong %s", http11protocol.Name)
|
log.Printf("pong %s", http11protocol.Name)
|
||||||
}
|
}
|
||||||
@@ -279,10 +292,10 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
if elapsedTime < 0 {
|
if elapsedTime < 0 {
|
||||||
elapsedTime = 0
|
elapsedTime = 0
|
||||||
}
|
}
|
||||||
httpPair, _ := json.Marshal(item.Pair)
|
|
||||||
return &api.Entry{
|
return &api.Entry{
|
||||||
Protocol: item.Protocol,
|
ProtocolId: fmt.Sprintf("%s/%s/%s", item.Protocol.Name, item.Protocol.Version, item.Protocol.Abbreviation),
|
||||||
Capture: item.Capture,
|
Capture: item.Capture,
|
||||||
Source: &api.TCP{
|
Source: &api.TCP{
|
||||||
Name: resolvedSource,
|
Name: resolvedSource,
|
||||||
IP: item.ConnectionInfo.ClientIP,
|
IP: item.ConnectionInfo.ClientIP,
|
||||||
@@ -302,7 +315,6 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
Timestamp: item.Timestamp,
|
Timestamp: item.Timestamp,
|
||||||
StartTime: item.Pair.Request.CaptureTime,
|
StartTime: item.Pair.Request.CaptureTime,
|
||||||
ElapsedTime: elapsedTime,
|
ElapsedTime: elapsedTime,
|
||||||
HTTPPair: string(httpPair),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,22 +327,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
statusQuery := fmt.Sprintf(`response.status == %d`, status)
|
statusQuery := fmt.Sprintf(`response.status == %d`, status)
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocolsMap[entry.ProtocolId],
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,10 +516,10 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
|
|||||||
|
|
||||||
func (d dissecting) Macros() map[string]string {
|
func (d dissecting) Macros() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
`http`: fmt.Sprintf(`proto.name == "%s" and proto.version.startsWith("%c")`, http11protocol.Name, http11protocol.Version[0]),
|
`http`: fmt.Sprintf(`protocol == "%s/%s/%s" or protocol == "%s/%s/%s"`, http10protocol.Name, http10protocol.Version, http10protocol.Abbreviation, http11protocol.Name, http11protocol.Version, http11protocol.Abbreviation),
|
||||||
`http2`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, http11protocol.Name, http2Protocol.Version),
|
`http2`: fmt.Sprintf(`protocol == "%s/%s/%s"`, http2Protocol.Name, http2Protocol.Version, http2Protocol.Abbreviation),
|
||||||
`grpc`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s" and proto.macro == "%s"`, http11protocol.Name, grpcProtocol.Version, grpcProtocol.Macro),
|
`grpc`: fmt.Sprintf(`protocol == "%s/%s/%s"`, grpcProtocol.Name, grpcProtocol.Version, grpcProtocol.Abbreviation),
|
||||||
`gql`: fmt.Sprintf(`proto.name == "%s" and proto.macro == "%s"`, graphQL1Protocol.Name, graphQL1Protocol.Macro),
|
`gql`: fmt.Sprintf(`protocol == "%s/%s/%s" or protocol == "%s/%s/%s"`, graphQL1Protocol.Name, graphQL1Protocol.Version, graphQL1Protocol.Abbreviation, graphQL2Protocol.Name, graphQL2Protocol.Version, graphQL2Protocol.Abbreviation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ func TestRegister(t *testing.T) {
|
|||||||
|
|
||||||
func TestMacros(t *testing.T) {
|
func TestMacros(t *testing.T) {
|
||||||
expectedMacros := map[string]string{
|
expectedMacros := map[string]string{
|
||||||
"http": `proto.name == "http" and proto.version.startsWith("1")`,
|
"http": `protocol == "http/1.0/HTTP" or protocol == "http/1.1/HTTP"`,
|
||||||
"http2": `proto.name == "http" and proto.version == "2.0"`,
|
"http2": `protocol == "http/2.0/HTTP/2"`,
|
||||||
"grpc": `proto.name == "http" and proto.version == "2.0" and proto.macro == "grpc"`,
|
"grpc": `protocol == "http/2.0/gRPC"`,
|
||||||
"gql": `proto.name == "http" and proto.macro == "gql"`,
|
"gql": `protocol == "http/1.1/GQL" or protocol == "http/2.0/GQL"`,
|
||||||
}
|
}
|
||||||
dissector := NewDissector()
|
dissector := NewDissector()
|
||||||
macros := dissector.Macros()
|
macros := dissector.Macros()
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func (matcher *requestResponseMatcher) registerRequest(ident string, request *ht
|
|||||||
IsRequest: true,
|
IsRequest: true,
|
||||||
CaptureTime: captureTime,
|
CaptureTime: captureTime,
|
||||||
CaptureSize: captureSize,
|
CaptureSize: captureSize,
|
||||||
Payload: api.HTTPPayload{
|
Payload: HTTPPayload{
|
||||||
Type: TypeHttpRequest,
|
Type: TypeHttpRequest,
|
||||||
Data: request,
|
Data: request,
|
||||||
},
|
},
|
||||||
@@ -53,7 +53,7 @@ func (matcher *requestResponseMatcher) registerResponse(ident string, response *
|
|||||||
IsRequest: false,
|
IsRequest: false,
|
||||||
CaptureTime: captureTime,
|
CaptureTime: captureTime,
|
||||||
CaptureSize: captureSize,
|
CaptureSize: captureSize,
|
||||||
Payload: api.HTTPPayload{
|
Payload: HTTPPayload{
|
||||||
Type: TypeHttpResponse,
|
Type: TypeHttpResponse,
|
||||||
Data: response,
|
Data: response,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func IsIgnoredUserAgent(item *api.OutputChannelItem, options *api.TrafficFilteri
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
|
|
||||||
for headerKey, headerValues := range request.Header {
|
for headerKey, headerValues := range request.Header {
|
||||||
if strings.ToLower(headerKey) == userAgent {
|
if strings.ToLower(headerKey) == userAgent {
|
||||||
@@ -50,8 +50,8 @@ func IsIgnoredUserAgent(item *api.OutputChannelItem, options *api.TrafficFilteri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FilterSensitiveData(item *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
func FilterSensitiveData(item *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
response := item.Pair.Response.Payload.(api.HTTPPayload).Data.(*http.Response)
|
response := item.Pair.Response.Payload.(HTTPPayload).Data.(*http.Response)
|
||||||
|
|
||||||
filterHeaders(&request.Header)
|
filterHeaders(&request.Header)
|
||||||
filterHeaders(&response.Header)
|
filterHeaders(&response.Header)
|
||||||
|
|||||||
100
tap/extensions/http/structs.go
Normal file
100
tap/extensions/http/structs.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/google/martian/har"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPPayload struct {
|
||||||
|
Type uint8
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTPPayloader interface {
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTPWrapper struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Details interface{} `json:"details"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h HTTPPayload) MarshalJSON() ([]byte, error) {
|
||||||
|
switch h.Type {
|
||||||
|
case TypeHttpRequest:
|
||||||
|
harRequest, err := har.NewRequest(h.Data.(*http.Request), true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed converting request to HAR")
|
||||||
|
}
|
||||||
|
sort.Slice(harRequest.Headers, func(i, j int) bool {
|
||||||
|
if harRequest.Headers[i].Name < harRequest.Headers[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.Headers[i].Name > harRequest.Headers[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.Headers[i].Value < harRequest.Headers[j].Value
|
||||||
|
})
|
||||||
|
sort.Slice(harRequest.QueryString, func(i, j int) bool {
|
||||||
|
if harRequest.QueryString[i].Name < harRequest.QueryString[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.QueryString[i].Name > harRequest.QueryString[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.QueryString[i].Value < harRequest.QueryString[j].Value
|
||||||
|
})
|
||||||
|
if harRequest.PostData != nil {
|
||||||
|
sort.Slice(harRequest.PostData.Params, func(i, j int) bool {
|
||||||
|
if harRequest.PostData.Params[i].Name < harRequest.PostData.Params[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.PostData.Params[i].Name > harRequest.PostData.Params[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.PostData.Params[i].Value < harRequest.PostData.Params[j].Value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return json.Marshal(&HTTPWrapper{
|
||||||
|
Method: harRequest.Method,
|
||||||
|
Url: "",
|
||||||
|
Details: harRequest,
|
||||||
|
})
|
||||||
|
case TypeHttpResponse:
|
||||||
|
harResponse, err := har.NewResponse(h.Data.(*http.Response), true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed converting response to HAR")
|
||||||
|
}
|
||||||
|
sort.Slice(harResponse.Headers, func(i, j int) bool {
|
||||||
|
if harResponse.Headers[i].Name < harResponse.Headers[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harResponse.Headers[i].Name > harResponse.Headers[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harResponse.Headers[i].Value < harResponse.Headers[j].Value
|
||||||
|
})
|
||||||
|
sort.Slice(harResponse.Cookies, func(i, j int) bool {
|
||||||
|
if harResponse.Cookies[i].Name < harResponse.Cookies[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harResponse.Cookies[i].Name > harResponse.Cookies[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harResponse.Cookies[i].Value < harResponse.Cookies[j].Value
|
||||||
|
})
|
||||||
|
return json.Marshal(&HTTPWrapper{
|
||||||
|
Method: "",
|
||||||
|
Url: "",
|
||||||
|
Details: harResponse,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("HTTP payload cannot be marshaled: %v", h.Type))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect9/kafka/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/kafka/\* expect
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
|||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
||||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
|||||||
@@ -24,12 +24,20 @@ var _protocol = api.Protocol{
|
|||||||
Priority: 2,
|
Priority: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var protocolsMap = map[string]*api.Protocol{
|
||||||
|
fmt.Sprintf("%s/%s/%s", _protocol.Name, _protocol.Version, _protocol.Abbreviation): &_protocol,
|
||||||
|
}
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
extension.Protocol = &_protocol
|
extension.Protocol = &_protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d dissecting) GetProtocols() map[string]*api.Protocol {
|
||||||
|
return protocolsMap
|
||||||
|
}
|
||||||
|
|
||||||
func (d dissecting) Ping() {
|
func (d dissecting) Ping() {
|
||||||
log.Printf("pong %s", _protocol.Name)
|
log.Printf("pong %s", _protocol.Name)
|
||||||
}
|
}
|
||||||
@@ -62,8 +70,8 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
elapsedTime = 0
|
elapsedTime = 0
|
||||||
}
|
}
|
||||||
return &api.Entry{
|
return &api.Entry{
|
||||||
Protocol: _protocol,
|
ProtocolId: fmt.Sprintf("%s/%s/%s", _protocol.Name, _protocol.Version, _protocol.Abbreviation),
|
||||||
Capture: item.Capture,
|
Capture: item.Capture,
|
||||||
Source: &api.TCP{
|
Source: &api.TCP{
|
||||||
Name: resolvedSource,
|
Name: resolvedSource,
|
||||||
IP: item.ConnectionInfo.ClientIP,
|
IP: item.ConnectionInfo.ClientIP,
|
||||||
@@ -186,22 +194,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocolsMap[entry.ProtocolId],
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +251,7 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
|
|||||||
|
|
||||||
func (d dissecting) Macros() map[string]string {
|
func (d dissecting) Macros() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
`kafka`: fmt.Sprintf(`proto.name == "%s"`, _protocol.Name),
|
`kafka`: fmt.Sprintf(`protocol == "%s/%s/%s"`, _protocol.Name, _protocol.Version, _protocol.Abbreviation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func TestRegister(t *testing.T) {
|
|||||||
|
|
||||||
func TestMacros(t *testing.T) {
|
func TestMacros(t *testing.T) {
|
||||||
expectedMacros := map[string]string{
|
expectedMacros := map[string]string{
|
||||||
"kafka": `proto.name == "kafka"`,
|
"kafka": `protocol == "kafka/12/KAFKA"`,
|
||||||
}
|
}
|
||||||
dissector := NewDissector()
|
dissector := NewDissector()
|
||||||
macros := dissector.Macros()
|
macros := dissector.Macros()
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect8/redis/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/redis/\* expect
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|||||||
@@ -24,12 +24,20 @@ var protocol = api.Protocol{
|
|||||||
Priority: 3,
|
Priority: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var protocolsMap = map[string]*api.Protocol{
|
||||||
|
fmt.Sprintf("%s/%s/%s", protocol.Name, protocol.Version, protocol.Abbreviation): &protocol,
|
||||||
|
}
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
extension.Protocol = &protocol
|
extension.Protocol = &protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d dissecting) GetProtocols() map[string]*api.Protocol {
|
||||||
|
return protocolsMap
|
||||||
|
}
|
||||||
|
|
||||||
func (d dissecting) Ping() {
|
func (d dissecting) Ping() {
|
||||||
log.Printf("pong %s", protocol.Name)
|
log.Printf("pong %s", protocol.Name)
|
||||||
}
|
}
|
||||||
@@ -70,8 +78,8 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
elapsedTime = 0
|
elapsedTime = 0
|
||||||
}
|
}
|
||||||
return &api.Entry{
|
return &api.Entry{
|
||||||
Protocol: protocol,
|
ProtocolId: fmt.Sprintf("%s/%s/%s", protocol.Name, protocol.Version, protocol.Abbreviation),
|
||||||
Capture: item.Capture,
|
Capture: item.Capture,
|
||||||
Source: &api.TCP{
|
Source: &api.TCP{
|
||||||
Name: resolvedSource,
|
Name: resolvedSource,
|
||||||
IP: item.ConnectionInfo.ClientIP,
|
IP: item.ConnectionInfo.ClientIP,
|
||||||
@@ -114,22 +122,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: *protocolsMap[entry.ProtocolId],
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +152,7 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
|
|||||||
|
|
||||||
func (d dissecting) Macros() map[string]string {
|
func (d dissecting) Macros() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
`redis`: fmt.Sprintf(`proto.name == "%s"`, protocol.Name),
|
`redis`: fmt.Sprintf(`protocol == "%s/%s/%s"`, protocol.Name, protocol.Version, protocol.Abbreviation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestRegister(t *testing.T) {
|
|||||||
|
|
||||||
func TestMacros(t *testing.T) {
|
func TestMacros(t *testing.T) {
|
||||||
expectedMacros := map[string]string{
|
expectedMacros := map[string]string{
|
||||||
"redis": `proto.name == "redis"`,
|
"redis": `protocol == "redis/3.x/REDIS"`,
|
||||||
}
|
}
|
||||||
dissector := NewDissector()
|
dissector := NewDissector()
|
||||||
macros := dissector.Macros()
|
macros := dissector.Macros()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/go-errors/errors v1.4.2
|
github.com/go-errors/errors v1.4.2
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
github.com/struCoder/pidusage v0.2.1
|
github.com/struCoder/pidusage v0.2.1
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger v0.0.0
|
||||||
@@ -24,7 +24,6 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/google/go-cmp v0.5.7 // indirect
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
|||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
@@ -83,8 +81,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e h1:6J5obSn9umEThiYzWzndcPOZR0Qj/sVCZpH6V1G7yNE=
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9 h1:1KszOoXSFt0aRQ6wxxcKm7QKgfLPI0TWO47UcY/f+vA=
|
||||||
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e/go.mod h1:1K5hEzsMBLTPdRJKEHqBFJ8Zt2VRqDhomcQ11KH0WW4=
|
github.com/knightsc/gapstone v0.0.0-20191231144527-6fa5afaf11a9/go.mod h1:1K5hEzsMBLTPdRJKEHqBFJ8Zt2VRqDhomcQ11KH0WW4=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
|||||||
@@ -60,7 +60,18 @@ Capstone Engine: https://www.capstone-engine.org/
|
|||||||
|
|
||||||
static __always_inline __u32 go_crypto_tls_get_fd_from_tcp_conn(struct pt_regs *ctx) {
|
static __always_inline __u32 go_crypto_tls_get_fd_from_tcp_conn(struct pt_regs *ctx) {
|
||||||
struct go_interface conn;
|
struct go_interface conn;
|
||||||
long err = bpf_probe_read(&conn, sizeof(conn), (void*)GO_ABI_INTERNAL_PT_REGS_R1(ctx));
|
long err;
|
||||||
|
__u64 addr;
|
||||||
|
#if defined(bpf_target_arm64)
|
||||||
|
err = bpf_probe_read(&addr, sizeof(addr), (void*)GO_ABI_INTERNAL_PT_REGS_SP(ctx)+0x8);
|
||||||
|
if (err != 0) {
|
||||||
|
return invalid_fd;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
addr = GO_ABI_INTERNAL_PT_REGS_R1(ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
err = bpf_probe_read(&conn, sizeof(conn), (void*)addr);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return invalid_fd;
|
return invalid_fd;
|
||||||
}
|
}
|
||||||
@@ -88,14 +99,23 @@ static __always_inline void go_crypto_tls_uprobe(struct pt_regs *ctx, struct bpf
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_info info = new_ssl_info();
|
struct ssl_info info = new_ssl_info();
|
||||||
|
long err;
|
||||||
|
|
||||||
|
#if defined(bpf_target_arm64)
|
||||||
|
err = bpf_probe_read(&info.buffer_len, sizeof(__u32), (void*)GO_ABI_INTERNAL_PT_REGS_SP(ctx)+0x18);
|
||||||
|
if (err != 0) {
|
||||||
|
log_error(ctx, LOG_ERROR_READING_BYTES_COUNT, pid_tgid, err, ORIGIN_SSL_UPROBE_CODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
info.buffer_len = GO_ABI_INTERNAL_PT_REGS_R2(ctx);
|
info.buffer_len = GO_ABI_INTERNAL_PT_REGS_R2(ctx);
|
||||||
|
#endif
|
||||||
info.buffer = (void*)GO_ABI_INTERNAL_PT_REGS_R4(ctx);
|
info.buffer = (void*)GO_ABI_INTERNAL_PT_REGS_R4(ctx);
|
||||||
info.fd = go_crypto_tls_get_fd_from_tcp_conn(ctx);
|
info.fd = go_crypto_tls_get_fd_from_tcp_conn(ctx);
|
||||||
|
|
||||||
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
||||||
__u64 pid_fp = pid << 32 | GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
__u64 pid_fp = pid << 32 | GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
||||||
long err = bpf_map_update_elem(go_context, &pid_fp, &info, BPF_ANY);
|
err = bpf_map_update_elem(go_context, &pid_fp, &info, BPF_ANY);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
log_error(ctx, LOG_ERROR_PUTTING_SSL_CONTEXT, pid_tgid, err, 0l);
|
log_error(ctx, LOG_ERROR_PUTTING_SSL_CONTEXT, pid_tgid, err, 0l);
|
||||||
@@ -130,7 +150,15 @@ static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs *ctx, struct
|
|||||||
|
|
||||||
// In case of read, the length is determined on return
|
// In case of read, the length is determined on return
|
||||||
if (flags == FLAGS_IS_READ_BIT) {
|
if (flags == FLAGS_IS_READ_BIT) {
|
||||||
|
#if defined(bpf_target_arm64)
|
||||||
|
// On ARM64 we look at a general-purpose register as an indicator of error return
|
||||||
|
if (GO_ABI_INTERNAL_PT_REGS_R6(ctx) == 0x10) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info.buffer_len = GO_ABI_INTERNAL_PT_REGS_R7(ctx); // n in return n, nil
|
||||||
|
#else
|
||||||
info.buffer_len = GO_ABI_INTERNAL_PT_REGS_R1(ctx); // n in return n, nil
|
info.buffer_len = GO_ABI_INTERNAL_PT_REGS_R1(ctx); // n in return n, nil
|
||||||
|
#endif
|
||||||
// This check achieves ignoring 0 length reads (the reads result with an error)
|
// This check achieves ignoring 0 length reads (the reads result with an error)
|
||||||
if (info.buffer_len <= 0) {
|
if (info.buffer_len <= 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -66,11 +66,12 @@ https://go.googlesource.com/go/+/refs/heads/dev.regabi/src/cmd/compile/internal-
|
|||||||
https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/AMD64Ops.go#L100
|
https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/AMD64Ops.go#L100
|
||||||
*/
|
*/
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R1(x) ((x)->eax)
|
#define GO_ABI_INTERNAL_PT_REGS_R1(x) ((x)->eax)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_P2(x) ((x)->ecx)
|
#define GO_ABI_INTERNAL_PT_REGS_R2(x) ((x)->ecx)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_P3(x) ((x)->edx)
|
#define GO_ABI_INTERNAL_PT_REGS_R3(x) ((x)->edx)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_P4(x) 0
|
#define GO_ABI_INTERNAL_PT_REGS_R4(x) 0
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_P5(x) 0
|
#define GO_ABI_INTERNAL_PT_REGS_R5(x) 0
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_P6(x) 0
|
#define GO_ABI_INTERNAL_PT_REGS_R6(x) 0
|
||||||
|
#define GO_ABI_INTERNAL_PT_REGS_R7(x) 0
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->esp)
|
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->esp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->ebp)
|
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->ebp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->e14)
|
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->e14)
|
||||||
@@ -83,6 +84,7 @@ https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/AMD6
|
|||||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->rbx)
|
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->rbx)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->rbp)
|
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->rbp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->rsi)
|
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->rsi)
|
||||||
|
#define GO_ABI_INTERNAL_PT_REGS_R7(x) ((x)->rdi)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->rsp)
|
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->rsp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->rbp)
|
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->rbp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->r14)
|
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->r14)
|
||||||
@@ -101,7 +103,8 @@ https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/ARM6
|
|||||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->uregs[3])
|
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->uregs[3])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->uregs[4])
|
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->uregs[4])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->uregs[5])
|
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->uregs[5])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->uregs[14])
|
#define GO_ABI_INTERNAL_PT_REGS_R7(x) ((x)->uregs[6])
|
||||||
|
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->uregs[13])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->uregs[29])
|
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->uregs[29])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->uregs[28])
|
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->uregs[28])
|
||||||
|
|
||||||
@@ -116,7 +119,8 @@ struct pt_regs;
|
|||||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) (((PT_REGS_ARM64 *)(x))->regs[3])
|
#define GO_ABI_INTERNAL_PT_REGS_R4(x) (((PT_REGS_ARM64 *)(x))->regs[3])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) (((PT_REGS_ARM64 *)(x))->regs[4])
|
#define GO_ABI_INTERNAL_PT_REGS_R5(x) (((PT_REGS_ARM64 *)(x))->regs[4])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) (((PT_REGS_ARM64 *)(x))->regs[5])
|
#define GO_ABI_INTERNAL_PT_REGS_R6(x) (((PT_REGS_ARM64 *)(x))->regs[5])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->regs[30])
|
#define GO_ABI_INTERNAL_PT_REGS_R7(x) (((PT_REGS_ARM64 *)(x))->regs[6])
|
||||||
|
#define GO_ABI_INTERNAL_PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29])
|
#define GO_ABI_INTERNAL_PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) (((PT_REGS_ARM64 *)(x))->regs[28])
|
#define GO_ABI_INTERNAL_PT_REGS_GP(x) (((PT_REGS_ARM64 *)(x))->regs[28])
|
||||||
|
|
||||||
@@ -132,6 +136,7 @@ https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/PPC6
|
|||||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->gpr[6])
|
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->gpr[6])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->gpr[7])
|
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->gpr[7])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->gpr[8])
|
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->gpr[8])
|
||||||
|
#define GO_ABI_INTERNAL_PT_REGS_R7(x) ((x)->gpr[9])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->sp)
|
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->sp)
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->gpr[12])
|
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->gpr[12])
|
||||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->gpr[30])
|
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->gpr[30])
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, err erro
|
|||||||
case "arm64":
|
case "arm64":
|
||||||
engine, err = gapstone.New(
|
engine, err = gapstone.New(
|
||||||
gapstone.CS_ARCH_ARM64,
|
gapstone.CS_ARCH_ARM64,
|
||||||
gapstone.CS_MODE_ARM,
|
gapstone.CS_MODE_LITTLE_ENDIAN,
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("Unsupported architecture: %v", runtime.GOARCH)
|
err = fmt.Errorf("Unsupported architecture: %v", runtime.GOARCH)
|
||||||
@@ -86,6 +86,16 @@ func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engineMajor, engineMinor := engine.Version()
|
||||||
|
logger.Log.Infof(
|
||||||
|
"Disassembling %s with Capstone %d.%d (arch: %d, mode: %d)",
|
||||||
|
filePath,
|
||||||
|
engineMajor,
|
||||||
|
engineMinor,
|
||||||
|
engine.Arch(),
|
||||||
|
engine.Mode(),
|
||||||
|
)
|
||||||
|
|
||||||
offsets = make(map[string]*goExtendedOffset)
|
offsets = make(map[string]*goExtendedOffset)
|
||||||
var fd *os.File
|
var fd *os.File
|
||||||
fd, err = os.Open(filePath)
|
fd, err = os.Open(filePath)
|
||||||
@@ -133,7 +143,7 @@ func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, err erro
|
|||||||
extendedOffset := &goExtendedOffset{enter: offset}
|
extendedOffset := &goExtendedOffset{enter: offset}
|
||||||
|
|
||||||
// source: https://gist.github.com/grantseltzer/3efa8ecc5de1fb566e8091533050d608
|
// source: https://gist.github.com/grantseltzer/3efa8ecc5de1fb566e8091533050d608
|
||||||
// skip over any symbols that aren't functinons/methods
|
// skip over any symbols that aren't functions/methods
|
||||||
if sym.Info != byte(2) && sym.Info != byte(18) {
|
if sym.Info != byte(2) && sym.Info != byte(18) {
|
||||||
offsets[sym.Name] = extendedOffset
|
offsets[sym.Name] = extendedOffset
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ func (t *TlsTapper) tapGoPid(procfs string, pid uint32, namespace string) error
|
|||||||
hooks := goHooks{}
|
hooks := goHooks{}
|
||||||
|
|
||||||
if err := hooks.installUprobes(&t.bpfObjects, exePath); err != nil {
|
if err := hooks.installUprobes(&t.bpfObjects, exePath); err != nil {
|
||||||
return err
|
logger.Log.Infof("PID skipped not a Go binary or symbol table is stripped (pid: %v) %v", pid, exePath)
|
||||||
|
return nil // hide the error on purpose, its OK for a process to be not a Go binary or stripped Go binary
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof("Tapping TLS (pid: %v) (Go: %v)", pid, exePath)
|
logger.Log.Infof("Tapping TLS (pid: %v) (Go: %v)", pid, exePath)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -147,10 +147,6 @@ export const EntryDetailed = () => {
|
|||||||
representation={entryData.representation}
|
representation={entryData.representation}
|
||||||
isRulesEnabled={entryData.isRulesEnabled}
|
isRulesEnabled={entryData.isRulesEnabled}
|
||||||
rulesMatched={entryData.rulesMatched}
|
rulesMatched={entryData.rulesMatched}
|
||||||
contractStatus={entryData.data.contractStatus}
|
|
||||||
requestReason={entryData.data.contractRequestReason}
|
|
||||||
responseReason={entryData.data.contractResponseReason}
|
|
||||||
contractContent={entryData.data.contractContent}
|
|
||||||
elapsedTime={entryData.data.elapsedTime}
|
elapsedTime={entryData.data.elapsedTime}
|
||||||
color={entryData.protocol.backgroundColor}
|
color={entryData.protocol.backgroundColor}
|
||||||
/>}
|
/>}
|
||||||
|
|||||||
@@ -364,27 +364,3 @@ export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({ tit
|
|||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntryContractSectionProps {
|
|
||||||
color: string,
|
|
||||||
requestReason: string,
|
|
||||||
responseReason: string,
|
|
||||||
contractContent: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EntryContractSection: React.FC<EntryContractSectionProps> = ({ color, requestReason, responseReason, contractContent }) => {
|
|
||||||
return <React.Fragment>
|
|
||||||
{requestReason && <EntrySectionContainer title="Request" color={color}>
|
|
||||||
{requestReason}
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
{responseReason && <EntrySectionContainer title="Response" color={color}>
|
|
||||||
{responseReason}
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
{contractContent && <EntrySectionContainer title="Contract" color={color}>
|
|
||||||
<SyntaxHighlighter
|
|
||||||
code={contractContent}
|
|
||||||
language={"yaml"}
|
|
||||||
/>
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import styles from './EntryViewer.module.sass';
|
import styles from './EntryViewer.module.sass';
|
||||||
import Tabs from "../../UI/Tabs/Tabs";
|
import Tabs from "../../UI/Tabs/Tabs";
|
||||||
import {EntryTableSection, EntryBodySection, EntryTablePolicySection, EntryContractSection} from "../EntrySections/EntrySections";
|
import {EntryTableSection, EntryBodySection, EntryTablePolicySection} from "../EntrySections/EntrySections";
|
||||||
|
|
||||||
enum SectionTypes {
|
enum SectionTypes {
|
||||||
SectionTable = "table",
|
SectionTable = "table",
|
||||||
@@ -33,7 +33,7 @@ const SectionsRepresentation: React.FC<any> = ({data, color}) => {
|
|||||||
return <React.Fragment>{sections}</React.Fragment>;
|
return <React.Fragment>{sections}</React.Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rulesMatched, contractStatus, requestReason, responseReason, contractContent, elapsedTime, color}) => {
|
const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rulesMatched, elapsedTime, color}) => {
|
||||||
var TABS = [
|
var TABS = [
|
||||||
{
|
{
|
||||||
tab: 'Request'
|
tab: 'Request'
|
||||||
@@ -50,7 +50,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
|
|
||||||
let responseTabIndex = 0;
|
let responseTabIndex = 0;
|
||||||
let rulesTabIndex = 0;
|
let rulesTabIndex = 0;
|
||||||
let contractTabIndex = 0;
|
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
TABS.push(
|
TABS.push(
|
||||||
@@ -70,15 +69,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
rulesTabIndex = TABS.length - 1;
|
rulesTabIndex = TABS.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contractStatus !== 0 && contractContent) {
|
|
||||||
TABS.push(
|
|
||||||
{
|
|
||||||
tab: 'Contract',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
contractTabIndex = TABS.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className={styles.Entry}>
|
return <div className={styles.Entry}>
|
||||||
{<div className={styles.body}>
|
{<div className={styles.body}>
|
||||||
<div className={styles.bodyHeader}>
|
<div className={styles.bodyHeader}>
|
||||||
@@ -93,9 +83,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
{isRulesEnabled && currentTab === TABS[rulesTabIndex].tab && <React.Fragment>
|
{isRulesEnabled && currentTab === TABS[rulesTabIndex].tab && <React.Fragment>
|
||||||
<EntryTablePolicySection title={'Rule'} color={color} latency={elapsedTime} arrayToIterate={rulesMatched ? rulesMatched : []}/>
|
<EntryTablePolicySection title={'Rule'} color={color} latency={elapsedTime} arrayToIterate={rulesMatched ? rulesMatched : []}/>
|
||||||
</React.Fragment>}
|
</React.Fragment>}
|
||||||
{contractStatus !== 0 && contractContent && currentTab === TABS[contractTabIndex].tab && <React.Fragment>
|
|
||||||
<EntryContractSection color={color} requestReason={requestReason} responseReason={responseReason} contractContent={contractContent}/>
|
|
||||||
</React.Fragment>}
|
|
||||||
</div>}
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
@@ -104,23 +91,15 @@ interface Props {
|
|||||||
representation: any;
|
representation: any;
|
||||||
isRulesEnabled: boolean;
|
isRulesEnabled: boolean;
|
||||||
rulesMatched: any;
|
rulesMatched: any;
|
||||||
contractStatus: number;
|
|
||||||
requestReason: string;
|
|
||||||
responseReason: string;
|
|
||||||
contractContent: string;
|
|
||||||
color: string;
|
color: string;
|
||||||
elapsedTime: number;
|
elapsedTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryViewer: React.FC<Props> = ({representation, isRulesEnabled, rulesMatched, contractStatus, requestReason, responseReason, contractContent, elapsedTime, color}) => {
|
const EntryViewer: React.FC<Props> = ({representation, isRulesEnabled, rulesMatched, elapsedTime, color}) => {
|
||||||
return <AutoRepresentation
|
return <AutoRepresentation
|
||||||
representation={representation}
|
representation={representation}
|
||||||
isRulesEnabled={isRulesEnabled}
|
isRulesEnabled={isRulesEnabled}
|
||||||
rulesMatched={rulesMatched}
|
rulesMatched={rulesMatched}
|
||||||
contractStatus={contractStatus}
|
|
||||||
requestReason={requestReason}
|
|
||||||
responseReason={responseReason}
|
|
||||||
contractContent={contractContent}
|
|
||||||
elapsedTime={elapsedTime}
|
elapsedTime={elapsedTime}
|
||||||
color={color}
|
color={color}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ interface Entry {
|
|||||||
isOutgoing?: boolean;
|
isOutgoing?: boolean;
|
||||||
latency: number;
|
latency: number;
|
||||||
rules: Rules;
|
rules: Rules;
|
||||||
contractStatus: number,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Rules {
|
interface Rules {
|
||||||
@@ -117,26 +116,6 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let contractEnabled = true;
|
|
||||||
let contractText = "";
|
|
||||||
switch (entry.contractStatus) {
|
|
||||||
case 0:
|
|
||||||
contractEnabled = false;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
additionalRulesProperties = styles.ruleSuccessRow
|
|
||||||
ruleSuccess = true
|
|
||||||
contractText = "No Breaches"
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
additionalRulesProperties = styles.ruleFailureRow
|
|
||||||
ruleSuccess = false
|
|
||||||
contractText = "Breach"
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
||||||
|
|
||||||
@@ -144,7 +123,7 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
<div
|
<div
|
||||||
id={`entry-${entry.id}`}
|
id={`entry-${entry.id}`}
|
||||||
className={`${styles.row}
|
className={`${styles.row}
|
||||||
${isSelected && !rule && !contractEnabled ? styles.rowSelected : additionalRulesProperties}`}
|
${isSelected && !rule ? styles.rowSelected : additionalRulesProperties}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!setFocusedEntryId) return;
|
if (!setFocusedEntryId) return;
|
||||||
setFocusedEntryId(entry.id);
|
setFocusedEntryId(entry.id);
|
||||||
@@ -210,18 +189,11 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
rule ?
|
rule ?
|
||||||
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule && contractEnabled ? styles.separatorRight : ""}`}>
|
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule ? styles.separatorRight : ""}`}>
|
||||||
{`Rules (${numberOfRules})`}
|
{`Rules (${numberOfRules})`}
|
||||||
</div>
|
</div>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
{
|
|
||||||
contractEnabled ?
|
|
||||||
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule && contractEnabled ? styles.separatorLeft : ""}`}>
|
|
||||||
{contractText}
|
|
||||||
</div>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
<div className={styles.separatorRight}>
|
<div className={styles.separatorRight}>
|
||||||
{headingMode ? <Queryable
|
{headingMode ? <Queryable
|
||||||
query={`namespace == "${namespace}"`}
|
query={`namespace == "${namespace}"`}
|
||||||
|
|||||||
Reference in New Issue
Block a user