mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-06 04:32:12 +00:00
Compare commits
44 Commits
31.0-dev44
...
32.0-dev2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fadd052f02 | ||
|
|
171b72831f | ||
|
|
36910c84ed | ||
|
|
95a37c877e | ||
|
|
7ce74c71b4 | ||
|
|
6a15bf1aed | ||
|
|
2de57a6630 | ||
|
|
b5c5a8934b | ||
|
|
df269fa950 | ||
|
|
80ebd7199d | ||
|
|
9b475a78f9 | ||
|
|
d76f24edb8 | ||
|
|
32ba653d12 | ||
|
|
e03db7b09b | ||
|
|
de533730d3 | ||
|
|
d834fcc3cb | ||
|
|
1624b0d7b9 | ||
|
|
9715bb046b | ||
|
|
65e5ebe23c | ||
|
|
30986c3b22 | ||
|
|
1e167f2757 | ||
|
|
149e86d050 | ||
|
|
1213162b85 | ||
|
|
189c158150 | ||
|
|
c5006e5f57 | ||
|
|
d7fcf273c0 | ||
|
|
eca3267b47 | ||
|
|
a527fc6c51 | ||
|
|
e104128df8 | ||
|
|
5bb904d068 | ||
|
|
dc0365dfb0 | ||
|
|
84f641d8fe | ||
|
|
ac94554d2f | ||
|
|
2ef6afa395 | ||
|
|
697bfef861 | ||
|
|
f8c0ddd69a | ||
|
|
2253737625 | ||
|
|
4a0294c61a | ||
|
|
9053c58146 | ||
|
|
5d5b13fc86 | ||
|
|
af61c69fb6 | ||
|
|
94dfa68858 | ||
|
|
50c0062db4 | ||
|
|
720969bbe6 |
16
.github/workflows/acceptance_tests.yml
vendored
16
.github/workflows/acceptance_tests.yml
vendored
@@ -8,6 +8,9 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- 'develop'
|
- 'develop'
|
||||||
|
|
||||||
|
env:
|
||||||
|
MIZU_CI_IMAGE: mizu/ci:0.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-acceptance-tests:
|
run-acceptance-tests:
|
||||||
name: Run acceptance tests
|
name: Run acceptance tests
|
||||||
@@ -21,6 +24,19 @@ jobs:
|
|||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: ${{ env.MIZU_CI_IMAGE }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
- name: Setup acceptance test
|
- name: Setup acceptance test
|
||||||
run: ./acceptanceTests/setup.sh
|
run: ./acceptanceTests/setup.sh
|
||||||
|
|
||||||
|
|||||||
54
.github/workflows/acceptance_tests_on_pr.yml
vendored
Normal file
54
.github/workflows/acceptance_tests_on_pr.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
name: Acceptance tests on PR
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
env:
|
||||||
|
MIZU_CI_IMAGE: mizu/ci:0.0
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: acceptance-tests-on-pr-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-tests:
|
||||||
|
name: Run tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ contains(github.event.head_commit.message, '#run_acceptance_tests') }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Go 1.17
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '^1.17'
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: ${{ env.MIZU_CI_IMAGE }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Setup acceptance test
|
||||||
|
run: ./acceptanceTests/setup.sh
|
||||||
|
|
||||||
|
- name: Create k8s users and change context
|
||||||
|
env:
|
||||||
|
USERNAME_UNRESTRICTED: user-with-clusterwide-access
|
||||||
|
USERNAME_RESTRICTED: user-with-restricted-access
|
||||||
|
run: |
|
||||||
|
./acceptanceTests/create_user.sh "${USERNAME_UNRESTRICTED}"
|
||||||
|
./acceptanceTests/create_user.sh "${USERNAME_RESTRICTED}"
|
||||||
|
kubectl apply -f cli/cmd/permissionFiles/permissions-all-namespaces-tap.yaml
|
||||||
|
kubectl config use-context ${USERNAME_UNRESTRICTED}
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make acceptance-test
|
||||||
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check extensions modified files
|
- name: Check extensions modified files
|
||||||
id: ext_modified_files
|
id: ext_modified_files
|
||||||
run: devops/check_modified_files.sh tap/extensions/
|
run: devops/check_modified_files.sh tap/extensions/ tap/api/
|
||||||
|
|
||||||
- name: Extensions Test
|
- name: Extensions Test
|
||||||
if: github.event_name == 'push' || steps.ext_modified_files.outputs.matched == 'true'
|
if: github.event_name == 'push' || steps.ext_modified_files.outputs.matched == 'true'
|
||||||
@@ -64,4 +64,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v2
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ RUN go build -ldflags="-extldflags=-static -s -w \
|
|||||||
-X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent .
|
-X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent .
|
||||||
|
|
||||||
# Download Basenine executable, verify the sha1sum
|
# Download Basenine executable, verify the sha1sum
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.7.1/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
ADD https://github.com/up9inc/basenine/releases/download/v0.7.3/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.7.1/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
ADD https://github.com/up9inc/basenine/releases/download/v0.7.3/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
||||||
|
|
||||||
RUN shasum -a 256 -c basenine_linux_"${GOARCH}".sha256 && \
|
RUN shasum -a 256 -c basenine_linux_"${GOARCH}".sha256 && \
|
||||||
chmod +x ./basenine_linux_"${GOARCH}" && \
|
chmod +x ./basenine_linux_"${GOARCH}" && \
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ function deeperCheck(leftSidePath, rightSidePath, filterName, leftSideExpectedTe
|
|||||||
const entryId = getEntryId(element[0].id);
|
const entryId = getEntryId(element[0].id);
|
||||||
leftOnHoverCheck(entryId, leftSidePath, filterName);
|
leftOnHoverCheck(entryId, leftSidePath, filterName);
|
||||||
|
|
||||||
element.click();
|
cy.get(`#list #entry-${entryId}`).click();
|
||||||
rightTextCheck(rightSidePath, rightSideExpectedText);
|
rightTextCheck(rightSidePath, rightSideExpectedText);
|
||||||
rightOnHoverCheck(rightSidePath, filterName);
|
rightOnHoverCheck(rightSidePath, filterName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,11 +57,16 @@ kubectl expose deployment rabbitmq --type=LoadBalancer --port=5672 -n mizu-tests
|
|||||||
echo "Starting proxy"
|
echo "Starting proxy"
|
||||||
kubectl proxy --port=8080 &
|
kubectl proxy --port=8080 &
|
||||||
|
|
||||||
echo "Setting minikube docker env"
|
if [[ -z "${CI}" ]]; then
|
||||||
eval $(minikube docker-env)
|
echo "Setting env var of mizu ci image"
|
||||||
|
export MIZU_CI_IMAGE="mizu/ci:0.0"
|
||||||
|
echo "Build agent image"
|
||||||
|
docker build -t "${MIZU_CI_IMAGE}" .
|
||||||
|
else
|
||||||
|
echo "not building docker image in CI because it is created as separate step"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Build agent image"
|
minikube image load "${MIZU_CI_IMAGE}"
|
||||||
docker build -t mizu/ci:0.0 .
|
|
||||||
|
|
||||||
echo "Build cli"
|
echo "Build cli"
|
||||||
cd cli && make build GIT_BRANCH=ci SUFFIX=ci
|
cd cli && make build GIT_BRANCH=ci SUFFIX=ci
|
||||||
|
|||||||
@@ -212,9 +212,10 @@ func DeleteKubeFile(kubeContext string, namespace string, filename string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultCommandArgs() []string {
|
func getDefaultCommandArgs() []string {
|
||||||
|
agentImageValue := os.Getenv("MIZU_CI_IMAGE")
|
||||||
setFlag := "--set"
|
setFlag := "--set"
|
||||||
telemetry := "telemetry=false"
|
telemetry := "telemetry=false"
|
||||||
agentImage := "agent-image=mizu/ci:0.0"
|
agentImage := fmt.Sprintf("agent-image=%s", agentImageValue)
|
||||||
imagePullPolicy := "image-pull-policy=IfNotPresent"
|
imagePullPolicy := "image-pull-policy=IfNotPresent"
|
||||||
headless := "headless=true"
|
headless := "headless=true"
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ require (
|
|||||||
github.com/nav-inc/datetime v0.1.3
|
github.com/nav-inc/datetime v0.1.3
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/orcaman/concurrent-map v1.0.0
|
github.com/orcaman/concurrent-map v1.0.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220413023528-c741e4aa1cf2
|
github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap v0.0.0
|
github.com/up9inc/mizu/tap v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
@@ -49,7 +49,6 @@ require (
|
|||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/beevik/etree v1.1.0 // indirect
|
github.com/beevik/etree v1.1.0 // indirect
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4 // indirect
|
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
||||||
github.com/chanced/dynamic v0.0.0-20211210164248-f8fadb1d735b // indirect
|
github.com/chanced/dynamic v0.0.0-20211210164248-f8fadb1d735b // indirect
|
||||||
github.com/cilium/ebpf v0.8.0 // indirect
|
github.com/cilium/ebpf v0.8.0 // indirect
|
||||||
|
|||||||
@@ -108,8 +108,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4 h1:NJOOlc6ZJjix0A1rAU+nxruZtR8KboG1848yqpIUo4M=
|
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4/go.mod h1:DQPxZS994Ld1Y8uwnJT+dRL04XPD0cElP/pHH/zEBHM=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
@@ -683,8 +681,8 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn
|
|||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220413023528-c741e4aa1cf2 h1:2Ol+X82EOLac/GGP/oB0ACVP/g2vIJrAuzCjZcn+RRI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607 h1:UqxUSkOYOmsLZWQtMSk02ttnhdRwBRLOLt2aDiS9tEk=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220413023528-c741e4aa1cf2/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw=
|
github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw=
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ func dialSocketWithRetry(socketAddress string, retryAmount int, retryDelay time.
|
|||||||
for i := 1; i < retryAmount; i++ {
|
for i := 1; i < retryAmount; i++ {
|
||||||
socketConnection, _, err := dialer.Dial(socketAddress, nil)
|
socketConnection, _, err := dialer.Dial(socketAddress, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
lastErr = err
|
||||||
if i < retryAmount {
|
if i < retryAmount {
|
||||||
logger.Log.Infof("socket connection to %s failed: %v, retrying %d out of %d in %d seconds...", socketAddress, err, i, retryAmount, retryDelay/time.Second)
|
logger.Log.Infof("socket connection to %s failed: %v, retrying %d out of %d in %d seconds...", socketAddress, err, i, retryAmount, retryDelay/time.Second)
|
||||||
time.Sleep(retryDelay)
|
time.Sleep(retryDelay)
|
||||||
|
|||||||
@@ -103,12 +103,18 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
panic("Channel of captured messages is nil")
|
panic("Channel of captured messages is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BasenineReconnect:
|
||||||
connection, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
connection, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Panicf("Can't establish a new connection to Basenine server: %v", err)
|
logger.Log.Errorf("Can't establish a new connection to Basenine server: %v", err)
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
goto BasenineReconnect
|
||||||
}
|
}
|
||||||
if err = connection.InsertMode(); err != nil {
|
if err = connection.InsertMode(); err != nil {
|
||||||
logger.Log.Panicf("Insert mode call failed: %v", err)
|
logger.Log.Errorf("Insert mode call failed: %v", err)
|
||||||
|
connection.Close()
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
goto BasenineReconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
disableOASValidation := false
|
disableOASValidation := false
|
||||||
@@ -122,19 +128,24 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
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)
|
||||||
|
|
||||||
|
if namespace == "" && item.Namespace != tapApi.UNKNOWN_NAMESPACE {
|
||||||
|
namespace = item.Namespace
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
if !disableOASValidation {
|
||||||
var httpPair tapApi.HTTPRequestResponsePair
|
var httpPair tapApi.HTTPRequestResponsePair
|
||||||
if err := json.Unmarshal([]byte(mizuEntry.HTTPPair), &httpPair); err != nil {
|
if err := json.Unmarshal([]byte(mizuEntry.HTTPPair), &httpPair); err != nil {
|
||||||
logger.Log.Error(err)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -146,13 +157,17 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
|
|
||||||
data, err := json.Marshal(mizuEntry)
|
data, err := json.Marshal(mizuEntry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Log.Errorf("Error while marshaling entry: %v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
providers.EntryAdded(len(data))
|
providers.EntryAdded(len(data))
|
||||||
|
|
||||||
if err = connection.SendText(string(data)); err != nil {
|
if err = connection.SendText(string(data)); err != nil {
|
||||||
logger.Log.Panicf("An error occured while inserting a new record to database: %v", err)
|
logger.Log.Errorf("An error occured while inserting a new record to database: %v", err)
|
||||||
|
connection.Close()
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
goto BasenineReconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMapSink)
|
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMapSink)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
|
|
||||||
connection, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
connection, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Errorf("failed to establish a connection to Basenine: %v", err)
|
logger.Log.Errorf("Failed to establish a connection to Basenine: %v", err)
|
||||||
entryStreamerSocketConnector.CleanupSocket(socketId)
|
entryStreamerSocketConnector.CleanupSocket(socketId)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,9 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
go handleMetaChannel(connection, meta)
|
go handleMetaChannel(connection, meta)
|
||||||
|
|
||||||
if err = connection.Query(query, data, meta); err != nil {
|
if err = connection.Query(query, data, meta); err != nil {
|
||||||
logger.Log.Panicf("Query mode call failed: %v", err)
|
logger.Log.Errorf("Query mode call failed: %v", err)
|
||||||
|
entryStreamerSocketConnector.CleanupSocket(socketId)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -123,22 +123,23 @@ func SendToSocket(socketId int, message []byte) error {
|
|||||||
return fmt.Errorf("socket %v is disconnected", socketId)
|
return fmt.Errorf("socket %v is disconnected", socketId)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sent = false
|
|
||||||
time.AfterFunc(time.Second*5, func() {
|
|
||||||
if !sent {
|
|
||||||
logger.Log.Error("socket timed out")
|
|
||||||
socketCleanup(socketId, socketObj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
socketObj.lock.Lock() // gorilla socket panics from concurrent writes to a single socket
|
socketObj.lock.Lock() // gorilla socket panics from concurrent writes to a single socket
|
||||||
err := socketObj.connection.WriteMessage(1, message)
|
defer socketObj.lock.Unlock()
|
||||||
socketObj.lock.Unlock()
|
|
||||||
sent = true
|
|
||||||
|
|
||||||
if err != nil {
|
if connectedWebsockets[socketId] == nil {
|
||||||
return fmt.Errorf("failed to write message to socket %v, err: %w", socketId, err)
|
return fmt.Errorf("socket %v is disconnected", socketId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := socketObj.connection.SetWriteDeadline(time.Now().Add(time.Second * 10)); err != nil {
|
||||||
|
socketCleanup(socketId, socketObj)
|
||||||
|
return fmt.Errorf("error setting timeout to socket %v, err: %v", socketId, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := socketObj.connection.WriteMessage(websocket.TextMessage, message); err != nil {
|
||||||
|
socketCleanup(socketId, socketObj)
|
||||||
|
return fmt.Errorf("failed to write message to socket %v, err: %v", socketId, err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -93,10 +94,6 @@ func GetGeneralStats(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, providers.GetGeneralStats())
|
c.JSON(http.StatusOK, providers.GetGeneralStats())
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRecentTLSLinks(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, providers.GetAllRecentTLSAddresses())
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCurrentResolvingInformation(c *gin.Context) {
|
func GetCurrentResolvingInformation(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, holder.GetResolver().GetMap())
|
c.JSON(http.StatusOK, holder.GetResolver().GetMap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package entries
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
@@ -64,7 +65,7 @@ func (e *BasenineEntriesProvider) GetEntry(singleEntryRequest *models.SingleEntr
|
|||||||
}
|
}
|
||||||
err = json.Unmarshal(bytes, &entry)
|
err = json.Unmarshal(bytes, &entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.New(string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
extension := app.ExtensionsMap[entry.Protocol.Name]
|
extension := app.ExtensionsMap[entry.Protocol.Name]
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
"github.com/up9inc/mizu/tap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntriesRequest struct {
|
type EntriesRequest struct {
|
||||||
@@ -44,11 +43,6 @@ type WebSocketTappedEntryMessage struct {
|
|||||||
Data *tapApi.OutputChannelItem
|
Data *tapApi.OutputChannelItem
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsocketOutboundLinkMessage struct {
|
|
||||||
*shared.WebSocketMessageMetadata
|
|
||||||
Data *tap.OutboundLink
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthStatus struct {
|
type AuthStatus struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
|
|||||||
@@ -142,17 +142,18 @@ func (g *defaultOasGenerator) runGenerator() {
|
|||||||
|
|
||||||
func (g *defaultOasGenerator) handleEntry(mizuEntry *api.Entry) {
|
func (g *defaultOasGenerator) handleEntry(mizuEntry *api.Entry) {
|
||||||
if mizuEntry.Protocol.Name == "http" {
|
if mizuEntry.Protocol.Name == "http" {
|
||||||
|
dest := mizuEntry.Destination.Name
|
||||||
|
if dest == "" {
|
||||||
|
logger.Log.Debugf("OAS: Unresolved entry %d", mizuEntry.Id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
entry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
entry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Warningf("Failed to turn MizuEntry %d into HAR Entry: %s", mizuEntry.Id, err)
|
logger.Log.Warningf("Failed to turn MizuEntry %d into HAR Entry: %s", mizuEntry.Id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dest := mizuEntry.Destination.Name
|
|
||||||
if dest == "" {
|
|
||||||
dest = mizuEntry.Destination.IP + ":" + mizuEntry.Destination.Port
|
|
||||||
}
|
|
||||||
|
|
||||||
entryWSource := &EntryWithSource{
|
entryWSource := &EntryWithSource{
|
||||||
Entry: *entry,
|
Entry: *entry,
|
||||||
Source: mizuEntry.Source.Name,
|
Source: mizuEntry.Source.Name,
|
||||||
|
|||||||
@@ -4,19 +4,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
"github.com/up9inc/mizu/tap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const tlsLinkRetainmentTime = time.Minute * 15
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
authStatus *models.AuthStatus
|
authStatus *models.AuthStatus
|
||||||
RecentTLSLinks = cache.New(tlsLinkRetainmentTime, tlsLinkRetainmentTime)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAuthStatus() (*models.AuthStatus, error) {
|
func GetAuthStatus() (*models.AuthStatus, error) {
|
||||||
@@ -51,16 +45,3 @@ func GetAuthStatus() (*models.AuthStatus, error) {
|
|||||||
|
|
||||||
return authStatus, nil
|
return authStatus, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllRecentTLSAddresses() []string {
|
|
||||||
recentTLSLinks := make([]string, 0)
|
|
||||||
|
|
||||||
for _, outboundLinkItem := range RecentTLSLinks.Items() {
|
|
||||||
outboundLink, castOk := outboundLinkItem.Object.(*tap.OutboundLink)
|
|
||||||
if castOk {
|
|
||||||
recentTLSLinks = append(recentTLSLinks, outboundLink.DstIP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return recentTLSLinks
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -21,7 +21,5 @@ func StatusRoutes(ginApp *gin.Engine) {
|
|||||||
|
|
||||||
routeGroup.GET("/general", controllers.GetGeneralStats) // get general stats about entries in DB
|
routeGroup.GET("/general", controllers.GetGeneralStats) // get general stats about entries in DB
|
||||||
|
|
||||||
routeGroup.GET("/recentTLSLinks", controllers.GetRecentTLSLinks)
|
|
||||||
|
|
||||||
routeGroup.GET("/resolving", controllers.GetCurrentResolvingInformation)
|
routeGroup.GET("/resolving", controllers.GetCurrentResolvingInformation)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,11 +211,15 @@ func syncEntriesImpl(token string, model string, envPrefix string, uploadInterva
|
|||||||
|
|
||||||
logger.Log.Infof("Getting entries from the database")
|
logger.Log.Infof("Getting entries from the database")
|
||||||
|
|
||||||
|
BasenineReconnect:
|
||||||
var connection *basenine.Connection
|
var connection *basenine.Connection
|
||||||
var err error
|
var err error
|
||||||
connection, err = basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
connection, err = basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Log.Errorf("Can't establish a new connection to Basenine server: %v", err)
|
||||||
|
connection.Close()
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
goto BasenineReconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make(chan []byte)
|
data := make(chan []byte)
|
||||||
@@ -324,7 +328,10 @@ func syncEntriesImpl(token string, model string, envPrefix string, uploadInterva
|
|||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
||||||
if err = connection.Query(query, data, meta); err != nil {
|
if err = connection.Query(query, data, meta); err != nil {
|
||||||
logger.Log.Panicf("Query mode call failed: %v", err)
|
logger.Log.Errorf("Query mode call failed: %v", err)
|
||||||
|
connection.Close()
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
goto BasenineReconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
20
cli/Makefile
20
cli/Makefile
@@ -36,16 +36,16 @@ build-base: ## Build mizu CLI binary (select platform via GOOS / GOARCH env vari
|
|||||||
(cd bin && shasum -a 256 mizu_${SUFFIX} > mizu_${SUFFIX}.sha256)
|
(cd bin && shasum -a 256 mizu_${SUFFIX} > mizu_${SUFFIX}.sha256)
|
||||||
|
|
||||||
build-all: ## Build for all supported platforms.
|
build-all: ## Build for all supported platforms.
|
||||||
@echo "Compiling for every OS and Platform"
|
echo "Compiling for every OS and Platform" && \
|
||||||
@mkdir -p bin && sed s/_VER_/$(VER)/g README.md.TEMPLATE > bin/README.md
|
mkdir -p bin && sed s/_VER_/$(VER)/g README.md.TEMPLATE > bin/README.md && \
|
||||||
@$(MAKE) build GOOS=linux GOARCH=amd64
|
$(MAKE) build GOOS=linux GOARCH=amd64 && \
|
||||||
@$(MAKE) build GOOS=linux GOARCH=arm64
|
$(MAKE) build GOOS=linux GOARCH=arm64 && \
|
||||||
@$(MAKE) build GOOS=darwin GOARCH=amd64
|
$(MAKE) build GOOS=darwin GOARCH=amd64 && \
|
||||||
@$(MAKE) build GOOS=darwin GOARCH=arm64
|
$(MAKE) build GOOS=darwin GOARCH=arm64 && \
|
||||||
@$(MAKE) build GOOS=windows GOARCH=amd64
|
$(MAKE) build GOOS=windows GOARCH=amd64 && \
|
||||||
@mv ./bin/mizu_windows_amd64 ./bin/mizu.exe
|
mv ./bin/mizu_windows_amd64 ./bin/mizu.exe && \
|
||||||
@echo "---------"
|
echo "---------" && \
|
||||||
@find ./bin -ls
|
find ./bin -ls
|
||||||
|
|
||||||
clean: ## Clean all build artifacts.
|
clean: ## Clean all build artifacts.
|
||||||
go clean
|
go clean
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/up9inc/mizu/cli/uiUtils"
|
"github.com/up9inc/mizu/cli/uiUtils"
|
||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/server/lib"
|
|
||||||
"github.com/up9inc/mizu/shared/logger"
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
"github.com/up9inc/mizu/shared/units"
|
"github.com/up9inc/mizu/shared/units"
|
||||||
)
|
)
|
||||||
@@ -79,10 +78,6 @@ func (config *TapConfig) GetInsertionFilter() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := basenine.Parse(insertionFilter)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Warningf(uiUtils.Warning, fmt.Sprintf("Insertion filter syntax error: %v", err))
|
|
||||||
}
|
|
||||||
return insertionFilter
|
return insertionFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ require (
|
|||||||
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/basenine/server/lib v0.0.0-20220413023528-c741e4aa1cf2
|
|
||||||
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
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
@@ -33,11 +32,8 @@ require (
|
|||||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/alecthomas/participle/v2 v2.0.0-alpha7 // indirect
|
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.5.5 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
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
|
||||||
@@ -72,7 +68,6 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
github.com/ohler55/ojg v1.14.0 // indirect
|
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|||||||
12
cli/go.sum
12
cli/go.sum
@@ -83,10 +83,6 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
|
|||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c=
|
|
||||||
github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA=
|
|
||||||
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 h1:GDQdwm/gAcJcLAKQQZGOJ4knlw+7rfEQQcmwTbt4p5E=
|
|
||||||
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
@@ -120,8 +116,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
|
|
||||||
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
@@ -155,8 +149,6 @@ github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMS
|
|||||||
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
|
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
|
||||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
@@ -487,8 +479,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/ohler55/ojg v1.14.0 h1:DyHomsCwofNswmKj7BLMdx51xnKbXxgIo1rVWCaBcNk=
|
|
||||||
github.com/ohler55/ojg v1.14.0/go.mod h1:3+GH+0PggMKocQtbZCrFifal3yRpHiBT4QUkxFJI6e8=
|
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@@ -600,8 +590,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/up9inc/basenine/server/lib v0.0.0-20220413023528-c741e4aa1cf2 h1:rgm5a2ALbYKbItaSXx25K8vavZpeF0HN1Pk0qmOqy50=
|
|
||||||
github.com/up9inc/basenine/server/lib v0.0.0-20220413023528-c741e4aa1cf2/go.mod h1:v0hIh31iwDGbkkdeSSppdMNm1oIigfCA2mG2XajKnf8=
|
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
package shared
|
package shared
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS"
|
MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS"
|
||||||
SyncEntriesConfigEnvVar = "SYNC_ENTRIES_CONFIG"
|
SyncEntriesConfigEnvVar = "SYNC_ENTRIES_CONFIG"
|
||||||
HostModeEnvVar = "HOST_MODE"
|
HostModeEnvVar = "HOST_MODE"
|
||||||
NodeNameEnvVar = "NODE_NAME"
|
NodeNameEnvVar = "NODE_NAME"
|
||||||
ConfigDirPath = "/app/config/"
|
ConfigDirPath = "/app/config/"
|
||||||
DataDirPath = "/app/data/"
|
DataDirPath = "/app/data/"
|
||||||
ValidationRulesFileName = "validation-rules.yaml"
|
ValidationRulesFileName = "validation-rules.yaml"
|
||||||
ContractFileName = "contract-oas.yaml"
|
ContractFileName = "contract-oas.yaml"
|
||||||
ConfigFileName = "mizu-config.json"
|
ConfigFileName = "mizu-config.json"
|
||||||
GoGCEnvVar = "GOGC"
|
GoGCEnvVar = "GOGC"
|
||||||
DefaultApiServerPort = 8899
|
DefaultApiServerPort = 8899
|
||||||
LogLevelEnvVar = "LOG_LEVEL"
|
LogLevelEnvVar = "LOG_LEVEL"
|
||||||
MizuAgentImageRepo = "docker.io/up9inc/mizu"
|
MizuAgentImageRepo = "docker.io/up9inc/mizu"
|
||||||
BasenineHost = "127.0.0.1"
|
BasenineHost = "127.0.0.1"
|
||||||
BaseninePort = "9099"
|
BaseninePort = "9099"
|
||||||
|
BasenineReconnectInterval = 3
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -805,14 +805,20 @@ func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespac
|
|||||||
agentResources := applyconfcore.ResourceRequirements().WithRequests(agentResourceRequests).WithLimits(agentResourceLimits)
|
agentResources := applyconfcore.ResourceRequirements().WithRequests(agentResourceRequests).WithLimits(agentResourceLimits)
|
||||||
agentContainer.WithResources(agentResources)
|
agentContainer.WithResources(agentResources)
|
||||||
|
|
||||||
nodeSelectorRequirement := applyconfcore.NodeSelectorRequirement()
|
matchFields := make([]*applyconfcore.NodeSelectorTermApplyConfiguration, 0)
|
||||||
nodeSelectorRequirement.WithKey("kubernetes.io/hostname")
|
for _, nodeName := range nodeNames {
|
||||||
nodeSelectorRequirement.WithOperator(core.NodeSelectorOpIn)
|
nodeSelectorRequirement := applyconfcore.NodeSelectorRequirement()
|
||||||
nodeSelectorRequirement.WithValues(nodeNames...)
|
nodeSelectorRequirement.WithKey("metadata.name")
|
||||||
nodeSelectorTerm := applyconfcore.NodeSelectorTerm()
|
nodeSelectorRequirement.WithOperator(core.NodeSelectorOpIn)
|
||||||
nodeSelectorTerm.WithMatchExpressions(nodeSelectorRequirement)
|
nodeSelectorRequirement.WithValues(nodeName)
|
||||||
|
|
||||||
|
nodeSelectorTerm := applyconfcore.NodeSelectorTerm()
|
||||||
|
nodeSelectorTerm.WithMatchFields(nodeSelectorRequirement)
|
||||||
|
matchFields = append(matchFields, nodeSelectorTerm)
|
||||||
|
}
|
||||||
|
|
||||||
nodeSelector := applyconfcore.NodeSelector()
|
nodeSelector := applyconfcore.NodeSelector()
|
||||||
nodeSelector.WithNodeSelectorTerms(nodeSelectorTerm)
|
nodeSelector.WithNodeSelectorTerms(matchFields...)
|
||||||
nodeAffinity := applyconfcore.NodeAffinity()
|
nodeAffinity := applyconfcore.NodeAffinity()
|
||||||
nodeAffinity.WithRequiredDuringSchedulingIgnoredDuringExecution(nodeSelector)
|
nodeAffinity.WithRequiredDuringSchedulingIgnoredDuringExecution(nodeSelector)
|
||||||
affinity := applyconfcore.Affinity()
|
affinity := applyconfcore.Affinity()
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ func GetNodeHostToTappedPodsMap(tappedPods []core.Pod) shared.NodeToPodsMap {
|
|||||||
func getMinimizedPod(fullPod core.Pod) core.Pod {
|
func getMinimizedPod(fullPod core.Pod) core.Pod {
|
||||||
return core.Pod{
|
return core.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: fullPod.Name,
|
Name: fullPod.Name,
|
||||||
|
Namespace: fullPod.Namespace,
|
||||||
},
|
},
|
||||||
Status: core.PodStatus{
|
Status: core.PodStatus{
|
||||||
PodIP: fullPod.Status.PodIP,
|
PodIP: fullPod.Status.PodIP,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const (
|
|||||||
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
||||||
WebSocketMessageTypeUpdateTappedPods WebSocketMessageType = "tappedPods"
|
WebSocketMessageTypeUpdateTappedPods WebSocketMessageType = "tappedPods"
|
||||||
WebSocketMessageTypeAnalyzeStatus WebSocketMessageType = "analyzeStatus"
|
WebSocketMessageTypeAnalyzeStatus WebSocketMessageType = "analyzeStatus"
|
||||||
WebsocketMessageTypeOutboundLink WebSocketMessageType = "outboundLink"
|
|
||||||
WebSocketMessageTypeToast WebSocketMessageType = "toast"
|
WebSocketMessageTypeToast WebSocketMessageType = "toast"
|
||||||
WebSocketMessageTypeQueryMetadata WebSocketMessageType = "queryMetadata"
|
WebSocketMessageTypeQueryMetadata WebSocketMessageType = "queryMetadata"
|
||||||
WebSocketMessageTypeStartTime WebSocketMessageType = "startTime"
|
WebSocketMessageTypeStartTime WebSocketMessageType = "startTime"
|
||||||
@@ -92,7 +91,7 @@ func (np NodeToPodsMap) Summary() map[string][]string {
|
|||||||
summary := make(map[string][]string)
|
summary := make(map[string][]string)
|
||||||
for node, pods := range np {
|
for node, pods := range np {
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
summary[node] = append(summary[node], pod.Namespace + "/" + pod.Name)
|
summary[node] = append(summary[node], pod.Namespace+"/"+pod.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const mizuTestEnvVar = "MIZU_TEST"
|
const mizuTestEnvVar = "MIZU_TEST"
|
||||||
|
const UNKNOWN_NAMESPACE = ""
|
||||||
|
|
||||||
var UnknownIp net.IP = net.IP{0, 0, 0, 0}
|
var UnknownIp net.IP = net.IP{0, 0, 0, 0}
|
||||||
var UnknownPort uint16 = 0
|
var UnknownPort uint16 = 0
|
||||||
@@ -92,14 +93,15 @@ type RequestResponsePair struct {
|
|||||||
Response GenericMessage `json:"response"`
|
Response GenericMessage `json:"response"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Protocol` is modified in the later stages of data propagation. Therefore it's not a pointer.
|
|
||||||
type OutputChannelItem struct {
|
type OutputChannelItem struct {
|
||||||
|
// `Protocol` is modified in later stages of data propagation. Therefore, it's not a pointer.
|
||||||
Protocol Protocol
|
Protocol Protocol
|
||||||
Capture Capture
|
Capture Capture
|
||||||
Timestamp int64
|
Timestamp int64
|
||||||
ConnectionInfo *ConnectionInfo
|
ConnectionInfo *ConnectionInfo
|
||||||
Pair *RequestResponsePair
|
Pair *RequestResponsePair
|
||||||
Summary *BaseEntry
|
Summary *BaseEntry
|
||||||
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
type SuperTimer struct {
|
type SuperTimer struct {
|
||||||
|
|||||||
@@ -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/expect7/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/expect8/amqp/\* expect
|
||||||
|
|||||||
@@ -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/expect7/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/expect8/http/\* expect
|
||||||
|
|||||||
@@ -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/expect7/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/expect8/kafka/\* expect
|
||||||
|
|||||||
@@ -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/expect7/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/expect8/redis/\* expect
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module github.com/up9inc/mizu/tap
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4
|
|
||||||
github.com/cilium/ebpf v0.8.0
|
github.com/cilium/ebpf v0.8.0
|
||||||
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
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4 h1:NJOOlc6ZJjix0A1rAU+nxruZtR8KboG1848yqpIUo4M=
|
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4/go.mod h1:DQPxZS994Ld1Y8uwnJT+dRL04XPD0cElP/pHH/zEBHM=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
|||||||
@@ -29,21 +29,6 @@ func getLocalhostIPs() ([]string, error) {
|
|||||||
return myIPs, nil
|
return myIPs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//lint:ignore U1000 will be used in the future
|
|
||||||
func isPrivateIP(ipStr string) bool {
|
|
||||||
ip := net.ParseIP(ipStr)
|
|
||||||
if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, block := range privateIPBlocks {
|
|
||||||
if block.Contains(ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func initPrivateIPBlocks() {
|
func initPrivateIPBlocks() {
|
||||||
for _, cidr := range []string{
|
for _, cidr := range []string{
|
||||||
"127.0.0.0/8", // IPv4 loopback
|
"127.0.0.0/8", // IPv4 loopback
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
package tap
|
|
||||||
|
|
||||||
type OutboundLinkProtocol string
|
|
||||||
|
|
||||||
const (
|
|
||||||
TLSProtocol OutboundLinkProtocol = "tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OutboundLink struct {
|
|
||||||
Src string
|
|
||||||
DstIP string
|
|
||||||
DstPort int
|
|
||||||
SuggestedResolvedName string
|
|
||||||
SuggestedProtocol OutboundLinkProtocol
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewOutboundLinkWriter() *OutboundLinkWriter {
|
|
||||||
return &OutboundLinkWriter{
|
|
||||||
OutChan: make(chan *OutboundLink),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutboundLinkWriter struct {
|
|
||||||
OutChan chan *OutboundLink
|
|
||||||
}
|
|
||||||
|
|
||||||
func (olw *OutboundLinkWriter) WriteOutboundLink(src string, DstIP string, DstPort int, SuggestedResolvedName string, SuggestedProtocol OutboundLinkProtocol) {
|
|
||||||
olw.OutChan <- &OutboundLink{
|
|
||||||
Src: src,
|
|
||||||
DstIP: DstIP,
|
|
||||||
DstPort: DstPort,
|
|
||||||
SuggestedResolvedName: SuggestedResolvedName,
|
|
||||||
SuggestedProtocol: SuggestedProtocol,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (olw *OutboundLinkWriter) Stop() {
|
|
||||||
close(olw.OutChan)
|
|
||||||
}
|
|
||||||
@@ -27,9 +27,6 @@ import (
|
|||||||
|
|
||||||
const cleanPeriod = time.Second * 10
|
const cleanPeriod = time.Second * 10
|
||||||
|
|
||||||
//lint:ignore U1000 will be used in the future
|
|
||||||
var remoteOnlyOutboundPorts = []int{80, 443}
|
|
||||||
|
|
||||||
var maxcount = flag.Int64("c", -1, "Only grab this many packets, then exit")
|
var maxcount = flag.Int64("c", -1, "Only grab this many packets, then exit")
|
||||||
var decoder = flag.String("decoder", "", "Name of the decoder to use (default: guess from capture)")
|
var decoder = flag.String("decoder", "", "Name of the decoder to use (default: guess from capture)")
|
||||||
var statsevery = flag.Int("stats", 60, "Output statistics every N seconds")
|
var statsevery = flag.Int("stats", 60, "Output statistics every N seconds")
|
||||||
@@ -58,7 +55,7 @@ var tls = flag.Bool("tls", false, "Enable TLS tapper")
|
|||||||
var memprofile = flag.String("memprofile", "", "Write memory profile")
|
var memprofile = flag.String("memprofile", "", "Write memory profile")
|
||||||
|
|
||||||
type TapOpts struct {
|
type TapOpts struct {
|
||||||
HostMode bool
|
HostMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var extensions []*api.Extension // global
|
var extensions []*api.Extension // global
|
||||||
@@ -68,24 +65,6 @@ var packetSourceManager *source.PacketSourceManager // global
|
|||||||
var mainPacketInputChan chan source.TcpPacketInfo // global
|
var mainPacketInputChan chan source.TcpPacketInfo // global
|
||||||
var tlsTapperInstance *tlstapper.TlsTapper // global
|
var tlsTapperInstance *tlstapper.TlsTapper // global
|
||||||
|
|
||||||
func inArrayInt(arr []int, valueToCheck int) bool {
|
|
||||||
for _, value := range arr {
|
|
||||||
if value == valueToCheck {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func inArrayString(arr []string, valueToCheck string) bool {
|
|
||||||
for _, value := range arr {
|
|
||||||
if value == valueToCheck {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem, extensionsRef []*api.Extension, options *api.TrafficFilteringOptions) {
|
func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem, extensionsRef []*api.Extension, options *api.TrafficFilteringOptions) {
|
||||||
extensions = extensionsRef
|
extensions = extensionsRef
|
||||||
filteringOptions = options
|
filteringOptions = options
|
||||||
|
|||||||
@@ -7,13 +7,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bradleyfalzon/tlsx"
|
|
||||||
"github.com/up9inc/mizu/shared/logger"
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const checkTLSPacketAmount = 100
|
|
||||||
|
|
||||||
type tcpReaderDataMsg struct {
|
type tcpReaderDataMsg struct {
|
||||||
bytes []byte
|
bytes []byte
|
||||||
timestamp time.Time
|
timestamp time.Time
|
||||||
@@ -33,22 +30,21 @@ type ConnectionInfo struct {
|
|||||||
* Implements io.Reader interface (Read)
|
* Implements io.Reader interface (Read)
|
||||||
*/
|
*/
|
||||||
type tcpReader struct {
|
type tcpReader struct {
|
||||||
ident string
|
ident string
|
||||||
tcpID *api.TcpID
|
tcpID *api.TcpID
|
||||||
isClosed bool
|
isClosed bool
|
||||||
isClient bool
|
isClient bool
|
||||||
isOutgoing bool
|
isOutgoing bool
|
||||||
msgQueue chan tcpReaderDataMsg // Channel of captured reassembled tcp payload
|
msgQueue chan tcpReaderDataMsg // Channel of captured reassembled tcp payload
|
||||||
data []byte
|
data []byte
|
||||||
progress *api.ReadProgress
|
progress *api.ReadProgress
|
||||||
superTimer *api.SuperTimer
|
superTimer *api.SuperTimer
|
||||||
parent *tcpStream
|
parent *tcpStream
|
||||||
packetsSeen uint
|
packetsSeen uint
|
||||||
outboundLinkWriter *OutboundLinkWriter
|
extension *api.Extension
|
||||||
extension *api.Extension
|
emitter api.Emitter
|
||||||
emitter api.Emitter
|
counterPair *api.CounterPair
|
||||||
counterPair *api.CounterPair
|
reqResMatcher api.RequestResponseMatcher
|
||||||
reqResMatcher api.RequestResponseMatcher
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,16 +60,6 @@ func (h *tcpReader) Read(p []byte) (int, error) {
|
|||||||
if len(h.data) > 0 {
|
if len(h.data) > 0 {
|
||||||
h.packetsSeen += 1
|
h.packetsSeen += 1
|
||||||
}
|
}
|
||||||
if h.packetsSeen < checkTLSPacketAmount && len(msg.bytes) > 5 { // packets with less than 5 bytes cause tlsx to panic
|
|
||||||
clientHello := tlsx.ClientHello{}
|
|
||||||
err := clientHello.Unmarshall(msg.bytes)
|
|
||||||
if err == nil {
|
|
||||||
logger.Log.Debugf("Detected TLS client hello with SNI %s", clientHello.SNI)
|
|
||||||
// TODO: Throws `panic: runtime error: invalid memory address or nil pointer dereference` error.
|
|
||||||
// numericPort, _ := strconv.Atoi(h.tcpID.DstPort)
|
|
||||||
// h.outboundLinkWriter.WriteOutboundLink(h.tcpID.SrcIP, h.tcpID.DstIP, numericPort, clientHello.SNI, TLSProtocol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !ok || len(h.data) == 0 {
|
if !ok || len(h.data) == 0 {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
|
|||||||
@@ -20,12 +20,11 @@ import (
|
|||||||
* Generates a new tcp stream for each new tcp connection. Closes the stream when the connection closes.
|
* Generates a new tcp stream for each new tcp connection. Closes the stream when the connection closes.
|
||||||
*/
|
*/
|
||||||
type tcpStreamFactory struct {
|
type tcpStreamFactory struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
outboundLinkWriter *OutboundLinkWriter
|
Emitter api.Emitter
|
||||||
Emitter api.Emitter
|
streamsMap *tcpStreamMap
|
||||||
streamsMap *tcpStreamMap
|
ownIps []string
|
||||||
ownIps []string
|
opts *TapOpts
|
||||||
opts *TapOpts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type tcpStreamWrapper struct {
|
type tcpStreamWrapper struct {
|
||||||
@@ -63,9 +62,6 @@ func (factory *tcpStreamFactory) New(net, transport gopacket.Flow, tcp *layers.T
|
|||||||
srcPort := transport.Src().String()
|
srcPort := transport.Src().String()
|
||||||
dstPort := transport.Dst().String()
|
dstPort := transport.Dst().String()
|
||||||
|
|
||||||
// if factory.shouldNotifyOnOutboundLink(dstIp, dstPort) {
|
|
||||||
// factory.outboundLinkWriter.WriteOutboundLink(net.Src().String(), dstIp, dstPort, "", "")
|
|
||||||
// }
|
|
||||||
props := factory.getStreamProps(srcIp, srcPort, dstIp, dstPort)
|
props := factory.getStreamProps(srcIp, srcPort, dstIp, dstPort)
|
||||||
isTapTarget := props.isTapTarget
|
isTapTarget := props.isTapTarget
|
||||||
stream := &tcpStream{
|
stream := &tcpStream{
|
||||||
@@ -99,14 +95,13 @@ func (factory *tcpStreamFactory) New(net, transport gopacket.Flow, tcp *layers.T
|
|||||||
SrcPort: srcPort,
|
SrcPort: srcPort,
|
||||||
DstPort: dstPort,
|
DstPort: dstPort,
|
||||||
},
|
},
|
||||||
parent: stream,
|
parent: stream,
|
||||||
isClient: true,
|
isClient: true,
|
||||||
isOutgoing: props.isOutgoing,
|
isOutgoing: props.isOutgoing,
|
||||||
outboundLinkWriter: factory.outboundLinkWriter,
|
extension: extension,
|
||||||
extension: extension,
|
emitter: factory.Emitter,
|
||||||
emitter: factory.Emitter,
|
counterPair: counterPair,
|
||||||
counterPair: counterPair,
|
reqResMatcher: reqResMatcher,
|
||||||
reqResMatcher: reqResMatcher,
|
|
||||||
})
|
})
|
||||||
stream.servers = append(stream.servers, tcpReader{
|
stream.servers = append(stream.servers, tcpReader{
|
||||||
msgQueue: make(chan tcpReaderDataMsg),
|
msgQueue: make(chan tcpReaderDataMsg),
|
||||||
@@ -119,14 +114,13 @@ func (factory *tcpStreamFactory) New(net, transport gopacket.Flow, tcp *layers.T
|
|||||||
SrcPort: transport.Dst().String(),
|
SrcPort: transport.Dst().String(),
|
||||||
DstPort: transport.Src().String(),
|
DstPort: transport.Src().String(),
|
||||||
},
|
},
|
||||||
parent: stream,
|
parent: stream,
|
||||||
isClient: false,
|
isClient: false,
|
||||||
isOutgoing: props.isOutgoing,
|
isOutgoing: props.isOutgoing,
|
||||||
outboundLinkWriter: factory.outboundLinkWriter,
|
extension: extension,
|
||||||
extension: extension,
|
emitter: factory.Emitter,
|
||||||
emitter: factory.Emitter,
|
counterPair: counterPair,
|
||||||
counterPair: counterPair,
|
reqResMatcher: reqResMatcher,
|
||||||
reqResMatcher: reqResMatcher,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
factory.streamsMap.Store(stream.id, &tcpStreamWrapper{
|
factory.streamsMap.Store(stream.id, &tcpStreamWrapper{
|
||||||
@@ -174,15 +168,6 @@ func (factory *tcpStreamFactory) getStreamProps(srcIP string, srcPort string, ds
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//lint:ignore U1000 will be used in the future
|
|
||||||
func (factory *tcpStreamFactory) shouldNotifyOnOutboundLink(dstIP string, dstPort int) bool {
|
|
||||||
if inArrayInt(remoteOnlyOutboundPorts, dstPort) {
|
|
||||||
isDirectedHere := inArrayString(factory.ownIps, dstIP)
|
|
||||||
return !isDirectedHere && !isPrivateIP(dstIP)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPacketOrigin(ac reassembly.AssemblerContext) api.Capture {
|
func getPacketOrigin(ac reassembly.AssemblerContext) api.Capture {
|
||||||
c, ok := ac.(*context)
|
c, ok := ac.(*context)
|
||||||
|
|
||||||
|
|||||||
13
tap/tlstapper/tls_emitter.go
Normal file
13
tap/tlstapper/tls_emitter.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import "github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
|
type tlsEmitter struct {
|
||||||
|
delegate api.Emitter
|
||||||
|
namespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *tlsEmitter) Emit(item *api.OutputChannelItem) {
|
||||||
|
item.Namespace = e.namespace
|
||||||
|
e.delegate.Emit(item)
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -19,13 +21,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tlsPoller struct {
|
type tlsPoller struct {
|
||||||
tls *TlsTapper
|
tls *TlsTapper
|
||||||
readers map[string]*tlsReader
|
readers map[string]*tlsReader
|
||||||
closedReaders chan string
|
closedReaders chan string
|
||||||
reqResMatcher api.RequestResponseMatcher
|
reqResMatcher api.RequestResponseMatcher
|
||||||
chunksReader *perf.Reader
|
chunksReader *perf.Reader
|
||||||
extension *api.Extension
|
extension *api.Extension
|
||||||
procfs string
|
procfs string
|
||||||
|
pidToNamespace sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTlsPoller(tls *TlsTapper, extension *api.Extension, procfs string) *tlsPoller {
|
func newTlsPoller(tls *TlsTapper, extension *api.Extension, procfs string) *tlsPoller {
|
||||||
@@ -151,16 +154,25 @@ func (p *tlsPoller) startNewTlsReader(chunk *tlsChunk, ip net.IP, port uint16, k
|
|||||||
|
|
||||||
tcpid := p.buildTcpId(chunk, ip, port)
|
tcpid := p.buildTcpId(chunk, ip, port)
|
||||||
|
|
||||||
go dissect(extension, reader, chunk.isRequest(), &tcpid, emitter, options, p.reqResMatcher)
|
tlsEmitter := &tlsEmitter{
|
||||||
|
delegate: emitter,
|
||||||
|
namespace: p.getNamespace(chunk.Pid),
|
||||||
|
}
|
||||||
|
|
||||||
|
go dissect(extension, reader, chunk.isRequest(), &tcpid, tlsEmitter, options, p.reqResMatcher)
|
||||||
return reader
|
return reader
|
||||||
}
|
}
|
||||||
|
|
||||||
func dissect(extension *api.Extension, reader *tlsReader, isRequest bool, tcpid *api.TcpID,
|
func dissect(extension *api.Extension, reader *tlsReader, isRequest bool, tcpid *api.TcpID,
|
||||||
emitter api.Emitter, options *api.TrafficFilteringOptions, reqResMatcher api.RequestResponseMatcher) {
|
tlsEmitter *tlsEmitter, options *api.TrafficFilteringOptions, reqResMatcher api.RequestResponseMatcher) {
|
||||||
b := bufio.NewReader(reader)
|
b := bufio.NewReader(reader)
|
||||||
|
|
||||||
|
timer := api.SuperTimer{
|
||||||
|
CaptureTime: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
err := extension.Dissector.Dissect(b, reader.progress, api.Ebpf, isRequest, tcpid, &api.CounterPair{},
|
err := extension.Dissector.Dissect(b, reader.progress, api.Ebpf, isRequest, tcpid, &api.CounterPair{},
|
||||||
&api.SuperTimer{}, &api.SuperIdentifier{}, emitter, options, reqResMatcher)
|
&timer, &api.SuperIdentifier{}, tlsEmitter, options, reqResMatcher)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Warningf("Error dissecting TLS %v - %v", tcpid, err)
|
logger.Log.Warningf("Error dissecting TLS %v - %v", tcpid, err)
|
||||||
@@ -205,6 +217,33 @@ func (p *tlsPoller) buildTcpId(chunk *tlsChunk, ip net.IP, port uint16) api.TcpI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) addPid(pid uint32, namespace string) {
|
||||||
|
p.pidToNamespace.Store(pid, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) getNamespace(pid uint32) string {
|
||||||
|
namespaceIfc, ok := p.pidToNamespace.Load(pid)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return api.UNKNOWN_NAMESPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace, ok := namespaceIfc.(string)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return api.UNKNOWN_NAMESPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) clearPids() {
|
||||||
|
p.pidToNamespace.Range(func(key, v interface{}) bool {
|
||||||
|
p.pidToNamespace.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (p *tlsPoller) logTls(chunk *tlsChunk, ip net.IP, port uint16) {
|
func (p *tlsPoller) logTls(chunk *tlsChunk, ip net.IP, port uint16) {
|
||||||
var flagsStr string
|
var flagsStr string
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ func UpdateTapTargets(tls *TlsTapper, pods *[]v1.Pod, procfs string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tls.ClearPids()
|
tls.ClearPids()
|
||||||
|
|
||||||
for _, pid := range containerPids {
|
for pid, pod := range containerPids {
|
||||||
if err := tls.AddPid(procfs, pid); err != nil {
|
if err := tls.AddPid(procfs, pid, pod.Namespace); err != nil {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,8 +36,8 @@ func UpdateTapTargets(tls *TlsTapper, pods *[]v1.Pod, procfs string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findContainerPids(procfs string, containerIds map[string]bool) ([]uint32, error) {
|
func findContainerPids(procfs string, containerIds map[string]v1.Pod) (map[uint32]v1.Pod, error) {
|
||||||
result := make([]uint32, 0)
|
result := make(map[uint32]v1.Pod)
|
||||||
|
|
||||||
pids, err := ioutil.ReadDir(procfs)
|
pids, err := ioutil.ReadDir(procfs)
|
||||||
|
|
||||||
@@ -63,7 +63,9 @@ func findContainerPids(procfs string, containerIds map[string]bool) ([]uint32, e
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := containerIds[cgroup]; !ok {
|
pod, ok := containerIds[cgroup]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,14 +75,14 @@ func findContainerPids(procfs string, containerIds map[string]bool) ([]uint32, e
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result = append(result, uint32(pidNumber))
|
result[uint32(pidNumber)] = pod
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildContainerIdsMap(pods *[]v1.Pod) map[string]bool {
|
func buildContainerIdsMap(pods *[]v1.Pod) map[string]v1.Pod {
|
||||||
result := make(map[string]bool)
|
result := make(map[string]v1.Pod)
|
||||||
|
|
||||||
for _, pod := range *pods {
|
for _, pod := range *pods {
|
||||||
for _, container := range pod.Status.ContainerStatuses {
|
for _, container := range pod.Status.ContainerStatuses {
|
||||||
@@ -91,7 +93,7 @@ func buildContainerIdsMap(pods *[]v1.Pod) map[string]bool {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result[url.Host] = true
|
result[url.Host] = pod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,14 +143,14 @@ func extractCgroup(lines []string) string {
|
|||||||
// /kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3beae8e0_164d_4689_a087_efd902d8c2ab.slice/docker-<ID>.scope
|
// /kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3beae8e0_164d_4689_a087_efd902d8c2ab.slice/docker-<ID>.scope
|
||||||
// /kubepods/besteffort/pod7709c1d5-447c-428f-bed9-8ddec35c93f4/<ID>
|
// /kubepods/besteffort/pod7709c1d5-447c-428f-bed9-8ddec35c93f4/<ID>
|
||||||
//
|
//
|
||||||
// This function extract the <ID> out of the cgroup path, the <ID> should match
|
// This function extract the <ID> out of the cgroup path, the <ID> should match
|
||||||
// the "Container ID:" field when running kubectl describe pod <POD>
|
// the "Container ID:" field when running kubectl describe pod <POD>
|
||||||
//
|
//
|
||||||
func normalizeCgroup(cgrouppath string) string {
|
func normalizeCgroup(cgrouppath string) string {
|
||||||
basename := strings.TrimSpace(path.Base(cgrouppath))
|
basename := strings.TrimSpace(path.Base(cgrouppath))
|
||||||
|
|
||||||
if strings.Contains(basename, "-") {
|
if strings.Contains(basename, "-") {
|
||||||
basename = basename[strings.Index(basename, "-") + 1:]
|
basename = basename[strings.Index(basename, "-")+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(basename, ".") {
|
if strings.Contains(basename, ".") {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package tlstapper
|
package tlstapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/rlimit"
|
"github.com/cilium/ebpf/rlimit"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/up9inc/mizu/shared/logger"
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const GLOABL_TAP_PID = 0
|
const GLOABL_TAP_PID = 0
|
||||||
@@ -58,10 +59,10 @@ func (t *TlsTapper) PollForLogging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) GlobalTap(sslLibrary string) error {
|
func (t *TlsTapper) GlobalTap(sslLibrary string) error {
|
||||||
return t.tapPid(GLOABL_TAP_PID, sslLibrary)
|
return t.tapPid(GLOABL_TAP_PID, sslLibrary, api.UNKNOWN_NAMESPACE)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) AddPid(procfs string, pid uint32) error {
|
func (t *TlsTapper) AddPid(procfs string, pid uint32, namespace string) error {
|
||||||
sslLibrary, err := findSsllib(procfs, pid)
|
sslLibrary, err := findSsllib(procfs, pid)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,7 +70,7 @@ func (t *TlsTapper) AddPid(procfs string, pid uint32) error {
|
|||||||
return nil // hide the error on purpose, its OK for a process to not use libssl.so
|
return nil // hide the error on purpose, its OK for a process to not use libssl.so
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.tapPid(pid, sslLibrary)
|
return t.tapPid(pid, sslLibrary, namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) RemovePid(pid uint32) error {
|
func (t *TlsTapper) RemovePid(pid uint32) error {
|
||||||
@@ -85,12 +86,13 @@ func (t *TlsTapper) RemovePid(pid uint32) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) ClearPids() {
|
func (t *TlsTapper) ClearPids() {
|
||||||
|
t.poller.clearPids()
|
||||||
t.registeredPids.Range(func(key, v interface{}) bool {
|
t.registeredPids.Range(func(key, v interface{}) bool {
|
||||||
pid := key.(uint32)
|
pid := key.(uint32)
|
||||||
if pid == GLOABL_TAP_PID {
|
if pid == GLOABL_TAP_PID {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := t.RemovePid(pid); err != nil {
|
if err := t.RemovePid(pid); err != nil {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
@@ -133,7 +135,7 @@ func setupRLimit() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) tapPid(pid uint32, sslLibrary string) error {
|
func (t *TlsTapper) tapPid(pid uint32, sslLibrary string, namespace string) error {
|
||||||
logger.Log.Infof("Tapping TLS (pid: %v) (sslLibrary: %v)", pid, sslLibrary)
|
logger.Log.Infof("Tapping TLS (pid: %v) (sslLibrary: %v)", pid, sslLibrary)
|
||||||
|
|
||||||
newSsl := sslHooks{}
|
newSsl := sslHooks{}
|
||||||
@@ -144,12 +146,14 @@ func (t *TlsTapper) tapPid(pid uint32, sslLibrary string) error {
|
|||||||
|
|
||||||
t.sslHooksStructs = append(t.sslHooksStructs, newSsl)
|
t.sslHooksStructs = append(t.sslHooksStructs, newSsl)
|
||||||
|
|
||||||
|
t.poller.addPid(pid, namespace)
|
||||||
|
|
||||||
pids := t.bpfObjects.tlsTapperMaps.PidsMap
|
pids := t.bpfObjects.tlsTapperMaps.PidsMap
|
||||||
|
|
||||||
if err := pids.Put(pid, uint32(1)); err != nil {
|
if err := pids.Put(pid, uint32(1)); err != nil {
|
||||||
return errors.Wrap(err, 0)
|
return errors.Wrap(err, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.registeredPids.Store(pid, true)
|
t.registeredPids.Store(pid, true)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -54,11 +54,6 @@ export default class Api {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecentTLSLinks = async () => {
|
|
||||||
const response = await client.get("/status/recentTLSLinks");
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
getOasServices = async () => {
|
getOasServices = async () => {
|
||||||
const response = await client.get("/oas");
|
const response = await client.get("/oas");
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -121,4 +116,4 @@ export function getWebsocketUrl(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
return websocketUrl;
|
return websocketUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"node-fetch": "^3.1.1",
|
"node-fetch": "^3.1.1",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"protobuf-decoder": "^0.1.0",
|
"protobuf-decoder": "^0.1.2",
|
||||||
"react-graph-vis": "^1.0.7",
|
"react-graph-vis": "^1.0.7",
|
||||||
"react-lowlight": "^3.0.0",
|
"react-lowlight": "^3.0.0",
|
||||||
"react-router-dom": "^6.2.1",
|
"react-router-dom": "^6.2.1",
|
||||||
|
|||||||
@@ -78,15 +78,8 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onClos
|
|||||||
const serviceMapData: ServiceMapGraph = await getServiceMapDataApi()
|
const serviceMapData: ServiceMapGraph = await getServiceMapDataApi()
|
||||||
setServiceMapApiData(serviceMapData)
|
setServiceMapApiData(serviceMapData)
|
||||||
const newGraphData: GraphData = { nodes: [], edges: [] }
|
const newGraphData: GraphData = { nodes: [], edges: [] }
|
||||||
|
newGraphData.nodes = serviceMapData.nodes.map(mapNodesDatatoGraph)
|
||||||
if (serviceMapData.nodes) {
|
newGraphData.edges = serviceMapData.edges.map(mapEdgesDatatoGraph)
|
||||||
newGraphData.nodes = serviceMapData.nodes.map(mapNodesDatatoGraph)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serviceMapData.edges) {
|
|
||||||
newGraphData.edges = serviceMapData.edges.map(mapEdgesDatatoGraph)
|
|
||||||
}
|
|
||||||
|
|
||||||
setGraphData(newGraphData)
|
setGraphData(newGraphData)
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
toast.error("An error occurred while loading Mizu Service Map, see console for mode details", { containerId: TOAST_CONTAINER_ID });
|
toast.error("An error occurred while loading Mizu Service Map, see console for mode details", { containerId: TOAST_CONTAINER_ID });
|
||||||
@@ -124,27 +117,32 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onClos
|
|||||||
.sort((a, b) => { return a.key.localeCompare(b.key) });
|
.sort((a, b) => { return a.key.localeCompare(b.key) });
|
||||||
|
|
||||||
const getServicesForFilter = useMemo(() => {
|
const getServicesForFilter = useMemo(() => {
|
||||||
|
|
||||||
const resolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => x.resolved))
|
const resolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => x.resolved))
|
||||||
const unResolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => !x.resolved))
|
const unResolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => !x.resolved))
|
||||||
return [...resolved, ...unResolved]
|
return [...resolved, ...unResolved]
|
||||||
}, [serviceMapApiData])
|
}, [serviceMapApiData])
|
||||||
|
|
||||||
const filterServiceMap = (newProtocolsFilters?: any[], newServiceFilters?: string[]) => {
|
useEffect(() => {
|
||||||
const filterProt = newProtocolsFilters || checkedProtocols
|
|
||||||
const filterService = newServiceFilters || checkedServices
|
|
||||||
setCheckedProtocols(filterProt)
|
|
||||||
setCheckedServices(filterService)
|
|
||||||
const newGraphData: GraphData = {
|
const newGraphData: GraphData = {
|
||||||
nodes: serviceMapApiData.nodes?.map(mapNodesDatatoGraph).filter(node => filterService.includes(node.label)),
|
nodes: serviceMapApiData.nodes?.map(mapNodesDatatoGraph).filter(node => checkedServices.includes(node.label)),
|
||||||
edges: serviceMapApiData.edges?.filter(edge => filterProt.includes(edge.protocol.abbr)).map(mapEdgesDatatoGraph)
|
edges: serviceMapApiData.edges?.filter(edge => checkedProtocols.includes(edge.protocol.abbr)).map(mapEdgesDatatoGraph)
|
||||||
}
|
}
|
||||||
setGraphData(newGraphData);
|
setGraphData(newGraphData);
|
||||||
|
}, [checkedServices, checkedProtocols, serviceMapApiData])
|
||||||
|
|
||||||
|
const onProtocolsChange = (newProtocolsFiltersnewProt) => {
|
||||||
|
const filterProt = newProtocolsFiltersnewProt || checkedProtocols
|
||||||
|
setCheckedProtocols(filterProt)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onServiceChanges = (newServiceFilters) => {
|
||||||
|
const filterService = newServiceFilters || checkedServices
|
||||||
|
setCheckedServices([...filterService])
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (checkedServices.length > 0) return // only after refresh
|
if (checkedServices.length == 0)
|
||||||
filterServiceMap(checkedProtocols, getServicesForFilter.map(x => x.key).filter(serviceName => !Utils.isIpAddress(serviceName)))
|
setCheckedServices(getServicesForFilter.map(x => x.key).filter(serviceName => !Utils.isIpAddress(serviceName)))
|
||||||
}, [getServicesForFilter])
|
}, [getServicesForFilter])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -176,18 +174,18 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onClos
|
|||||||
<Box sx={modalStyle}>
|
<Box sx={modalStyle}>
|
||||||
<div className={styles.modalContainer}>
|
<div className={styles.modalContainer}>
|
||||||
<div className={styles.filterSection}>
|
<div className={styles.filterSection}>
|
||||||
<Resizeable minWidth={170}>
|
<Resizeable minWidth={170} maxWidth={320}>
|
||||||
<div className={styles.filterWrapper}>
|
<div className={styles.filterWrapper}>
|
||||||
<div className={styles.protocolsFilterList}>
|
<div className={styles.protocolsFilterList}>
|
||||||
<SelectList items={protocols} checkBoxWidth="5%" tableName={"Protocols"} multiSelect={true}
|
<SelectList items={protocols} checkBoxWidth="5%" tableName={"Protocols"} multiSelect={true}
|
||||||
checkedValues={checkedProtocols} setCheckedValues={filterServiceMap} tableClassName={styles.filters} />
|
checkedValues={checkedProtocols} setCheckedValues={onProtocolsChange} tableClassName={styles.filters} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.separtorLine}></div>
|
<div className={styles.separtorLine}></div>
|
||||||
<div className={styles.servicesFilter}>
|
<div className={styles.servicesFilter}>
|
||||||
<input className={commonClasses.textField + ` ${styles.servicesFilterSearch}`} placeholder="search service" value={servicesSearchVal} onChange={(event) => setServicesSearchVal(event.target.value)} />
|
<input className={commonClasses.textField + ` ${styles.servicesFilterSearch}`} placeholder="search service" value={servicesSearchVal} onChange={(event) => setServicesSearchVal(event.target.value)} />
|
||||||
<div className={styles.servicesFilterList}>
|
<div className={styles.servicesFilterList}>
|
||||||
<SelectList items={getServicesForFilter} tableName={"Services"} tableClassName={styles.filters} multiSelect={true} searchValue={servicesSearchVal}
|
<SelectList items={getServicesForFilter} tableName={"Services"} tableClassName={styles.filters} multiSelect={true} searchValue={servicesSearchVal}
|
||||||
checkBoxWidth="5%" checkedValues={checkedServices} setCheckedValues={(newServicesForFilter) => filterServiceMap(null, newServicesForFilter)} />
|
checkBoxWidth="5%" checkedValues={checkedServices} setCheckedValues={onServiceChanges} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ const ServiceMapOptions = {
|
|||||||
color: '#343434',
|
color: '#343434',
|
||||||
size: 12, // px
|
size: 12, // px
|
||||||
face: 'arial',
|
face: 'arial',
|
||||||
background: 'none',
|
background: 'rgba(255,255,255,0.7)',
|
||||||
strokeWidth: 2, // px
|
strokeWidth: 2, // px
|
||||||
strokeColor: '#ffffff',
|
strokeColor: '#ffffff',
|
||||||
align: 'horizontal',
|
align: 'horizontal',
|
||||||
multi: false,
|
multi: false
|
||||||
},
|
},
|
||||||
labelHighlightBold: true,
|
labelHighlightBold: true,
|
||||||
selectionWidth: 1,
|
selectionWidth: 1,
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
.httpsDomains
|
|
||||||
display: none
|
|
||||||
margin: 0
|
|
||||||
padding: 0
|
|
||||||
list-style: none
|
|
||||||
|
|
||||||
.customWarningStyle
|
|
||||||
&:hover
|
|
||||||
overflow-y: scroll
|
|
||||||
height: 85px
|
|
||||||
.httpsDomains
|
|
||||||
display: block
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import {Snackbar} from "@material-ui/core";
|
|
||||||
import MuiAlert from "@material-ui/lab/Alert";
|
|
||||||
import React, {useEffect} from "react";
|
|
||||||
import { RecoilState, useRecoilValue } from "recoil";
|
|
||||||
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
|
|
||||||
import TrafficViewerApi from "../TrafficViewer/TrafficViewerApi";
|
|
||||||
import './TLSWarning.sass';
|
|
||||||
|
|
||||||
interface TLSWarningProps {
|
|
||||||
showTLSWarning: boolean
|
|
||||||
setShowTLSWarning: (show: boolean) => void
|
|
||||||
addressesWithTLS: Set<string>
|
|
||||||
setAddressesWithTLS: (addresses: Set<string>) => void
|
|
||||||
userDismissedTLSWarning: boolean
|
|
||||||
setUserDismissedTLSWarning: (flag: boolean) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TLSWarning: React.FC<TLSWarningProps> = ({showTLSWarning, setShowTLSWarning, addressesWithTLS, setAddressesWithTLS, userDismissedTLSWarning, setUserDismissedTLSWarning}) => {
|
|
||||||
|
|
||||||
const trafficViewerApi = useRecoilValue(TrafficViewerApiAtom as RecoilState<TrafficViewerApi>)
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const getRecentTLSLinksFunc = trafficViewerApi?.getRecentTLSLinks ? trafficViewerApi?.getRecentTLSLinks : function(){}
|
|
||||||
const recentTLSLinks = await getRecentTLSLinksFunc();
|
|
||||||
if (recentTLSLinks?.length > 0) {
|
|
||||||
setAddressesWithTLS(new Set(recentTLSLinks));
|
|
||||||
setShowTLSWarning(true);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [setShowTLSWarning, setAddressesWithTLS,trafficViewerApi]);
|
|
||||||
|
|
||||||
return (<Snackbar open={showTLSWarning && !userDismissedTLSWarning}>
|
|
||||||
<MuiAlert classes={{filledWarning: 'customWarningStyle'}} elevation={6} variant="filled"
|
|
||||||
onClose={() => setUserDismissedTLSWarning(true)} severity="warning">
|
|
||||||
Mizu is detecting TLS traffic, this type of traffic will not be displayed.
|
|
||||||
{addressesWithTLS.size > 0 &&
|
|
||||||
<ul className="httpsDomains"> {Array.from(addressesWithTLS, address => <li>{address}</li>)} </ul>}
|
|
||||||
</MuiAlert>
|
|
||||||
</Snackbar>);
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi";
|
|||||||
import TrafficViewerApi from "./TrafficViewerApi";
|
import TrafficViewerApi from "./TrafficViewerApi";
|
||||||
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {TOAST_CONTAINER_ID} from "../../configs/Consts";
|
import {MAX_ENTRIES, TOAST_CONTAINER_ID} from "../../configs/Consts";
|
||||||
import tappingStatusAtom from "../../recoil/tappingStatus";
|
import tappingStatusAtom from "../../recoil/tappingStatus";
|
||||||
import leftOffTopAtom from "../../recoil/leftOffTop";
|
import leftOffTopAtom from "../../recoil/leftOffTop";
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ export const EntriesList: React.FC<EntriesListProps> = ({
|
|||||||
setLeftOffTop(data.meta.leftOff);
|
setLeftOffTop(data.meta.leftOff);
|
||||||
|
|
||||||
let scrollTo: boolean;
|
let scrollTo: boolean;
|
||||||
if (data.meta.leftOff === 0) {
|
if (data.meta.noMoreData) {
|
||||||
setNoMoreDataTop(true);
|
setNoMoreDataTop(true);
|
||||||
scrollTo = false;
|
scrollTo = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -98,8 +98,8 @@ export const EntriesList: React.FC<EntriesListProps> = ({
|
|||||||
setIsLoadingTop(false);
|
setIsLoadingTop(false);
|
||||||
|
|
||||||
const newEntries = [...data.data.reverse(), ...entries];
|
const newEntries = [...data.data.reverse(), ...entries];
|
||||||
if(newEntries.length > 10000) {
|
if(newEntries.length > MAX_ENTRIES) {
|
||||||
newEntries.splice(10000, newEntries.length - 10000)
|
newEntries.splice(MAX_ENTRIES, newEntries.length - MAX_ENTRIES)
|
||||||
}
|
}
|
||||||
setEntries(newEntries);
|
setEntries(newEntries);
|
||||||
|
|
||||||
@@ -118,23 +118,28 @@ export const EntriesList: React.FC<EntriesListProps> = ({
|
|||||||
|
|
||||||
const scrollbarVisible = scrollableRef.current?.childWrapperRef.current.clientHeight > scrollableRef.current?.wrapperRef.current.clientHeight;
|
const scrollbarVisible = scrollableRef.current?.childWrapperRef.current.clientHeight > scrollableRef.current?.wrapperRef.current.clientHeight;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!focusedEntryId && entries.length > 0)
|
||||||
|
setFocusedEntryId(entries[0].id);
|
||||||
|
}, [focusedEntryId, entries])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const newEntries = [...entries];
|
||||||
|
if (newEntries.length > MAX_ENTRIES) {
|
||||||
|
setLeftOffTop(newEntries[0].id);
|
||||||
|
newEntries.splice(0, newEntries.length - MAX_ENTRIES)
|
||||||
|
setNoMoreDataTop(false);
|
||||||
|
setEntries(newEntries);
|
||||||
|
}
|
||||||
|
}, [entries])
|
||||||
|
|
||||||
if (ws.current) {
|
if(ws.current && !ws.current.onmessage) {
|
||||||
ws.current.onmessage = (e) => {
|
ws.current.onmessage = (e) => {
|
||||||
if (!e?.data) return;
|
if (!e?.data) return;
|
||||||
const message = JSON.parse(e.data);
|
const message = JSON.parse(e.data);
|
||||||
switch (message.messageType) {
|
switch (message.messageType) {
|
||||||
case "entry":
|
case "entry":
|
||||||
const entry = message.data;
|
setEntries(entriesState => [...entriesState, message.data]);
|
||||||
if (!focusedEntryId) setFocusedEntryId(entry.id);
|
|
||||||
const newEntries = [...entries, entry];
|
|
||||||
if (newEntries.length > 10000) {
|
|
||||||
setLeftOffTop(newEntries[0].id);
|
|
||||||
newEntries.splice(0, newEntries.length - 10000)
|
|
||||||
setNoMoreDataTop(false);
|
|
||||||
}
|
|
||||||
setEntries(newEntries);
|
|
||||||
break;
|
break;
|
||||||
case "status":
|
case "status":
|
||||||
setTappingStatus(message.tappingStatus);
|
setTappingStatus(message.tappingStatus);
|
||||||
@@ -151,9 +156,7 @@ export const EntriesList: React.FC<EntriesListProps> = ({
|
|||||||
case "queryMetadata":
|
case "queryMetadata":
|
||||||
setTruncatedTimestamp(message.data.truncatedTimestamp);
|
setTruncatedTimestamp(message.data.truncatedTimestamp);
|
||||||
setQueriedTotal(message.data.total);
|
setQueriedTotal(message.data.total);
|
||||||
if (leftOffTop === "") {
|
setLeftOffTop(leftOffState => leftOffState === "" ? message.data.leftOff : leftOffState);
|
||||||
setLeftOffTop(message.data.leftOff);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "startTime":
|
case "startTime":
|
||||||
setStartTime(message.data);
|
setStartTime(message.data);
|
||||||
@@ -206,10 +209,10 @@ export const EntriesList: React.FC<EntriesListProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
<div>Displaying <b id="entries-length">{entries?.length}</b> results out of <b
|
<div>Displaying <b id="entries-length">{entries?.length > MAX_ENTRIES ? MAX_ENTRIES : entries?.length}</b> results out of <b
|
||||||
id="total-entries">{queriedTotal}</b> total
|
id="total-entries">{queriedTotal}</b> total
|
||||||
</div>
|
</div>
|
||||||
{startTime !== 0 && <div>Started listening at <span style={{
|
{startTime !== 0 && <div>First traffic entry time <span style={{
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: 13
|
fontSize: 13
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import styles from "./EntrySections.module.sass";
|
import styles from "./EntrySections.module.sass";
|
||||||
import React, {useState} from "react";
|
import React, { useState } from "react";
|
||||||
import {SyntaxHighlighter} from "../../UI/SyntaxHighlighter/index";
|
import { SyntaxHighlighter } from "../../UI/SyntaxHighlighter/index";
|
||||||
import CollapsibleContainer from "../../UI/CollapsibleContainer";
|
import CollapsibleContainer from "../../UI/CollapsibleContainer";
|
||||||
import FancyTextDisplay from "../../UI/FancyTextDisplay";
|
import FancyTextDisplay from "../../UI/FancyTextDisplay";
|
||||||
import Queryable from "../../UI/Queryable";
|
import Queryable from "../../UI/Queryable";
|
||||||
import Checkbox from "../../UI/Checkbox";
|
import Checkbox from "../../UI/Checkbox";
|
||||||
import ProtobufDecoder from "protobuf-decoder";
|
import ProtobufDecoder from "protobuf-decoder";
|
||||||
import {default as jsonBeautify} from "json-beautify";
|
import { default as jsonBeautify } from "json-beautify";
|
||||||
import {default as xmlBeautify} from "xml-formatter";
|
import { default as xmlBeautify } from "xml-formatter";
|
||||||
|
|
||||||
interface EntryViewLineProps {
|
interface EntryViewLineProps {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -18,40 +18,40 @@ interface EntryViewLineProps {
|
|||||||
useTooltip?: boolean;
|
useTooltip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryViewLine: React.FC<EntryViewLineProps> = ({label, value, selector = "", overrideQueryValue = "", displayIconOnMouseOver = true, useTooltip = true}) => {
|
const EntryViewLine: React.FC<EntryViewLineProps> = ({ label, value, selector = "", overrideQueryValue = "", displayIconOnMouseOver = true, useTooltip = true }) => {
|
||||||
let query: string;
|
let query: string;
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
query = "";
|
query = "";
|
||||||
} else if (overrideQueryValue) {
|
} else if (overrideQueryValue) {
|
||||||
query = `${selector} == ${overrideQueryValue}`;
|
query = `${selector} == ${overrideQueryValue}`;
|
||||||
} else if (typeof(value) == "string") {
|
} else if (typeof (value) == "string") {
|
||||||
query = `${selector} == "${JSON.stringify(value).slice(1, -1)}"`;
|
query = `${selector} == "${JSON.stringify(value).slice(1, -1)}"`;
|
||||||
} else {
|
} else {
|
||||||
query = `${selector} == ${value}`;
|
query = `${selector} == ${value}`;
|
||||||
}
|
}
|
||||||
return (label && <tr className={styles.dataLine}>
|
return (label && <tr className={styles.dataLine}>
|
||||||
<td className={`${styles.dataKey}`}>
|
<td className={`${styles.dataKey}`}>
|
||||||
<Queryable
|
<Queryable
|
||||||
query={query}
|
query={query}
|
||||||
style={{float: "right", height: "18px"}}
|
style={{ float: "right", height: "18px" }}
|
||||||
iconStyle={{marginRight: "20px"}}
|
iconStyle={{ marginRight: "20px" }}
|
||||||
flipped={true}
|
flipped={true}
|
||||||
useTooltip={useTooltip}
|
useTooltip={useTooltip}
|
||||||
displayIconOnMouseOver={displayIconOnMouseOver}
|
displayIconOnMouseOver={displayIconOnMouseOver}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</Queryable>
|
</Queryable>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FancyTextDisplay
|
<FancyTextDisplay
|
||||||
className={styles.dataValue}
|
className={styles.dataValue}
|
||||||
text={value}
|
text={value}
|
||||||
applyTextEllipsis={false}
|
applyTextEllipsis={false}
|
||||||
flipped={true}
|
flipped={true}
|
||||||
displayIconOnMouseOver={true}
|
displayIconOnMouseOver={true}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>) || null;
|
</tr>) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -63,11 +63,11 @@ interface EntrySectionCollapsibleTitleProps {
|
|||||||
query?: string,
|
query?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntrySectionCollapsibleTitle: React.FC<EntrySectionCollapsibleTitleProps> = ({title, color, expanded, setExpanded, query = ""}) => {
|
const EntrySectionCollapsibleTitle: React.FC<EntrySectionCollapsibleTitleProps> = ({ title, color, expanded, setExpanded, query = "" }) => {
|
||||||
return <div className={styles.title}>
|
return <div className={styles.title}>
|
||||||
<div
|
<div
|
||||||
className={`${styles.button} ${expanded ? styles.expanded : ''}`}
|
className={`${styles.button} ${expanded ? styles.expanded : ''}`}
|
||||||
style={{backgroundColor: color}}
|
style={{ backgroundColor: color }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setExpanded(!expanded)
|
setExpanded(!expanded)
|
||||||
}}
|
}}
|
||||||
@@ -90,12 +90,12 @@ interface EntrySectionContainerProps {
|
|||||||
query?: string,
|
query?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EntrySectionContainer: React.FC<EntrySectionContainerProps> = ({title, color, children, query = ""}) => {
|
export const EntrySectionContainer: React.FC<EntrySectionContainerProps> = ({ title, color, children, query = "" }) => {
|
||||||
const [expanded, setExpanded] = useState(true);
|
const [expanded, setExpanded] = useState(true);
|
||||||
return <CollapsibleContainer
|
return <CollapsibleContainer
|
||||||
className={styles.collapsibleContainer}
|
className={styles.collapsibleContainer}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
title={<EntrySectionCollapsibleTitle title={title} color={color} expanded={expanded} setExpanded={setExpanded} query={query}/>}
|
title={<EntrySectionCollapsibleTitle title={title} color={color} expanded={expanded} setExpanded={setExpanded} query={query} />}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</CollapsibleContainer>
|
</CollapsibleContainer>
|
||||||
@@ -130,6 +130,7 @@ export const EntryBodySection: React.FC<EntryBodySectionProps> = ({
|
|||||||
|
|
||||||
const isBase64Encoding = encoding === 'base64';
|
const isBase64Encoding = encoding === 'base64';
|
||||||
const supportsPrettying = supportedFormats.some(format => contentType?.indexOf(format) > -1);
|
const supportsPrettying = supportedFormats.some(format => contentType?.indexOf(format) > -1);
|
||||||
|
const [isDecodeGrpc, setIsDecodeGrpc] = useState(true);
|
||||||
|
|
||||||
const formatTextBody = (body: any): string => {
|
const formatTextBody = (body: any): string => {
|
||||||
if (!decodeBase64) return body;
|
if (!decodeBase64) return body;
|
||||||
@@ -141,7 +142,7 @@ export const EntryBodySection: React.FC<EntryBodySectionProps> = ({
|
|||||||
if (jsonLikeFormats.some(format => contentType?.indexOf(format) > -1)) {
|
if (jsonLikeFormats.some(format => contentType?.indexOf(format) > -1)) {
|
||||||
if (!isPretty) return bodyBuf;
|
if (!isPretty) return bodyBuf;
|
||||||
return jsonBeautify(JSON.parse(bodyBuf), null, 2, 80);
|
return jsonBeautify(JSON.parse(bodyBuf), null, 2, 80);
|
||||||
} else if (xmlLikeFormats.some(format => contentType?.indexOf(format) > -1)) {
|
} else if (xmlLikeFormats.some(format => contentType?.indexOf(format) > -1)) {
|
||||||
if (!isPretty) return bodyBuf;
|
if (!isPretty) return bodyBuf;
|
||||||
return xmlBeautify(bodyBuf, {
|
return xmlBeautify(bodyBuf, {
|
||||||
indentation: ' ',
|
indentation: ' ',
|
||||||
@@ -157,49 +158,55 @@ export const EntryBodySection: React.FC<EntryBodySectionProps> = ({
|
|||||||
return jsonBeautify(protobufDecoded, null, 2, 80);
|
return jsonBeautify(protobufDecoded, null, 2, 80);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
if(isDecodeGrpc)
|
||||||
|
setIsDecodeGrpc(false);
|
||||||
|
if (!String(error).includes("More than one message in")){
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return bodyBuf;
|
return bodyBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
{content && content?.length > 0 && <EntrySectionContainer
|
{content && content?.length > 0 && <EntrySectionContainer
|
||||||
title={title}
|
title={title}
|
||||||
color={color}
|
color={color}
|
||||||
query={`${selector} == r".*"`}
|
query={`${selector} == r".*"`}
|
||||||
>
|
>
|
||||||
<div style={{display: 'flex', alignItems: 'center', alignContent: 'center', margin: "5px 0"}}>
|
<div style={{ display: 'flex', alignItems: 'center', alignContent: 'center', margin: "5px 0" }}>
|
||||||
{supportsPrettying && <div style={{paddingTop: 3}}>
|
{supportsPrettying && <div style={{ paddingTop: 3 }}>
|
||||||
<Checkbox checked={isPretty} onToggle={() => {setIsPretty(!isPretty)}}/>
|
<Checkbox checked={isPretty} onToggle={() => { setIsPretty(!isPretty) }} />
|
||||||
</div>}
|
</div>}
|
||||||
{supportsPrettying && <span style={{marginLeft: '.2rem'}}>Pretty</span>}
|
{supportsPrettying && <span style={{ marginLeft: '.2rem' }}>Pretty</span>}
|
||||||
|
|
||||||
<div style={{paddingTop: 3, paddingLeft: supportsPrettying ? 20 : 0}}>
|
<div style={{ paddingTop: 3, paddingLeft: supportsPrettying ? 20 : 0 }}>
|
||||||
<Checkbox checked={showLineNumbers} onToggle={() => {setShowLineNumbers(!showLineNumbers)}}/>
|
<Checkbox checked={showLineNumbers} onToggle={() => { setShowLineNumbers(!showLineNumbers) }} />
|
||||||
</div>
|
</div>
|
||||||
<span style={{marginLeft: '.2rem'}}>Line numbers</span>
|
<span style={{ marginLeft: '.2rem' }}>Line numbers</span>
|
||||||
|
{isBase64Encoding && <div style={{ paddingTop: 3, paddingLeft: 20 }}>
|
||||||
{isBase64Encoding && <div style={{paddingTop: 3, paddingLeft: 20}}>
|
<Checkbox checked={decodeBase64} onToggle={() => { setDecodeBase64(!decodeBase64) }} />
|
||||||
<Checkbox checked={decodeBase64} onToggle={() => {setDecodeBase64(!decodeBase64)}}/>
|
|
||||||
</div>}
|
</div>}
|
||||||
{isBase64Encoding && <span style={{marginLeft: '.2rem'}}>Decode Base64</span>}
|
{isBase64Encoding && <span style={{ marginLeft: '.2rem' }}>Decode Base64</span>}
|
||||||
</div>
|
{!isDecodeGrpc && <span style={{ fontSize: '12px', color: '#DB2156', marginLeft: '.8rem' }}>More than one message in protobuf payload is not supported</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
<SyntaxHighlighter
|
<SyntaxHighlighter
|
||||||
code={formatTextBody(content)}
|
code={formatTextBody(content)}
|
||||||
showLineNumbers={showLineNumbers}
|
showLineNumbers={showLineNumbers}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</EntrySectionContainer>}
|
</EntrySectionContainer>}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface EntrySectionProps {
|
interface EntrySectionProps {
|
||||||
title: string,
|
title: string,
|
||||||
color: string,
|
color: string,
|
||||||
arrayToIterate: any[],
|
arrayToIterate: any[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EntryTableSection: React.FC<EntrySectionProps> = ({title, color, arrayToIterate}) => {
|
export const EntryTableSection: React.FC<EntrySectionProps> = ({ title, color, arrayToIterate }) => {
|
||||||
let arrayToIterateSorted: any[];
|
let arrayToIterateSorted: any[];
|
||||||
if (arrayToIterate) {
|
if (arrayToIterate) {
|
||||||
arrayToIterateSorted = arrayToIterate.sort((a, b) => {
|
arrayToIterateSorted = arrayToIterate.sort((a, b) => {
|
||||||
@@ -220,7 +227,7 @@ export const EntryTableSection: React.FC<EntrySectionProps> = ({title, color, ar
|
|||||||
<EntrySectionContainer title={title} color={color}>
|
<EntrySectionContainer title={title} color={color}>
|
||||||
<table>
|
<table>
|
||||||
<tbody id={`tbody-${title}`}>
|
<tbody id={`tbody-${title}`}>
|
||||||
{arrayToIterateSorted.map(({name, value, selector}, index) => <EntryViewLine
|
{arrayToIterateSorted.map(({ name, value, selector }, index) => <EntryViewLine
|
||||||
key={index}
|
key={index}
|
||||||
label={name}
|
label={name}
|
||||||
value={value}
|
value={value}
|
||||||
@@ -228,7 +235,7 @@ export const EntryTableSection: React.FC<EntrySectionProps> = ({title, color, ar
|
|||||||
/>)}
|
/>)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</EntrySectionContainer> : <span/>
|
</EntrySectionContainer> : <span />
|
||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
@@ -247,7 +254,7 @@ interface EntryPolicySectionCollapsibleTitleProps {
|
|||||||
setExpanded: any;
|
setExpanded: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsibleTitleProps> = ({label, matched, expanded, setExpanded}) => {
|
const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsibleTitleProps> = ({ label, matched, expanded, setExpanded }) => {
|
||||||
return <div className={styles.title}>
|
return <div className={styles.title}>
|
||||||
<span
|
<span
|
||||||
className={`${styles.button}
|
className={`${styles.button}
|
||||||
@@ -260,8 +267,8 @@ const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsible
|
|||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<tr className={styles.dataLine}>
|
<tr className={styles.dataLine}>
|
||||||
<td className={`${styles.dataKey} ${styles.rulesTitleSuccess}`}>{label}</td>
|
<td className={`${styles.dataKey} ${styles.rulesTitleSuccess}`}>{label}</td>
|
||||||
<td className={`${styles.dataKey} ${matched === 'Success' ? styles.rulesMatchedSuccess : styles.rulesMatchedFailure}`}>{matched}</td>
|
<td className={`${styles.dataKey} ${matched === 'Success' ? styles.rulesMatchedSuccess : styles.rulesMatchedFailure}`}>{matched}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -273,28 +280,28 @@ interface EntryPolicySectionContainerProps {
|
|||||||
children?: any;
|
children?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EntryPolicySectionContainer: React.FC<EntryPolicySectionContainerProps> = ({label, matched, children}) => {
|
export const EntryPolicySectionContainer: React.FC<EntryPolicySectionContainerProps> = ({ label, matched, children }) => {
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
return <CollapsibleContainer
|
return <CollapsibleContainer
|
||||||
className={styles.collapsibleContainer}
|
className={styles.collapsibleContainer}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
title={<EntryPolicySectionCollapsibleTitle label={label} matched={matched} expanded={expanded} setExpanded={setExpanded}/>}
|
title={<EntryPolicySectionCollapsibleTitle label={label} matched={matched} expanded={expanded} setExpanded={setExpanded} />}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</CollapsibleContainer>
|
</CollapsibleContainer>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({title, color, latency, arrayToIterate}) => {
|
export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({ title, color, latency, arrayToIterate }) => {
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
{
|
{
|
||||||
arrayToIterate && arrayToIterate.length > 0 ?
|
arrayToIterate && arrayToIterate.length > 0 ?
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<EntrySectionContainer title={title} color={color}>
|
<EntrySectionContainer title={title} color={color}>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{arrayToIterate.map(({rule, matched}, index) => {
|
{arrayToIterate.map(({ rule, matched }, index) => {
|
||||||
return (
|
return (
|
||||||
<EntryPolicySectionContainer key={index} label={rule.Name} matched={matched && (rule.Type === 'slo' ? rule.ResponseTime >= latency : true)? "Success" : "Failure"}>
|
<EntryPolicySectionContainer key={index} label={rule.Name} matched={matched && (rule.Type === 'slo' ? rule.ResponseTime >= latency : true) ? "Success" : "Failure"}>
|
||||||
{
|
{
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{
|
{
|
||||||
@@ -330,11 +337,11 @@ export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({titl
|
|||||||
</EntryPolicySectionContainer>
|
</EntryPolicySectionContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</EntrySectionContainer>
|
</EntrySectionContainer>
|
||||||
</React.Fragment> : <span className={styles.noRules}>No rules could be applied to this request.</span>
|
</React.Fragment> : <span className={styles.noRules}>No rules could be applied to this request.</span>
|
||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@@ -347,7 +354,7 @@ interface EntryContractSectionProps {
|
|||||||
contractContent: string,
|
contractContent: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EntryContractSection: React.FC<EntryContractSectionProps> = ({color, requestReason, responseReason, contractContent}) => {
|
export const EntryContractSection: React.FC<EntryContractSectionProps> = ({ color, requestReason, responseReason, contractContent }) => {
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
{requestReason && <EntrySectionContainer title="Request" color={color}>
|
{requestReason && <EntrySectionContainer title="Request" color={color}>
|
||||||
{requestReason}
|
{requestReason}
|
||||||
|
|||||||
@@ -67,7 +67,6 @@
|
|||||||
|
|
||||||
.capture img
|
.capture img
|
||||||
height: 14px
|
height: 14px
|
||||||
z-index: 1000
|
|
||||||
margin-top: 12px
|
margin-top: 12px
|
||||||
margin-left: -2px
|
margin-left: -2px
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {RecoilRoot, RecoilState, useRecoilState, useRecoilValue, useSetRecoilSta
|
|||||||
import entriesAtom from "../../recoil/entries";
|
import entriesAtom from "../../recoil/entries";
|
||||||
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
||||||
import queryAtom from "../../recoil/query";
|
import queryAtom from "../../recoil/query";
|
||||||
import {TLSWarning} from "../TLSWarning/TLSWarning";
|
|
||||||
import trafficViewerApiAtom from "../../recoil/TrafficViewerApi"
|
import trafficViewerApiAtom from "../../recoil/TrafficViewerApi"
|
||||||
import TrafficViewerApi from "./TrafficViewerApi";
|
import TrafficViewerApi from "./TrafficViewerApi";
|
||||||
import {StatusBar} from "../UI/StatusBar";
|
import {StatusBar} from "../UI/StatusBar";
|
||||||
@@ -77,10 +76,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
|||||||
const setLeftOffTop = useSetRecoilState(leftOffTopAtom);
|
const setLeftOffTop = useSetRecoilState(leftOffTopAtom);
|
||||||
const scrollableRef = useRef(null);
|
const scrollableRef = useRef(null);
|
||||||
|
|
||||||
const [showTLSWarning, setShowTLSWarning] = useState(false);
|
|
||||||
const [userDismissedTLSWarning, setUserDismissedTLSWarning] = useState(false);
|
|
||||||
const [addressesWithTLS, setAddressesWithTLS] = useState(new Set<string>());
|
|
||||||
|
|
||||||
const handleQueryChange = useMemo(
|
const handleQueryChange = useMemo(
|
||||||
() =>
|
() =>
|
||||||
debounce(async (query: string) => {
|
debounce(async (query: string) => {
|
||||||
@@ -286,12 +281,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
|||||||
<EntryDetailed/>
|
<EntryDetailed/>
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
<TLSWarning showTLSWarning={showTLSWarning}
|
|
||||||
setShowTLSWarning={setShowTLSWarning}
|
|
||||||
addressesWithTLS={addressesWithTLS}
|
|
||||||
setAddressesWithTLS={setAddressesWithTLS}
|
|
||||||
userDismissedTLSWarning={userDismissedTLSWarning}
|
|
||||||
setUserDismissedTLSWarning={setUserDismissedTLSWarning}/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ type TrafficViewerApi = {
|
|||||||
analyzeStatus: () => any
|
analyzeStatus: () => any
|
||||||
fetchEntries: (leftOff: any, direction: number, query: any, limit: number, timeoutMs: number) => any
|
fetchEntries: (leftOff: any, direction: number, query: any, limit: number, timeoutMs: number) => any
|
||||||
getEntry: (entryId: any, query: string) => any
|
getEntry: (entryId: any, query: string) => any
|
||||||
getRecentTLSLinks: () => any,
|
|
||||||
webSocket: {
|
webSocket: {
|
||||||
close: () => void
|
close: () => void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import React, { CSSProperties } from "react";
|
import React from "react";
|
||||||
import styles from "./style/InformationIcon.module.sass"
|
import styles from "./style/InformationIcon.module.sass"
|
||||||
|
|
||||||
const DEFUALT_LINK = "https://getmizu.io/docs"
|
const DEFUALT_LINK = "https://getmizu.io/docs"
|
||||||
|
|
||||||
export interface InformationIconProps {
|
interface LinkProps {
|
||||||
link?: string,
|
link?: string,
|
||||||
style?: CSSProperties
|
className?: string
|
||||||
|
title?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InformationIcon: React.FC<InformationIconProps> = ({ link, style }) => {
|
export const Link: React.FC<LinkProps> = ({ link, className, title, children }) => {
|
||||||
return <React.Fragment>
|
return <a href={link} className={className} title={title} target="_blank">
|
||||||
<a href={DEFUALT_LINK ? DEFUALT_LINK : link} style={style} className={styles.linkStyle} title="documentation" target="_blank">
|
{children}
|
||||||
<span>Docs</span>
|
</a>
|
||||||
</a>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const InformationIcon: React.FC<LinkProps> = ({ className }) => {
|
||||||
|
return <Link title="documentation" className={`${styles.linkStyle} ${className}`} link={DEFUALT_LINK}>
|
||||||
|
<span>Docs</span>
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
@@ -5,9 +5,10 @@ import styles from './style/Resizeable.module.sass'
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
children
|
children
|
||||||
minWidth: number
|
minWidth: number
|
||||||
|
maxWidth?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const Resizeable: React.FC<Props> = ({ children, minWidth }) => {
|
const Resizeable: React.FC<Props> = ({ children, minWidth, maxWidth }) => {
|
||||||
const resizeble = useRef(null)
|
const resizeble = useRef(null)
|
||||||
let mousePos = { x: 0, y: 0 }
|
let mousePos = { x: 0, y: 0 }
|
||||||
let elementDimention = { w: 0, h: 0 }
|
let elementDimention = { w: 0, h: 0 }
|
||||||
@@ -47,14 +48,11 @@ const Resizeable: React.FC<Props> = ({ children, minWidth }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className={styles.resizable} ref={resizeble} style={{ width: elemWidth, maxWidth: maxWidth }}>
|
||||||
<div className={styles.resizable} ref={resizeble} style={{ width: elemWidth }}>
|
{children}
|
||||||
{children}
|
<div className={`${styles.resizer} ${styles.resizerRight}`} onMouseDown={mouseDownHandler}></div>
|
||||||
<div className={`${styles.resizer} ${styles.resizerRight}`} onMouseDown={mouseDownHandler}></div>
|
{/* <div className={`${styles.resizer} ${styles.resizerB}`} onMouseDown={mouseDownHandler}></div> -- FutureUse*/}
|
||||||
{/* <div className={`${styles.resizer} ${styles.resizerB}`} onMouseDown={mouseDownHandler}></div> -- FutureUse*/}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import Tooltip from "./Tooltip";
|
|||||||
import Checkbox from "./Checkbox"
|
import Checkbox from "./Checkbox"
|
||||||
import { StatusBar } from "./StatusBar";
|
import { StatusBar } from "./StatusBar";
|
||||||
import CustomModal from "./CustomModal";
|
import CustomModal from "./CustomModal";
|
||||||
import { InformationIcon } from "./InformationIcon";
|
import { InformationIcon, Link } from "./InformationIcon";
|
||||||
import SelectList from "./SelectList";
|
import SelectList from "./SelectList";
|
||||||
import NoDataMessage from "./NoDataMessage";
|
import NoDataMessage from "./NoDataMessage";
|
||||||
|
|
||||||
|
|
||||||
export { LoadingOverlay, Select, Tabs, Tooltip, Checkbox, CustomModal, InformationIcon, SelectList, NoDataMessage }
|
export { LoadingOverlay, Select, Tabs, Tooltip, Checkbox, CustomModal, InformationIcon, SelectList, NoDataMessage, Link }
|
||||||
export { StatusBar }
|
export { StatusBar }
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
align-items: center
|
align-items: center
|
||||||
justify-content: center
|
justify-content: center
|
||||||
background-color: rgba(25, 25, 25, 0.5)
|
background-color: rgba(25, 25, 25, 0.5)
|
||||||
|
z-index: 1000
|
||||||
|
|
||||||
.loadingOverlaySpinner
|
.loadingOverlaySpinner
|
||||||
width: 60px
|
width: 60px
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export const TOAST_CONTAINER_ID = "Common";
|
export const TOAST_CONTAINER_ID = "Common";
|
||||||
|
export const MAX_ENTRIES = 10000;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
"node-fetch": "^3.1.1",
|
"node-fetch": "^3.1.1",
|
||||||
"node-sass": "^6.0.0",
|
"node-sass": "^6.0.0",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"protobuf-decoder": "^0.1.0",
|
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-copy-to-clipboard": "^5.0.3",
|
"react-copy-to-clipboard": "^5.0.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
|||||||
@@ -62,11 +62,6 @@ export default class Api {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecentTLSLinks = async () => {
|
|
||||||
const response = await client.get("/status/recentTLSLinks");
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
getAuthStatus = async () => {
|
getAuthStatus = async () => {
|
||||||
const response = await client.get("/status/auth");
|
const response = await client.get("/status/auth");
|
||||||
return response.data;
|
return response.data;
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ button
|
|||||||
|
|
||||||
::-webkit-scrollbar
|
::-webkit-scrollbar
|
||||||
width: 6px
|
width: 6px
|
||||||
|
height: 6px
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb
|
::-webkit-scrollbar-thumb
|
||||||
background-color: $light-blue-color
|
background-color: $light-blue-color
|
||||||
|
|||||||
Reference in New Issue
Block a user