mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-10 12:53:37 +00:00
* Add GraphQL detection * Change the abbreviation to `GQL` * Fix the `TestMacros` test case * Try to fix the security issues reported by Snyk * Run `go mod tidy` in `agent` directory * Upgrade `golang.org/x/crypto` * Downgrade `golang.org/x/crypto` * Downgrade `golang.org/x/crypto` * Downgrade `golang.org/x/crypto` * Upgrade to `github.com/vektah/gqlparser/v2 v2.4.2` * Run `go mod tidy` * Replace `github.com/vektah/gqlparser/v2` with its fork `github.com/mertyildiran/gqlparser/v2` to fix the vulns * Upgrade the `github.com/mertyildiran/gqlparser/v2 v2.4.6` * Don't upgrade `golang.org/x/net`
378 lines
8.4 KiB
Go
378 lines
8.4 KiB
Go
package http
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/up9inc/mizu/tap/api"
|
|
)
|
|
|
|
const (
|
|
binDir = "bin"
|
|
patternBin = "*_req.bin"
|
|
patternExpect = "*.json"
|
|
msgDissecting = "Dissecting:"
|
|
msgAnalyzing = "Analyzing:"
|
|
msgSummarizing = "Summarizing:"
|
|
msgRepresenting = "Representing:"
|
|
respSuffix = "_res.bin"
|
|
expectDir = "expect"
|
|
dissectDir = "dissect"
|
|
analyzeDir = "analyze"
|
|
summarizeDir = "summarize"
|
|
representDir = "represent"
|
|
testUpdate = "TEST_UPDATE"
|
|
)
|
|
|
|
func TestRegister(t *testing.T) {
|
|
dissector := NewDissector()
|
|
extension := &api.Extension{}
|
|
dissector.Register(extension)
|
|
assert.Equal(t, "http", extension.Protocol.Name)
|
|
}
|
|
|
|
func TestMacros(t *testing.T) {
|
|
expectedMacros := map[string]string{
|
|
"http": `proto.name == "http" and proto.version.startsWith("1")`,
|
|
"http2": `proto.name == "http" and proto.version == "2.0"`,
|
|
"grpc": `proto.name == "http" and proto.version == "2.0" and proto.macro == "grpc"`,
|
|
"gql": `proto.name == "http" and proto.macro == "gql"`,
|
|
}
|
|
dissector := NewDissector()
|
|
macros := dissector.Macros()
|
|
assert.Equal(t, expectedMacros, macros)
|
|
}
|
|
|
|
func TestPing(t *testing.T) {
|
|
dissector := NewDissector()
|
|
dissector.Ping()
|
|
}
|
|
|
|
func TestDissect(t *testing.T) {
|
|
_, testUpdateEnabled := os.LookupEnv(testUpdate)
|
|
|
|
expectDirDissect := path.Join(expectDir, dissectDir)
|
|
|
|
if testUpdateEnabled {
|
|
os.RemoveAll(expectDirDissect)
|
|
err := os.MkdirAll(expectDirDissect, 0775)
|
|
assert.Nil(t, err)
|
|
}
|
|
|
|
dissector := NewDissector()
|
|
paths, err := filepath.Glob(path.Join(binDir, patternBin))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
options := &api.TrafficFilteringOptions{
|
|
IgnoredUserAgents: []string{},
|
|
}
|
|
|
|
for _, _path := range paths {
|
|
basePath := _path[:len(_path)-8]
|
|
|
|
// Channel to verify the output
|
|
itemChannel := make(chan *api.OutputChannelItem)
|
|
var emitter api.Emitter = &api.Emitting{
|
|
AppStats: &api.AppStats{},
|
|
OutputChannel: itemChannel,
|
|
}
|
|
|
|
var items []*api.OutputChannelItem
|
|
stop := make(chan bool)
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-stop:
|
|
return
|
|
case item := <-itemChannel:
|
|
items = append(items, item)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Stream level
|
|
counterPair := &api.CounterPair{
|
|
Request: 0,
|
|
Response: 0,
|
|
}
|
|
|
|
// Request
|
|
pathClient := _path
|
|
fmt.Printf("%s %s\n", msgDissecting, pathClient)
|
|
fileClient, err := os.Open(pathClient)
|
|
assert.Nil(t, err)
|
|
|
|
bufferClient := bufio.NewReader(fileClient)
|
|
tcpIDClient := &api.TcpID{
|
|
SrcIP: "1",
|
|
DstIP: "2",
|
|
SrcPort: "1",
|
|
DstPort: "2",
|
|
}
|
|
reqResMatcher := dissector.NewResponseRequestMatcher()
|
|
stream := NewTcpStream(api.Pcap)
|
|
reader := NewTcpReader(
|
|
&api.ReadProgress{},
|
|
"",
|
|
tcpIDClient,
|
|
time.Time{},
|
|
stream,
|
|
true,
|
|
false,
|
|
nil,
|
|
emitter,
|
|
counterPair,
|
|
reqResMatcher,
|
|
)
|
|
err = dissector.Dissect(bufferClient, reader, options)
|
|
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
|
panic(err)
|
|
}
|
|
|
|
// Response
|
|
pathServer := basePath + respSuffix
|
|
fmt.Printf("%s %s\n", msgDissecting, pathServer)
|
|
fileServer, err := os.Open(pathServer)
|
|
assert.Nil(t, err)
|
|
|
|
bufferServer := bufio.NewReader(fileServer)
|
|
tcpIDServer := &api.TcpID{
|
|
SrcIP: "2",
|
|
DstIP: "1",
|
|
SrcPort: "2",
|
|
DstPort: "1",
|
|
}
|
|
reader = NewTcpReader(
|
|
&api.ReadProgress{},
|
|
"",
|
|
tcpIDServer,
|
|
time.Time{},
|
|
stream,
|
|
false,
|
|
false,
|
|
nil,
|
|
emitter,
|
|
counterPair,
|
|
reqResMatcher,
|
|
)
|
|
err = dissector.Dissect(bufferServer, reader, options)
|
|
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
|
panic(err)
|
|
}
|
|
|
|
fileClient.Close()
|
|
fileServer.Close()
|
|
|
|
pathExpect := path.Join(expectDirDissect, fmt.Sprintf("%s.json", basePath[4:]))
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
stop <- true
|
|
|
|
marshaled, err := json.Marshal(items)
|
|
assert.Nil(t, err)
|
|
|
|
if testUpdateEnabled {
|
|
if len(items) > 0 {
|
|
err = os.WriteFile(pathExpect, marshaled, 0644)
|
|
assert.Nil(t, err)
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(pathExpect); errors.Is(err, os.ErrNotExist) {
|
|
assert.Len(t, items, 0)
|
|
} else {
|
|
expectedBytes, err := ioutil.ReadFile(pathExpect)
|
|
assert.Nil(t, err)
|
|
|
|
assert.JSONEq(t, string(expectedBytes), string(marshaled))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAnalyze(t *testing.T) {
|
|
_, testUpdateEnabled := os.LookupEnv(testUpdate)
|
|
|
|
expectDirDissect := path.Join(expectDir, dissectDir)
|
|
expectDirAnalyze := path.Join(expectDir, analyzeDir)
|
|
|
|
if testUpdateEnabled {
|
|
os.RemoveAll(expectDirAnalyze)
|
|
err := os.MkdirAll(expectDirAnalyze, 0775)
|
|
assert.Nil(t, err)
|
|
}
|
|
|
|
dissector := NewDissector()
|
|
paths, err := filepath.Glob(path.Join(expectDirDissect, patternExpect))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, _path := range paths {
|
|
fmt.Printf("%s %s\n", msgAnalyzing, _path)
|
|
|
|
bytes, err := ioutil.ReadFile(_path)
|
|
assert.Nil(t, err)
|
|
|
|
var items []*api.OutputChannelItem
|
|
err = json.Unmarshal(bytes, &items)
|
|
assert.Nil(t, err)
|
|
|
|
var entries []*api.Entry
|
|
for _, item := range items {
|
|
entry := dissector.Analyze(item, "", "", "")
|
|
entries = append(entries, entry)
|
|
}
|
|
|
|
pathExpect := path.Join(expectDirAnalyze, filepath.Base(_path))
|
|
|
|
marshaled, err := json.Marshal(entries)
|
|
assert.Nil(t, err)
|
|
|
|
if testUpdateEnabled {
|
|
if len(entries) > 0 {
|
|
err = os.WriteFile(pathExpect, marshaled, 0644)
|
|
assert.Nil(t, err)
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(pathExpect); errors.Is(err, os.ErrNotExist) {
|
|
assert.Len(t, items, 0)
|
|
} else {
|
|
expectedBytes, err := ioutil.ReadFile(pathExpect)
|
|
assert.Nil(t, err)
|
|
|
|
assert.JSONEq(t, string(expectedBytes), string(marshaled))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSummarize(t *testing.T) {
|
|
_, testUpdateEnabled := os.LookupEnv(testUpdate)
|
|
|
|
expectDirAnalyze := path.Join(expectDir, analyzeDir)
|
|
expectDirSummarize := path.Join(expectDir, summarizeDir)
|
|
|
|
if testUpdateEnabled {
|
|
os.RemoveAll(expectDirSummarize)
|
|
err := os.MkdirAll(expectDirSummarize, 0775)
|
|
assert.Nil(t, err)
|
|
}
|
|
|
|
dissector := NewDissector()
|
|
paths, err := filepath.Glob(path.Join(expectDirAnalyze, patternExpect))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, _path := range paths {
|
|
fmt.Printf("%s %s\n", msgSummarizing, _path)
|
|
|
|
bytes, err := ioutil.ReadFile(_path)
|
|
assert.Nil(t, err)
|
|
|
|
var entries []*api.Entry
|
|
err = json.Unmarshal(bytes, &entries)
|
|
assert.Nil(t, err)
|
|
|
|
var baseEntries []*api.BaseEntry
|
|
for _, entry := range entries {
|
|
baseEntry := dissector.Summarize(entry)
|
|
baseEntries = append(baseEntries, baseEntry)
|
|
}
|
|
|
|
pathExpect := path.Join(expectDirSummarize, filepath.Base(_path))
|
|
|
|
marshaled, err := json.Marshal(baseEntries)
|
|
assert.Nil(t, err)
|
|
|
|
if testUpdateEnabled {
|
|
if len(baseEntries) > 0 {
|
|
err = os.WriteFile(pathExpect, marshaled, 0644)
|
|
assert.Nil(t, err)
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(pathExpect); errors.Is(err, os.ErrNotExist) {
|
|
assert.Len(t, entries, 0)
|
|
} else {
|
|
expectedBytes, err := ioutil.ReadFile(pathExpect)
|
|
assert.Nil(t, err)
|
|
|
|
assert.JSONEq(t, string(expectedBytes), string(marshaled))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRepresent(t *testing.T) {
|
|
_, testUpdateEnabled := os.LookupEnv(testUpdate)
|
|
|
|
expectDirAnalyze := path.Join(expectDir, analyzeDir)
|
|
expectDirRepresent := path.Join(expectDir, representDir)
|
|
|
|
if testUpdateEnabled {
|
|
os.RemoveAll(expectDirRepresent)
|
|
err := os.MkdirAll(expectDirRepresent, 0775)
|
|
assert.Nil(t, err)
|
|
}
|
|
|
|
dissector := NewDissector()
|
|
paths, err := filepath.Glob(path.Join(expectDirAnalyze, patternExpect))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, _path := range paths {
|
|
fmt.Printf("%s %s\n", msgRepresenting, _path)
|
|
|
|
bytes, err := ioutil.ReadFile(_path)
|
|
assert.Nil(t, err)
|
|
|
|
var entries []*api.Entry
|
|
err = json.Unmarshal(bytes, &entries)
|
|
assert.Nil(t, err)
|
|
|
|
var objects []string
|
|
for _, entry := range entries {
|
|
object, err := dissector.Represent(entry.Request, entry.Response)
|
|
assert.Nil(t, err)
|
|
objects = append(objects, string(object))
|
|
}
|
|
|
|
pathExpect := path.Join(expectDirRepresent, filepath.Base(_path))
|
|
|
|
marshaled, err := json.Marshal(objects)
|
|
assert.Nil(t, err)
|
|
|
|
if testUpdateEnabled {
|
|
if len(objects) > 0 {
|
|
err = os.WriteFile(pathExpect, marshaled, 0644)
|
|
assert.Nil(t, err)
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(pathExpect); errors.Is(err, os.ErrNotExist) {
|
|
assert.Len(t, objects, 0)
|
|
} else {
|
|
expectedBytes, err := ioutil.ReadFile(pathExpect)
|
|
assert.Nil(t, err)
|
|
|
|
assert.JSONEq(t, string(expectedBytes), string(marshaled))
|
|
}
|
|
}
|
|
}
|
|
}
|