mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-02 17:50:30 +00:00
Compare commits
62 Commits
32.0-dev16
...
34.0-dev9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ef6a7d2c4 | ||
|
|
ba361df7e7 | ||
|
|
1f70eab0a4 | ||
|
|
ea4991905b | ||
|
|
2ad4838cf5 | ||
|
|
e41488ef3e | ||
|
|
533fb71bf4 | ||
|
|
6f8aad83e6 | ||
|
|
6e6bcec77e | ||
|
|
71db792a4e | ||
|
|
f7f61c1217 | ||
|
|
696501fa11 | ||
|
|
415b5e08fd | ||
|
|
7810f6defb | ||
|
|
2aeac6c9e6 | ||
|
|
dc241218bf | ||
|
|
02b3672e09 | ||
|
|
45b368b33e | ||
|
|
8f64fdaa61 | ||
|
|
7edb0b153b | ||
|
|
569a687fdf | ||
|
|
11e8b5eb65 | ||
|
|
3901f3f3fe | ||
|
|
2f1cc21fcb | ||
|
|
433253a27b | ||
|
|
00cc94fbe5 | ||
|
|
8feef78ab1 | ||
|
|
992abc99bc | ||
|
|
486d0b1088 | ||
|
|
f61a02d288 | ||
|
|
03694e57c0 | ||
|
|
1760afda2b | ||
|
|
522e2cc3da | ||
|
|
ab38f4c011 | ||
|
|
a9de4f0bba | ||
|
|
948af518b5 | ||
|
|
73448b514e | ||
|
|
fc194354bc | ||
|
|
8418802c7e | ||
|
|
bfa834e840 | ||
|
|
5c012641a5 | ||
|
|
74bd4b180f | ||
|
|
8ea2dabb34 | ||
|
|
366d34b8d0 | ||
|
|
5fc3e38c1a | ||
|
|
09a0fca2c2 | ||
|
|
0437586908 | ||
|
|
f8181ccb07 | ||
|
|
414e5cfe5a | ||
|
|
2fac0009ea | ||
|
|
36d59ede07 | ||
|
|
ac53508ad7 | ||
|
|
e24c18254c | ||
|
|
b2830f133f | ||
|
|
eef0ee8023 | ||
|
|
4c0aeb8146 | ||
|
|
0dc0459dff | ||
|
|
81f06003d5 | ||
|
|
c7d068748a | ||
|
|
8102c49138 | ||
|
|
65fb2a4fe4 | ||
|
|
57f8a8dca9 |
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -290,3 +290,15 @@ jobs:
|
|||||||
tag: ${{ steps.versioning.outputs.version }}
|
tag: ${{ steps.versioning.outputs.version }}
|
||||||
prerelease: ${{ github.ref != 'refs/heads/main' }}
|
prerelease: ${{ github.ref != 'refs/heads/main' }}
|
||||||
bodyFile: 'cli/bin/README.md'
|
bodyFile: 'cli/bin/README.md'
|
||||||
|
|
||||||
|
- name: Slack notification on failure
|
||||||
|
uses: ravsamhq/notify-slack-action@v1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notification_title: 'Mizu enterprise {workflow} has {status_message}'
|
||||||
|
message_format: '{emoji} *{workflow}* {status_message} during <{run_url}|run>, after commit <{commit_url}|{commit_sha}> by ${{ github.event.head_commit.author.name }} <${{ github.event.head_commit.author.email }}> ```${{ github.event.head_commit.message }}```'
|
||||||
|
footer: 'Linked Repo <{repo_url}|{repo}>'
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
|
|||||||
11
.github/workflows/static_code_analysis.yml
vendored
11
.github/workflows/static_code_analysis.yml
vendored
@@ -26,6 +26,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y libpcap-dev
|
sudo apt install -y libpcap-dev
|
||||||
|
./devops/install-capstone.sh
|
||||||
|
|
||||||
- name: Check Agent modified files
|
- name: Check Agent modified files
|
||||||
id: agent_modified_files
|
id: agent_modified_files
|
||||||
@@ -37,7 +38,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
working-directory: agent
|
working-directory: agent
|
||||||
args: --timeout=3m
|
args: --timeout=10m
|
||||||
|
|
||||||
- name: Check shared modified files
|
- name: Check shared modified files
|
||||||
id: shared_modified_files
|
id: shared_modified_files
|
||||||
@@ -49,7 +50,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
working-directory: shared
|
working-directory: shared
|
||||||
args: --timeout=3m
|
args: --timeout=10m
|
||||||
|
|
||||||
- name: Check tap modified files
|
- name: Check tap modified files
|
||||||
id: tap_modified_files
|
id: tap_modified_files
|
||||||
@@ -61,7 +62,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
working-directory: tap
|
working-directory: tap
|
||||||
args: --timeout=3m
|
args: --timeout=10m
|
||||||
|
|
||||||
- name: Check cli modified files
|
- name: Check cli modified files
|
||||||
id: cli_modified_files
|
id: cli_modified_files
|
||||||
@@ -73,7 +74,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
working-directory: cli
|
working-directory: cli
|
||||||
args: --timeout=3m
|
args: --timeout=10m
|
||||||
|
|
||||||
- name: Check acceptanceTests modified files
|
- name: Check acceptanceTests modified files
|
||||||
id: acceptanceTests_modified_files
|
id: acceptanceTests_modified_files
|
||||||
@@ -85,7 +86,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
working-directory: acceptanceTests
|
working-directory: acceptanceTests
|
||||||
args: --timeout=3m
|
args: --timeout=10m
|
||||||
|
|
||||||
- name: Check tap/api modified files
|
- name: Check tap/api modified files
|
||||||
id: tap_api_modified_files
|
id: tap_api_modified_files
|
||||||
|
|||||||
5
.github/workflows/test.yml
vendored
5
.github/workflows/test.yml
vendored
@@ -35,6 +35,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get install libpcap-dev
|
sudo apt-get install libpcap-dev
|
||||||
|
|
||||||
|
- name: Install Capstone
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
./devops/install-capstone.sh
|
||||||
|
|
||||||
- name: Check CLI modified files
|
- name: Check CLI modified files
|
||||||
id: cli_modified_files
|
id: cli_modified_files
|
||||||
run: devops/check_modified_files.sh cli/
|
run: devops/check_modified_files.sh cli/
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -53,3 +53,6 @@ tap/extensions/*/expect
|
|||||||
**/node_modules/**
|
**/node_modules/**
|
||||||
**/dist/**
|
**/dist/**
|
||||||
*.editorconfig
|
*.editorconfig
|
||||||
|
|
||||||
|
# Ignore *.log files
|
||||||
|
*.log
|
||||||
|
|||||||
17
Dockerfile
17
Dockerfile
@@ -25,7 +25,9 @@ RUN npm run build
|
|||||||
### Base builder image for native builds architecture
|
### Base builder image for native builds architecture
|
||||||
FROM golang:1.17-alpine AS builder-native-base
|
FROM golang:1.17-alpine AS builder-native-base
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
RUN apk add --no-cache libpcap-dev g++ perl-utils
|
RUN apk add --no-cache libpcap-dev g++ perl-utils curl build-base binutils-gold bash
|
||||||
|
COPY devops/install-capstone.sh .
|
||||||
|
RUN ./install-capstone.sh
|
||||||
|
|
||||||
|
|
||||||
### Intermediate builder image for x86-64 to x86-64 native builds
|
### Intermediate builder image for x86-64 to x86-64 native builds
|
||||||
@@ -39,15 +41,15 @@ ENV GOARCH=arm64
|
|||||||
|
|
||||||
|
|
||||||
### Builder image for x86-64 to AArch64 cross-compilation
|
### Builder image for x86-64 to AArch64 cross-compilation
|
||||||
FROM up9inc/linux-arm64-musl-go-libpcap AS builder-from-amd64-to-arm64v8
|
FROM up9inc/linux-arm64-musl-go-libpcap-capstone AS builder-from-amd64-to-arm64v8
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
ENV GOARCH=arm64 CGO_CFLAGS="-I/work/libpcap"
|
ENV GOARCH=arm64 CGO_CFLAGS="-I/work/libpcap -I/work/capstone/include"
|
||||||
|
|
||||||
|
|
||||||
### Builder image for AArch64 to x86-64 cross-compilation
|
### Builder image for AArch64 to x86-64 cross-compilation
|
||||||
FROM up9inc/linux-x86_64-musl-go-libpcap AS builder-from-arm64v8-to-amd64
|
FROM up9inc/linux-x86_64-musl-go-libpcap-capstone AS builder-from-arm64v8-to-amd64
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
ENV GOARCH=amd64 CGO_CFLAGS="-I/libpcap"
|
ENV GOARCH=amd64 CGO_CFLAGS="-I/libpcap -I/capstone/include"
|
||||||
|
|
||||||
|
|
||||||
### Final builder image where the build happens
|
### Final builder image where the build happens
|
||||||
@@ -68,6 +70,7 @@ COPY shared/go.mod shared/go.mod ../shared/
|
|||||||
COPY logger/go.mod logger/go.mod ../logger/
|
COPY logger/go.mod logger/go.mod ../logger/
|
||||||
COPY tap/go.mod tap/go.mod ../tap/
|
COPY tap/go.mod tap/go.mod ../tap/
|
||||||
COPY tap/api/go.mod ../tap/api/
|
COPY tap/api/go.mod ../tap/api/
|
||||||
|
COPY tap/dbgctl/go.mod ../tap/dbgctl/
|
||||||
COPY tap/extensions/amqp/go.mod ../tap/extensions/amqp/
|
COPY tap/extensions/amqp/go.mod ../tap/extensions/amqp/
|
||||||
COPY tap/extensions/http/go.mod ../tap/extensions/http/
|
COPY tap/extensions/http/go.mod ../tap/extensions/http/
|
||||||
COPY tap/extensions/kafka/go.mod ../tap/extensions/kafka/
|
COPY tap/extensions/kafka/go.mod ../tap/extensions/kafka/
|
||||||
@@ -94,8 +97,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.3/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
ADD https://github.com/up9inc/basenine/releases/download/v0.8.3/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.7.3/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
ADD https://github.com/up9inc/basenine/releases/download/v0.8.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}" && \
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -83,6 +83,7 @@ test-lint: ## Run lint on all modules
|
|||||||
cd cli && golangci-lint run
|
cd cli && golangci-lint run
|
||||||
cd acceptanceTests && golangci-lint run
|
cd acceptanceTests && golangci-lint run
|
||||||
cd tap/api && golangci-lint run
|
cd tap/api && golangci-lint run
|
||||||
|
cd tap/dbgctl && golangci-lint run
|
||||||
cd tap/extensions/ && for D in */; do cd $$D && golangci-lint run && cd ..; done
|
cd tap/extensions/ && for D in */; do cd $$D && golangci-lint run && cd ..; done
|
||||||
|
|
||||||
test-cli: ## Run cli tests
|
test-cli: ## Run cli tests
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
test: ## Run acceptance tests.
|
test: ## Run acceptance tests.
|
||||||
|
@npm install cypress@10.0.1 -y
|
||||||
@go test ./... -timeout 1h -v
|
@go test ./... -timeout 1h -v
|
||||||
|
|||||||
31
acceptanceTests/cypress.config.js
Normal file
31
acceptanceTests/cypress.config.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const { defineConfig } = require('cypress')
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
|
watchForFileChanges: false,
|
||||||
|
viewportWidth: 1920,
|
||||||
|
viewportHeight: 1080,
|
||||||
|
video: false,
|
||||||
|
screenshotOnRunFailure: false,
|
||||||
|
defaultCommandTimeout: 6000,
|
||||||
|
env: {
|
||||||
|
testUrl: 'http://localhost:8899/',
|
||||||
|
redactHeaderContent: 'User-Header[REDACTED]',
|
||||||
|
redactBodyContent: '{ "User": "[REDACTED]" }',
|
||||||
|
regexMaskingBodyContent: '[REDACTED]',
|
||||||
|
greenFilterColor: 'rgb(210, 250, 210)',
|
||||||
|
redFilterColor: 'rgb(250, 214, 220)',
|
||||||
|
bodyJsonClass: '.hljs',
|
||||||
|
mizuWidth: 1920,
|
||||||
|
normalMizuHeight: 1080,
|
||||||
|
hugeMizuHeight: 3500,
|
||||||
|
},
|
||||||
|
e2e: {
|
||||||
|
// We've imported your old cypress plugins here.
|
||||||
|
// You may want to clean this up later by importing these.
|
||||||
|
// setupNodeEvents(on, config) {
|
||||||
|
// return require('./cypress/plugins/index.js')(on, config)
|
||||||
|
// },
|
||||||
|
specPattern: 'cypress/e2e/tests/*.js',
|
||||||
|
supportFile: false
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"watchForFileChanges":false,
|
|
||||||
"viewportWidth": 1920,
|
|
||||||
"viewportHeight": 1080,
|
|
||||||
"video": false,
|
|
||||||
"screenshotOnRunFailure": false,
|
|
||||||
"defaultCommandTimeout": 6000,
|
|
||||||
"testFiles": [
|
|
||||||
"tests/GuiPort.js",
|
|
||||||
"tests/MultipleNamespaces.js",
|
|
||||||
"tests/Redact.js",
|
|
||||||
"tests/NoRedact.js",
|
|
||||||
"tests/Regex.js",
|
|
||||||
"tests/RegexMasking.js",
|
|
||||||
"tests/IgnoredUserAgents.js",
|
|
||||||
"tests/UiTest.js",
|
|
||||||
"tests/Redis.js",
|
|
||||||
"tests/Rabbit.js",
|
|
||||||
"tests/serviceMapFunction.js"
|
|
||||||
],
|
|
||||||
|
|
||||||
"env": {
|
|
||||||
"testUrl": "http://localhost:8899/",
|
|
||||||
"redactHeaderContent": "User-Header[REDACTED]",
|
|
||||||
"redactBodyContent": "{ \"User\": \"[REDACTED]\" }",
|
|
||||||
"regexMaskingBodyContent": "[REDACTED]",
|
|
||||||
"greenFilterColor": "rgb(210, 250, 210)",
|
|
||||||
"redFilterColor": "rgb(250, 214, 220)",
|
|
||||||
"bodyJsonClass": ".hljs",
|
|
||||||
"mizuWidth": 1920,
|
|
||||||
"normalMizuHeight": 1080,
|
|
||||||
"hugeMizuHeight": 3500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,8 +4,6 @@ export const valueTabs = {
|
|||||||
none: null
|
none: null
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxEntriesInDom = 13;
|
|
||||||
|
|
||||||
export function isValueExistsInElement(shouldInclude, content, domPathToContainer){
|
export function isValueExistsInElement(shouldInclude, content, domPathToContainer){
|
||||||
it(`should ${shouldInclude ? '' : 'not'} include '${content}'`, function () {
|
it(`should ${shouldInclude ? '' : 'not'} include '${content}'`, function () {
|
||||||
cy.get(domPathToContainer).then(htmlText => {
|
cy.get(domPathToContainer).then(htmlText => {
|
||||||
@@ -57,15 +55,8 @@ export function rightOnHoverCheck(path, expectedText) {
|
|||||||
cy.get(`#rightSideContainer [data-cy='QueryableTooltip']`).invoke('text').should('match', new RegExp(expectedText));
|
cy.get(`#rightSideContainer [data-cy='QueryableTooltip']`).invoke('text').should('match', new RegExp(expectedText));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkThatAllEntriesShown() {
|
|
||||||
cy.get('#entries-length').then(number => {
|
|
||||||
if (number.text() === '1')
|
|
||||||
cy.get('[title="Fetch old records"]').click();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkFilterByMethod(funcDict) {
|
export function checkFilterByMethod(funcDict) {
|
||||||
const {protocol, method, methodQuery, summary, summaryQuery} = funcDict;
|
const {protocol, method, methodQuery, summary, summaryQuery, numberOfRecords} = funcDict;
|
||||||
const summaryDict = getSummaryDict(summary, summaryQuery);
|
const summaryDict = getSummaryDict(summary, summaryQuery);
|
||||||
const methodDict = getMethodDict(method, methodQuery);
|
const methodDict = getMethodDict(method, methodQuery);
|
||||||
const protocolDict = getProtocolDict(protocol.name, protocol.text);
|
const protocolDict = getProtocolDict(protocol.name, protocol.text);
|
||||||
@@ -76,53 +67,53 @@ export function checkFilterByMethod(funcDict) {
|
|||||||
cy.get('[type="submit"]').click();
|
cy.get('[type="submit"]').click();
|
||||||
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
||||||
|
|
||||||
cy.get('#entries-length').then(number => {
|
waitForFetch(numberOfRecords);
|
||||||
// if the entries list isn't expanded it expands here
|
pauseStream();
|
||||||
if (number.text() === '0' || number.text() === '1') // todo change when TRA-4262 is fixed
|
|
||||||
cy.get('[title="Fetch old records"]').click();
|
|
||||||
|
|
||||||
cy.get('#entries-length').should('not.have.text', '0').and('not.have.text', '1').then(() => {
|
cy.get(`#list [id^=entry]`).then(elements => {
|
||||||
cy.get(`#list [id]`).then(elements => {
|
const listElmWithIdAttr = Object.values(elements);
|
||||||
const listElmWithIdAttr = Object.values(elements);
|
let doneCheckOnFirst = false;
|
||||||
let doneCheckOnFirst = false;
|
|
||||||
|
|
||||||
cy.get('#entries-length').invoke('text').then(len => {
|
cy.get('#entries-length').invoke('text').then(len => {
|
||||||
resizeIfNeeded(len);
|
listElmWithIdAttr.forEach(entry => {
|
||||||
listElmWithIdAttr.forEach(entry => {
|
if (entry?.id && entry.id.match(RegExp(/entry-(\d{24})$/gm))) {
|
||||||
if (entry?.id && entry.id.match(RegExp(/entry-(\d{24})$/gm))) {
|
const entryId = getEntryId(entry.id);
|
||||||
const entryId = getEntryId(entry.id);
|
|
||||||
|
|
||||||
leftTextCheck(entryId, methodDict.pathLeft, methodDict.expectedText);
|
leftTextCheck(entryId, methodDict.pathLeft, methodDict.expectedText);
|
||||||
leftTextCheck(entryId, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
leftTextCheck(entryId, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
||||||
if (summaryDict)
|
if (summaryDict)
|
||||||
leftTextCheck(entryId, summaryDict.pathLeft, summaryDict.expectedText);
|
leftTextCheck(entryId, summaryDict.pathLeft, summaryDict.expectedText);
|
||||||
|
|
||||||
if (!doneCheckOnFirst) {
|
if (!doneCheckOnFirst) {
|
||||||
deepCheck(funcDict, protocolDict, methodDict, entry);
|
deepCheck(funcDict, protocolDict, methodDict, entry);
|
||||||
doneCheckOnFirst = true;
|
doneCheckOnFirst = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
resizeIfNeeded(len);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const refreshWaitTimeout = 10000;
|
||||||
|
|
||||||
|
export function waitForFetch(gt) {
|
||||||
|
cy.get('#entries-length', {timeout: refreshWaitTimeout}).should((el) => {
|
||||||
|
expect(parseInt(el.text().trim(), 10)).to.be.greaterThan(gt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pauseStream() {
|
||||||
|
cy.get('#pause-icon').click();
|
||||||
|
cy.get('#pause-icon').should('not.be.visible');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getEntryId(id) {
|
export function getEntryId(id) {
|
||||||
// take the second part from the string (entry-<ID>)
|
// take the second part from the string (entry-<ID>)
|
||||||
return id.split('-')[1];
|
return id.split('-')[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function resizeIfNeeded(entriesLen) {
|
|
||||||
if (entriesLen > maxEntriesInDom){
|
|
||||||
Cypress.config().viewportHeight === Cypress.env('normalMizuHeight') ?
|
|
||||||
resizeToHugeMizu() : resizeToNormalMizu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deepCheck(generalDict, protocolDict, methodDict, entry) {
|
function deepCheck(generalDict, protocolDict, methodDict, entry) {
|
||||||
const entryId = getEntryId(entry.id);
|
const entryId = getEntryId(entry.id);
|
||||||
const {summary, value} = generalDict;
|
const {summary, value} = generalDict;
|
||||||
25
acceptanceTests/cypress/e2e/tests/IgnoredUserAgents.js
Normal file
25
acceptanceTests/cypress/e2e/tests/IgnoredUserAgents.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import {
|
||||||
|
isValueExistsInElement,
|
||||||
|
resizeToHugeMizu,
|
||||||
|
} from "../testHelpers/TrafficHelper";
|
||||||
|
|
||||||
|
it('Loading Mizu', function () {
|
||||||
|
cy.visit(Cypress.env('testUrl'));
|
||||||
|
});
|
||||||
|
|
||||||
|
checkEntries();
|
||||||
|
|
||||||
|
function checkEntries() {
|
||||||
|
it('checking all entries', function () {
|
||||||
|
cy.get('#entries-length').should('not.have.text', '0').then(() => {
|
||||||
|
resizeToHugeMizu();
|
||||||
|
|
||||||
|
cy.get('#list [id^=entry]').each(entryElement => {
|
||||||
|
entryElement.click();
|
||||||
|
cy.get('#tbody-Headers').should('be.visible');
|
||||||
|
isValueExistsInElement(false, 'Ignored-User-Agent', '#tbody-Headers');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ it('opening mizu', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const rabbitProtocolDetails = {name: 'AMQP', text: 'Advanced Message Queuing Protocol 0-9-1'};
|
const rabbitProtocolDetails = {name: 'AMQP', text: 'Advanced Message Queuing Protocol 0-9-1'};
|
||||||
|
const numberOfRecords = 5;
|
||||||
|
|
||||||
checkFilterByMethod({
|
checkFilterByMethod({
|
||||||
protocol: rabbitProtocolDetails,
|
protocol: rabbitProtocolDetails,
|
||||||
@@ -12,6 +13,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "exchange declare"',
|
methodQuery: 'request.method == "exchange declare"',
|
||||||
summary: 'exchange',
|
summary: 'exchange',
|
||||||
summaryQuery: 'request.exchange == "exchange"',
|
summaryQuery: 'request.exchange == "exchange"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: null
|
value: null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "queue declare"',
|
methodQuery: 'request.method == "queue declare"',
|
||||||
summary: 'queue',
|
summary: 'queue',
|
||||||
summaryQuery: 'request.queue == "queue"',
|
summaryQuery: 'request.queue == "queue"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: null
|
value: null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -30,6 +33,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "queue bind"',
|
methodQuery: 'request.method == "queue bind"',
|
||||||
summary: 'queue',
|
summary: 'queue',
|
||||||
summaryQuery: 'request.queue == "queue"',
|
summaryQuery: 'request.queue == "queue"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: null
|
value: null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,6 +43,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "basic publish"',
|
methodQuery: 'request.method == "basic publish"',
|
||||||
summary: 'exchange',
|
summary: 'exchange',
|
||||||
summaryQuery: 'request.exchange == "exchange"',
|
summaryQuery: 'request.exchange == "exchange"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.request, regex: /^message$/mg}
|
value: {tab: valueTabs.request, regex: /^message$/mg}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -48,6 +53,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "basic consume"',
|
methodQuery: 'request.method == "basic consume"',
|
||||||
summary: 'queue',
|
summary: 'queue',
|
||||||
summaryQuery: 'request.queue == "queue"',
|
summaryQuery: 'request.queue == "queue"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: null
|
value: null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,5 +63,6 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.method == "basic deliver"',
|
methodQuery: 'request.method == "basic deliver"',
|
||||||
summary: 'exchange',
|
summary: 'exchange',
|
||||||
summaryQuery: 'request.queue == "exchange"',
|
summaryQuery: 'request.queue == "exchange"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.request, regex: /^message$/mg}
|
value: {tab: valueTabs.request, regex: /^message$/mg}
|
||||||
});
|
});
|
||||||
@@ -5,6 +5,7 @@ it('opening mizu', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const redisProtocolDetails = {name: 'redis', text: 'Redis Serialization Protocol'};
|
const redisProtocolDetails = {name: 'redis', text: 'Redis Serialization Protocol'};
|
||||||
|
const numberOfRecords = 5;
|
||||||
|
|
||||||
checkFilterByMethod({
|
checkFilterByMethod({
|
||||||
protocol: redisProtocolDetails,
|
protocol: redisProtocolDetails,
|
||||||
@@ -12,6 +13,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.command == "PING"',
|
methodQuery: 'request.command == "PING"',
|
||||||
summary: null,
|
summary: null,
|
||||||
summaryQuery: '',
|
summaryQuery: '',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: null
|
value: null
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.command == "SET"',
|
methodQuery: 'request.command == "SET"',
|
||||||
summary: 'key',
|
summary: 'key',
|
||||||
summaryQuery: 'request.key == "key"',
|
summaryQuery: 'request.key == "key"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.request, regex: /^\[value, keepttl]$/mg}
|
value: {tab: valueTabs.request, regex: /^\[value, keepttl]$/mg}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -30,6 +33,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.command == "EXISTS"',
|
methodQuery: 'request.command == "EXISTS"',
|
||||||
summary: 'key',
|
summary: 'key',
|
||||||
summaryQuery: 'request.key == "key"',
|
summaryQuery: 'request.key == "key"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.response, regex: /^1$/mg}
|
value: {tab: valueTabs.response, regex: /^1$/mg}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -39,6 +43,7 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.command == "GET"',
|
methodQuery: 'request.command == "GET"',
|
||||||
summary: 'key',
|
summary: 'key',
|
||||||
summaryQuery: 'request.key == "key"',
|
summaryQuery: 'request.key == "key"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.response, regex: /^value$/mg}
|
value: {tab: valueTabs.response, regex: /^value$/mg}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -48,5 +53,6 @@ checkFilterByMethod({
|
|||||||
methodQuery: 'request.command == "DEL"',
|
methodQuery: 'request.command == "DEL"',
|
||||||
summary: 'key',
|
summary: 'key',
|
||||||
summaryQuery: 'request.key == "key"',
|
summaryQuery: 'request.key == "key"',
|
||||||
|
numberOfRecords: numberOfRecords,
|
||||||
value: {tab: valueTabs.response, regex: /^1$|^0$/mg}
|
value: {tab: valueTabs.response, regex: /^1$|^0$/mg}
|
||||||
})
|
})
|
||||||
@@ -7,12 +7,12 @@ import {
|
|||||||
resizeToNormalMizu,
|
resizeToNormalMizu,
|
||||||
rightOnHoverCheck,
|
rightOnHoverCheck,
|
||||||
rightTextCheck,
|
rightTextCheck,
|
||||||
verifyMinimumEntries
|
verifyMinimumEntries,
|
||||||
|
refreshWaitTimeout,
|
||||||
|
waitForFetch,
|
||||||
|
pauseStream
|
||||||
} from "../testHelpers/TrafficHelper";
|
} from "../testHelpers/TrafficHelper";
|
||||||
|
|
||||||
const refreshWaitTimeout = 10000;
|
|
||||||
|
|
||||||
|
|
||||||
const fullParam = Cypress.env('arrayDict'); // "Name:fooNamespace:barName:foo1Namespace:bar1"
|
const fullParam = Cypress.env('arrayDict'); // "Name:fooNamespace:barName:foo1Namespace:bar1"
|
||||||
const podsArray = fullParam.split('Name:').slice(1); // ["fooNamespace:bar", "foo1Namespace:bar1"]
|
const podsArray = fullParam.split('Name:').slice(1); // ["fooNamespace:bar", "foo1Namespace:bar1"]
|
||||||
podsArray.forEach((podStr, index) => {
|
podsArray.forEach((podStr, index) => {
|
||||||
@@ -65,70 +65,77 @@ it('right side sanity test', function () {
|
|||||||
checkIllegalFilter('invalid filter');
|
checkIllegalFilter('invalid filter');
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'http',
|
filter: 'http',
|
||||||
leftSidePath: '> :nth-child(1) > :nth-child(1)',
|
leftSidePath: '> :nth-child(1) > :nth-child(1)',
|
||||||
leftSideExpectedText: 'HTTP',
|
leftSideExpectedText: 'HTTP',
|
||||||
rightSidePath: '[title=HTTP]',
|
rightSidePath: '[title=HTTP]',
|
||||||
rightSideExpectedText: 'Hypertext Transfer Protocol -- HTTP/1.1',
|
rightSideExpectedText: 'Hypertext Transfer Protocol -- HTTP/1.1',
|
||||||
applyByEnter: true
|
applyByCtrlEnter: true,
|
||||||
|
numberOfRecords: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'response.status == 200',
|
filter: 'response.status == 200',
|
||||||
leftSidePath: '[title="Status Code"]',
|
leftSidePath: '[title="Status Code"]',
|
||||||
leftSideExpectedText: '200',
|
leftSideExpectedText: '200',
|
||||||
rightSidePath: '> :nth-child(2) [title="Status Code"]',
|
rightSidePath: '> :nth-child(2) [title="Status Code"]',
|
||||||
rightSideExpectedText: '200',
|
rightSideExpectedText: '200',
|
||||||
applyByEnter: false
|
applyByCtrlEnter: false,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Cypress.env('shouldCheckSrcAndDest')) {
|
if (Cypress.env('shouldCheckSrcAndDest')) {
|
||||||
serviceMapCheck();
|
serviceMapCheck();
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'src.name == ""',
|
filter: 'src.name == ""',
|
||||||
leftSidePath: '[title="Source Name"]',
|
leftSidePath: '[title="Source Name"]',
|
||||||
leftSideExpectedText: '[Unresolved]',
|
leftSideExpectedText: '[Unresolved]',
|
||||||
rightSidePath: '> :nth-child(2) [title="Source Name"]',
|
rightSidePath: '> :nth-child(2) [title="Source Name"]',
|
||||||
rightSideExpectedText: '[Unresolved]',
|
rightSideExpectedText: '[Unresolved]',
|
||||||
applyByEnter: false
|
applyByCtrlEnter: false,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: `dst.name == "httpbin.mizu-tests"`,
|
filter: `dst.name == "httpbin.mizu-tests"`,
|
||||||
leftSidePath: '> :nth-child(3) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
leftSidePath: '> :nth-child(3) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
||||||
leftSideExpectedText: 'httpbin.mizu-tests',
|
leftSideExpectedText: 'httpbin.mizu-tests',
|
||||||
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
||||||
rightSideExpectedText: 'httpbin.mizu-tests',
|
rightSideExpectedText: 'httpbin.mizu-tests',
|
||||||
applyByEnter: false
|
applyByCtrlEnter: false,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'request.method == "GET"',
|
filter: 'request.method == "GET"',
|
||||||
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
||||||
leftSideExpectedText: 'GET',
|
leftSideExpectedText: 'GET',
|
||||||
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
||||||
rightSideExpectedText: 'GET',
|
rightSideExpectedText: 'GET',
|
||||||
applyByEnter: true
|
applyByCtrlEnter: true,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'request.path == "/get"',
|
filter: 'request.path == "/get"',
|
||||||
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
||||||
leftSideExpectedText: '/get',
|
leftSideExpectedText: '/get',
|
||||||
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
||||||
rightSideExpectedText: '/get',
|
rightSideExpectedText: '/get',
|
||||||
applyByEnter: false
|
applyByCtrlEnter: false,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
checkFilter({
|
checkFilter({
|
||||||
name: 'src.ip == "127.0.0.1"',
|
filter: 'src.ip == "127.0.0.1"',
|
||||||
leftSidePath: '[title="Source IP"]',
|
leftSidePath: '[title="Source IP"]',
|
||||||
leftSideExpectedText: '127.0.0.1',
|
leftSideExpectedText: '127.0.0.1',
|
||||||
rightSidePath: '> :nth-child(2) [title="Source IP"]',
|
rightSidePath: '> :nth-child(2) [title="Source IP"]',
|
||||||
rightSideExpectedText: '127.0.0.1',
|
rightSideExpectedText: '127.0.0.1',
|
||||||
applyByEnter: false
|
applyByCtrlEnter: false,
|
||||||
|
numberOfRecords: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
checkFilterNoResults('request.method == "POST"');
|
checkFilterNoResults('request.method == "POST"');
|
||||||
@@ -182,67 +189,62 @@ function checkIllegalFilter(illegalFilterName) {
|
|||||||
|
|
||||||
function checkFilter(filterDetails) {
|
function checkFilter(filterDetails) {
|
||||||
const {
|
const {
|
||||||
name,
|
filter,
|
||||||
leftSidePath,
|
leftSidePath,
|
||||||
rightSidePath,
|
rightSidePath,
|
||||||
rightSideExpectedText,
|
rightSideExpectedText,
|
||||||
leftSideExpectedText,
|
leftSideExpectedText,
|
||||||
applyByEnter
|
applyByCtrlEnter,
|
||||||
|
numberOfRecords
|
||||||
} = filterDetails;
|
} = filterDetails;
|
||||||
|
|
||||||
const entriesForDeeperCheck = 5;
|
const entriesForDeeperCheck = 5;
|
||||||
|
|
||||||
it(`checking the filter: ${name}`, function () {
|
it(`checking the filter: ${filter}`, function () {
|
||||||
cy.get('#total-entries').should('not.have.text', '0').then(number => {
|
cy.get('.w-tc-editor-text').clear();
|
||||||
const totalEntries = number.text();
|
// applying the filter with alt+enter or with the button
|
||||||
|
cy.get('.w-tc-editor-text').type(`${filter}${applyByCtrlEnter ? '{ctrl+enter}' : ''}`);
|
||||||
|
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
||||||
|
if (!applyByCtrlEnter)
|
||||||
|
cy.get('[type="submit"]').click();
|
||||||
|
|
||||||
cy.get(`#list [id^=entry]`).last().then(elem => {
|
waitForFetch(numberOfRecords);
|
||||||
const element = elem[0];
|
pauseStream();
|
||||||
const entryId = getEntryId(element.id);
|
|
||||||
// checks the hover on the last entry (the only one in DOM at the beginning)
|
|
||||||
leftOnHoverCheck(entryId, leftSidePath, name);
|
|
||||||
|
|
||||||
cy.get('.w-tc-editor-text').clear();
|
cy.get(`#list [id^=entry]`).last().then(elem => {
|
||||||
// applying the filter with alt+enter or with the button
|
const element = elem[0];
|
||||||
cy.get('.w-tc-editor-text').type(`${name}${applyByEnter ? '{alt+enter}' : ''}`);
|
const entryId = getEntryId(element.id);
|
||||||
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
|
||||||
if (!applyByEnter)
|
|
||||||
cy.get('[type="submit"]').click();
|
|
||||||
|
|
||||||
// only one entry in DOM after filtering, checking all checks on it
|
// only one entry in DOM after filtering, checking all checks on it
|
||||||
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
||||||
leftOnHoverCheck(entryId, leftSidePath, name);
|
leftOnHoverCheck(entryId, leftSidePath, filter);
|
||||||
|
|
||||||
rightTextCheck(rightSidePath, rightSideExpectedText);
|
rightTextCheck(rightSidePath, rightSideExpectedText);
|
||||||
rightOnHoverCheck(rightSidePath, name);
|
rightOnHoverCheck(rightSidePath, filter);
|
||||||
checkRightSideResponseBody();
|
checkRightSideResponseBody();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('[title="Fetch old records"]').click();
|
resizeToHugeMizu();
|
||||||
resizeToHugeMizu();
|
|
||||||
|
|
||||||
// waiting for the entries number to load
|
// checking only 'leftTextCheck' on all entries because the rest of the checks require more time
|
||||||
cy.get('#entries-length', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
cy.get(`#list [id^=entry]`).each(elem => {
|
||||||
|
const element = elem[0];
|
||||||
|
let entryId = getEntryId(element.id);
|
||||||
|
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
||||||
|
});
|
||||||
|
|
||||||
// checking only 'leftTextCheck' on all entries because the rest of the checks require more time
|
// making the other 3 checks on the first X entries (longer time for each check)
|
||||||
cy.get(`#list [id^=entry]`).each(elem => {
|
deeperCheck(leftSidePath, rightSidePath, filter, rightSideExpectedText, entriesForDeeperCheck);
|
||||||
const element = elem[0];
|
|
||||||
let entryId = getEntryId(element.id);
|
|
||||||
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
|
||||||
});
|
|
||||||
|
|
||||||
// making the other 3 checks on the first X entries (longer time for each check)
|
// reloading then waiting for the entries number to load
|
||||||
deeperCheck(leftSidePath, rightSidePath, name, leftSideExpectedText, rightSideExpectedText, entriesForDeeperCheck);
|
resizeToNormalMizu();
|
||||||
|
cy.reload();
|
||||||
// reloading then waiting for the entries number to load
|
waitForFetch(numberOfRecords);
|
||||||
resizeToNormalMizu();
|
pauseStream();
|
||||||
cy.reload();
|
|
||||||
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deeperCheck(leftSidePath, rightSidePath, filterName, leftSideExpectedText, rightSideExpectedText, entriesNumToCheck) {
|
function deeperCheck(leftSidePath, rightSidePath, filterName, rightSideExpectedText, entriesNumToCheck) {
|
||||||
cy.get(`#list [id^=entry]`).each((element, index) => {
|
cy.get(`#list [id^=entry]`).each((element, index) => {
|
||||||
if (index < entriesNumToCheck) {
|
if (index < entriesNumToCheck) {
|
||||||
const entryId = getEntryId(element[0].id);
|
const entryId = getEntryId(element[0].id);
|
||||||
@@ -266,11 +268,12 @@ function checkRightSideResponseBody() {
|
|||||||
const decodedBody = atob(encodedBody);
|
const decodedBody = atob(encodedBody);
|
||||||
const responseBody = JSON.parse(decodedBody);
|
const responseBody = JSON.parse(decodedBody);
|
||||||
|
|
||||||
|
|
||||||
const expectdJsonBody = {
|
const expectdJsonBody = {
|
||||||
args: RegExp({}),
|
args: RegExp({}),
|
||||||
url: RegExp('http://.*/get'),
|
url: RegExp('http://.*/get'),
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": RegExp('[REDACTED]'),
|
"User-Agent": RegExp('client'),
|
||||||
"Accept-Encoding": RegExp('gzip'),
|
"Accept-Encoding": RegExp('gzip'),
|
||||||
"X-Forwarded-Uri": RegExp('/api/v1/namespaces/.*/services/.*/proxy/get')
|
"X-Forwarded-Uri": RegExp('/api/v1/namespaces/.*/services/.*/proxy/get')
|
||||||
}
|
}
|
||||||
@@ -287,16 +290,16 @@ function checkRightSideResponseBody() {
|
|||||||
|
|
||||||
cy.get(`${Cypress.env('bodyJsonClass')} > `).its('length').should('be.gt', 1).then(linesNum => {
|
cy.get(`${Cypress.env('bodyJsonClass')} > `).its('length').should('be.gt', 1).then(linesNum => {
|
||||||
cy.get(`${Cypress.env('bodyJsonClass')} > >`).its('length').should('be.gt', linesNum).then(jsonItemsNum => {
|
cy.get(`${Cypress.env('bodyJsonClass')} > >`).its('length').should('be.gt', linesNum).then(jsonItemsNum => {
|
||||||
checkPrettyAndLineNums(jsonItemsNum, decodedBody);
|
// checkPrettyAndLineNums(decodedBody);
|
||||||
|
|
||||||
clickCheckbox('Line numbers');
|
//clickCheckbox('Line numbers');
|
||||||
checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
//checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
||||||
|
|
||||||
clickCheckbox('Pretty');
|
// clickCheckbox('Pretty');
|
||||||
checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
// checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
||||||
|
//
|
||||||
clickCheckbox('Line numbers');
|
// clickCheckbox('Line numbers');
|
||||||
checkOnlyLineNumberes(jsonItemsNum, decodedBody);
|
// checkOnlyLineNumberes(jsonItemsNum, decodedBody);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -306,7 +309,7 @@ function clickCheckbox(type) {
|
|||||||
cy.contains(`${type}`).prev().children().click();
|
cy.contains(`${type}`).prev().children().click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPrettyAndLineNums(jsonItemsLen, decodedBody) {
|
function checkPrettyAndLineNums(decodedBody) {
|
||||||
decodedBody = decodedBody.replaceAll(' ', '');
|
decodedBody = decodedBody.replaceAll(' ', '');
|
||||||
cy.get(`${Cypress.env('bodyJsonClass')} >`).then(elements => {
|
cy.get(`${Cypress.env('bodyJsonClass')} >`).then(elements => {
|
||||||
const lines = Object.values(elements);
|
const lines = Object.values(elements);
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import {
|
|
||||||
checkThatAllEntriesShown,
|
|
||||||
isValueExistsInElement,
|
|
||||||
resizeToHugeMizu,
|
|
||||||
} from "../testHelpers/TrafficHelper";
|
|
||||||
|
|
||||||
it('Loading Mizu', function () {
|
|
||||||
cy.visit(Cypress.env('testUrl'));
|
|
||||||
});
|
|
||||||
|
|
||||||
checkEntries();
|
|
||||||
|
|
||||||
function checkEntries() {
|
|
||||||
it('checking all entries', function () {
|
|
||||||
checkThatAllEntriesShown();
|
|
||||||
resizeToHugeMizu();
|
|
||||||
|
|
||||||
cy.get('#list [id^=entry]').each(entryElement => {
|
|
||||||
entryElement.click();
|
|
||||||
cy.get('#tbody-Headers').should('be.visible');
|
|
||||||
isValueExistsInElement(false, 'Ignored-User-Agent', '#tbody-Headers');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ func TestRedis(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/Redis.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/Redis.js\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAmqp(t *testing.T) {
|
func TestAmqp(t *testing.T) {
|
||||||
@@ -236,5 +236,5 @@ func TestAmqp(t *testing.T) {
|
|||||||
ch.Close()
|
ch.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/Rabbit.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/Rabbit.js\"")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,3 +54,5 @@ replace github.com/up9inc/mizu/logger v0.0.0 => ../logger
|
|||||||
replace github.com/up9inc/mizu/shared v0.0.0 => ../shared
|
replace github.com/up9inc/mizu/shared v0.0.0 => ../shared
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../tap/dbgctl
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
PREFIX=$HOME/local/bin
|
PREFIX=$HOME/local/bin
|
||||||
VERSION=v1.22.0
|
VERSION=v1.22.0
|
||||||
|
TUNNEL_LOG="tunnel.log"
|
||||||
|
PROXY_LOG="proxy.log"
|
||||||
|
|
||||||
echo "Attempting to install minikube and assorted tools to $PREFIX"
|
echo "Attempting to install minikube and assorted tools to $PREFIX"
|
||||||
|
|
||||||
@@ -11,7 +14,7 @@ if ! [ -x "$(command -v kubectl)" ]; then
|
|||||||
chmod +x kubectl
|
chmod +x kubectl
|
||||||
mv kubectl "$PREFIX"
|
mv kubectl "$PREFIX"
|
||||||
else
|
else
|
||||||
echo "kubetcl is already installed"
|
echo "kubectl is already installed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ -x "$(command -v minikube)" ]; then
|
if ! [ -x "$(command -v minikube)" ]; then
|
||||||
@@ -24,38 +27,42 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting minikube..."
|
echo "Starting minikube..."
|
||||||
minikube start
|
minikube start --cpus 2 --memory 6946
|
||||||
|
|
||||||
echo "Creating mizu tests namespaces"
|
echo "Creating mizu tests namespaces"
|
||||||
kubectl create namespace mizu-tests
|
kubectl create namespace mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
kubectl create namespace mizu-tests2
|
kubectl create namespace mizu-tests2 --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating httpbin deployments"
|
echo "Creating httpbin deployments"
|
||||||
kubectl create deployment httpbin --image=kennethreitz/httpbin -n mizu-tests
|
kubectl create deployment httpbin --image=kennethreitz/httpbin -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
kubectl create deployment httpbin2 --image=kennethreitz/httpbin -n mizu-tests
|
kubectl create deployment httpbin2 --image=kennethreitz/httpbin -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
kubectl create deployment httpbin --image=kennethreitz/httpbin -n mizu-tests2
|
kubectl create deployment httpbin --image=kennethreitz/httpbin -n mizu-tests2 --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating redis deployment"
|
echo "Creating redis deployment"
|
||||||
kubectl create deployment redis --image=redis -n mizu-tests
|
kubectl create deployment redis --image=redis -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating rabbitmq deployment"
|
echo "Creating rabbitmq deployment"
|
||||||
kubectl create deployment rabbitmq --image=rabbitmq -n mizu-tests
|
kubectl create deployment rabbitmq --image=rabbitmq -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating httpbin services"
|
echo "Creating httpbin services"
|
||||||
kubectl expose deployment httpbin --type=NodePort --port=80 -n mizu-tests
|
kubectl expose deployment httpbin --type=NodePort --port=80 -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
kubectl expose deployment httpbin2 --type=NodePort --port=80 -n mizu-tests
|
kubectl expose deployment httpbin2 --type=NodePort --port=80 -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
kubectl expose deployment httpbin --type=NodePort --port=80 -n mizu-tests2
|
kubectl expose deployment httpbin --type=NodePort --port=80 -n mizu-tests2 --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating redis service"
|
echo "Creating redis service"
|
||||||
kubectl expose deployment redis --type=LoadBalancer --port=6379 -n mizu-tests
|
kubectl expose deployment redis --type=LoadBalancer --port=6379 -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
echo "Creating rabbitmq service"
|
echo "Creating rabbitmq service"
|
||||||
kubectl expose deployment rabbitmq --type=LoadBalancer --port=5672 -n mizu-tests
|
kubectl expose deployment rabbitmq --type=LoadBalancer --port=5672 -n mizu-tests --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
# TODO: need to understand how to fail if address already in use
|
||||||
echo "Starting proxy"
|
echo "Starting proxy"
|
||||||
kubectl proxy --port=8080 &
|
rm -f ${PROXY_LOG}
|
||||||
|
kubectl proxy --port=8080 > ${PROXY_LOG} &
|
||||||
|
PID1=$!
|
||||||
|
echo "kubectl proxy process id is ${PID1} and log of proxy in ${PROXY_LOG}"
|
||||||
|
|
||||||
if [[ -z "${CI}" ]]; then
|
if [[ -z "${CI}" ]]; then
|
||||||
echo "Setting env var of mizu ci image"
|
echo "Setting env var of mizu ci image"
|
||||||
@@ -71,5 +78,9 @@ minikube image load "${MIZU_CI_IMAGE}"
|
|||||||
echo "Build cli"
|
echo "Build cli"
|
||||||
cd cli && make build GIT_BRANCH=ci SUFFIX=ci
|
cd cli && make build GIT_BRANCH=ci SUFFIX=ci
|
||||||
|
|
||||||
|
# TODO: need to understand how to fail if password is asked (sudo)
|
||||||
echo "Starting tunnel"
|
echo "Starting tunnel"
|
||||||
minikube tunnel &
|
rm -f ${TUNNEL_LOG}
|
||||||
|
minikube tunnel > ${TUNNEL_LOG} &
|
||||||
|
PID2=$!
|
||||||
|
echo "Minikube tunnel process id is ${PID2} and log of tunnel in ${TUNNEL_LOG}"
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func basicTapTest(t *testing.T, shouldCheckSrcAndDest bool, extraArgs... string)
|
|||||||
expectedPodsStr += fmt.Sprintf("Name:%vNamespace:%v", expectedPods[i].Name, expectedPods[i].Namespace)
|
expectedPodsStr += fmt.Sprintf("Name:%vNamespace:%v", expectedPods[i].Name, expectedPods[i].Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/UiTest.js\" --env entriesCount=%d,arrayDict=%v,shouldCheckSrcAndDest=%v",
|
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/e2e/tests/UiTest.js\" --env entriesCount=%d,arrayDict=%v,shouldCheckSrcAndDest=%v",
|
||||||
entriesCount, expectedPodsStr, shouldCheckSrcAndDest))
|
entriesCount, expectedPodsStr, shouldCheckSrcAndDest))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ func TestTapGuiPort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/GuiPort.js\" --env name=%v,namespace=%v,port=%d",
|
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/e2e/tests/GuiPort.js\" --env name=%v,namespace=%v,port=%d",
|
||||||
"httpbin", "mizu-tests", guiPort))
|
"httpbin", "mizu-tests", guiPort))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ func TestTapAllNamespaces(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/e2e/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
||||||
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ func TestTapMultipleNamespaces(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/e2e/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
||||||
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ func TestTapRegex(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/Regex.js\" --env name=%v,namespace=%v",
|
RunCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/e2e/tests/Regex.js\" --env name=%v,namespace=%v",
|
||||||
expectedPods[0].Name, expectedPods[0].Namespace))
|
expectedPods[0].Name, expectedPods[0].Namespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,6 +343,7 @@ func TestTapRedact(t *testing.T) {
|
|||||||
|
|
||||||
tapNamespace := GetDefaultTapNamespace()
|
tapNamespace := GetDefaultTapNamespace()
|
||||||
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
||||||
|
tapCmdArgs = append(tapCmdArgs, "--redact")
|
||||||
|
|
||||||
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
||||||
t.Logf("running command: %v", tapCmd.String())
|
t.Logf("running command: %v", tapCmd.String())
|
||||||
@@ -375,7 +376,7 @@ func TestTapRedact(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/Redact.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/Redact.js\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTapNoRedact(t *testing.T) {
|
func TestTapNoRedact(t *testing.T) {
|
||||||
@@ -394,8 +395,6 @@ func TestTapNoRedact(t *testing.T) {
|
|||||||
tapNamespace := GetDefaultTapNamespace()
|
tapNamespace := GetDefaultTapNamespace()
|
||||||
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
||||||
|
|
||||||
tapCmdArgs = append(tapCmdArgs, "--no-redact")
|
|
||||||
|
|
||||||
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
||||||
t.Logf("running command: %v", tapCmd.String())
|
t.Logf("running command: %v", tapCmd.String())
|
||||||
|
|
||||||
@@ -427,7 +426,7 @@ func TestTapNoRedact(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/NoRedact.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/NoRedact.js\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTapRegexMasking(t *testing.T) {
|
func TestTapRegexMasking(t *testing.T) {
|
||||||
@@ -446,6 +445,8 @@ func TestTapRegexMasking(t *testing.T) {
|
|||||||
tapNamespace := GetDefaultTapNamespace()
|
tapNamespace := GetDefaultTapNamespace()
|
||||||
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
tapCmdArgs = append(tapCmdArgs, tapNamespace...)
|
||||||
|
|
||||||
|
tapCmdArgs = append(tapCmdArgs, "--redact")
|
||||||
|
|
||||||
tapCmdArgs = append(tapCmdArgs, "-r", "Mizu")
|
tapCmdArgs = append(tapCmdArgs, "-r", "Mizu")
|
||||||
|
|
||||||
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
tapCmd := exec.Command(cliPath, tapCmdArgs...)
|
||||||
@@ -478,7 +479,7 @@ func TestTapRegexMasking(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/RegexMasking.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/RegexMasking.js\"")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +541,7 @@ func TestTapIgnoredUserAgents(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/IgnoredUserAgents.js\"")
|
RunCypressTests(t, "npx cypress run --spec \"cypress/e2e/tests/IgnoredUserAgents.js\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTapDumpLogs(t *testing.T) {
|
func TestTapDumpLogs(t *testing.T) {
|
||||||
|
|||||||
18
agent/go.mod
18
agent/go.mod
@@ -6,8 +6,8 @@ require (
|
|||||||
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
||||||
github.com/chanced/openapi v0.0.8
|
github.com/chanced/openapi v0.0.8
|
||||||
github.com/djherbis/atime v1.1.0
|
github.com/djherbis/atime v1.1.0
|
||||||
github.com/elastic/go-elasticsearch/v7 v7.17.0
|
|
||||||
github.com/getkin/kin-openapi v0.89.0
|
github.com/getkin/kin-openapi v0.89.0
|
||||||
|
github.com/gin-contrib/pprof v1.3.0
|
||||||
github.com/gin-contrib/static v0.0.1
|
github.com/gin-contrib/static v0.0.1
|
||||||
github.com/gin-gonic/gin v1.7.7
|
github.com/gin-gonic/gin v1.7.7
|
||||||
github.com/go-playground/locales v0.14.0
|
github.com/go-playground/locales v0.14.0
|
||||||
@@ -20,11 +20,12 @@ require (
|
|||||||
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/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607
|
github.com/up9inc/basenine/client/go v0.0.0-20220612112747-3b28eeac9c51
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger v0.0.0
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap 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
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
||||||
github.com/up9inc/mizu/tap/extensions/amqp v0.0.0
|
github.com/up9inc/mizu/tap/extensions/amqp v0.0.0
|
||||||
github.com/up9inc/mizu/tap/extensions/http v0.0.0
|
github.com/up9inc/mizu/tap/extensions/http v0.0.0
|
||||||
github.com/up9inc/mizu/tap/extensions/kafka v0.0.0
|
github.com/up9inc/mizu/tap/extensions/kafka v0.0.0
|
||||||
@@ -46,12 +47,13 @@ require (
|
|||||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||||
|
github.com/Masterminds/semver v1.5.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/beevik/etree v1.1.0 // indirect
|
github.com/beevik/etree v1.1.0 // 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.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // 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
|
||||||
@@ -61,6 +63,7 @@ require (
|
|||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.2 // indirect
|
github.com/go-logr/logr v1.2.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
github.com/go-openapi/swag v0.21.1 // indirect
|
github.com/go-openapi/swag v0.21.1 // indirect
|
||||||
@@ -76,11 +79,13 @@ require (
|
|||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
|
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
@@ -101,15 +106,20 @@ require (
|
|||||||
github.com/russross/blackfriday v1.6.0 // indirect
|
github.com/russross/blackfriday v1.6.0 // indirect
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect
|
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect
|
||||||
github.com/segmentio/kafka-go v0.4.27 // indirect
|
github.com/segmentio/kafka-go v0.4.27 // indirect
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||||
github.com/spf13/cobra v1.3.0 // indirect
|
github.com/spf13/cobra v1.3.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/struCoder/pidusage v0.2.1 // indirect
|
||||||
github.com/tidwall/gjson v1.14.0 // indirect
|
github.com/tidwall/gjson v1.14.0 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
github.com/tidwall/sjson v1.2.4 // indirect
|
github.com/tidwall/sjson v1.2.4 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.6 // indirect
|
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
github.com/xlab/treeprint v1.1.0 // indirect
|
github.com/xlab/treeprint v1.1.0 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b // indirect
|
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
@@ -151,3 +161,5 @@ replace github.com/up9inc/mizu/tap/extensions/http v0.0.0 => ../tap/extensions/h
|
|||||||
replace github.com/up9inc/mizu/tap/extensions/kafka v0.0.0 => ../tap/extensions/kafka
|
replace github.com/up9inc/mizu/tap/extensions/kafka v0.0.0 => ../tap/extensions/kafka
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/extensions/redis v0.0.0 => ../tap/extensions/redis
|
replace github.com/up9inc/mizu/tap/extensions/redis v0.0.0 => ../tap/extensions/redis
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../tap/dbgctl
|
||||||
|
|||||||
32
agent/go.sum
32
agent/go.sum
@@ -77,6 +77,8 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
|
|||||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||||
@@ -126,8 +128,8 @@ github.com/chanced/openapi v0.0.8/go.mod h1:SxE2VMLPw+T7Vq8nwbVVhDF2PigvRF4n5Xyq
|
|||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
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/cilium/ebpf v0.8.0 h1:2V6KSg3FRADVU2BMIRemZ0hV+9OM+aAHhZDjQyjJTAs=
|
github.com/cilium/ebpf v0.8.1 h1:bLSSEbBLqGPXxls55pGr5qWZaTqcmfDJHhou7t254ao=
|
||||||
github.com/cilium/ebpf v0.8.0/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
|
github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
|
||||||
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@@ -166,8 +168,6 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
|||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/elastic/go-elasticsearch/v7 v7.17.0 h1:0fcSh4qeC/i1+7QU1KXpmq2iUAdMk4l0/vmbtW1+KJM=
|
|
||||||
github.com/elastic/go-elasticsearch/v7 v7.17.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
|
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
@@ -215,10 +215,13 @@ github.com/getkin/kin-openapi v0.89.0 h1:p4nagHchUKGn85z/f+pse4aSh50nIBOYjOhMIku
|
|||||||
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
||||||
|
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U=
|
github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U=
|
||||||
github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs=
|
github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs=
|
||||||
|
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||||
@@ -240,6 +243,8 @@ github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
|
|||||||
github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs=
|
github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
@@ -405,6 +410,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
|||||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||||
@@ -451,6 +457,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||||||
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
||||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e h1:6J5obSn9umEThiYzWzndcPOZR0Qj/sVCZpH6V1G7yNE=
|
||||||
|
github.com/knightsc/gapstone v0.0.0-20211014144438-5e0e64002a6e/go.mod h1:1K5hEzsMBLTPdRJKEHqBFJ8Zt2VRqDhomcQ11KH0WW4=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
@@ -619,6 +627,8 @@ github.com/segmentio/kafka-go v0.4.27 h1:sIhEozeL/TLN2mZ5dkG462vcGEWYKS+u31sXPjK
|
|||||||
github.com/segmentio/kafka-go v0.4.27/go.mod h1:XzMcoMjSzDGHcIwpWUI7GB43iKZ2fTVmryPSGLf/MPg=
|
github.com/segmentio/kafka-go v0.4.27/go.mod h1:XzMcoMjSzDGHcIwpWUI7GB43iKZ2fTVmryPSGLf/MPg=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
@@ -660,6 +670,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/struCoder/pidusage v0.2.1 h1:dFiEgUDkubeIj0XA1NpQ6+8LQmKrLi7NiIQl86E6BoY=
|
||||||
|
github.com/struCoder/pidusage v0.2.1/go.mod h1:bewtP2KUA1TBUyza5+/PCpSQ6sc/H6jJbIKAzqW86BA=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/gjson v1.12.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.12.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
@@ -673,6 +685,10 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso
|
|||||||
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
||||||
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
|
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
|
||||||
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
|
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||||
|
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||||
|
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||||
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=
|
||||||
@@ -682,8 +698,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-20220419100955-e2ca51087607 h1:UqxUSkOYOmsLZWQtMSk02ttnhdRwBRLOLt2aDiS9tEk=
|
github.com/up9inc/basenine/client/go v0.0.0-20220612112747-3b28eeac9c51 h1:6op+PUYmTlxze3V3f30lWKix3sWqv1M9rvRhyaxbsdQ=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220612112747-3b28eeac9c51/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=
|
||||||
@@ -703,6 +719,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
@@ -895,6 +913,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -963,6 +982,7 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
|
golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
|
||||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|||||||
@@ -14,17 +14,16 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/pprof"
|
||||||
"github.com/gin-contrib/static"
|
"github.com/gin-contrib/static"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/up9inc/mizu/agent/pkg/dependency"
|
"github.com/up9inc/mizu/agent/pkg/dependency"
|
||||||
"github.com/up9inc/mizu/agent/pkg/elastic"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/entries"
|
"github.com/up9inc/mizu/agent/pkg/entries"
|
||||||
"github.com/up9inc/mizu/agent/pkg/middlewares"
|
"github.com/up9inc/mizu/agent/pkg/middlewares"
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
"github.com/up9inc/mizu/agent/pkg/oas"
|
"github.com/up9inc/mizu/agent/pkg/oas"
|
||||||
"github.com/up9inc/mizu/agent/pkg/routes"
|
"github.com/up9inc/mizu/agent/pkg/routes"
|
||||||
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
||||||
"github.com/up9inc/mizu/agent/pkg/up9"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/utils"
|
"github.com/up9inc/mizu/agent/pkg/utils"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/api"
|
"github.com/up9inc/mizu/agent/pkg/api"
|
||||||
@@ -37,6 +36,7 @@ import (
|
|||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
"github.com/up9inc/mizu/tap"
|
"github.com/up9inc/mizu/tap"
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
var tapperMode = flag.Bool("tap", false, "Run in tapper mode without API")
|
var tapperMode = flag.Bool("tap", false, "Run in tapper mode without API")
|
||||||
@@ -46,6 +46,7 @@ var apiServerAddress = flag.String("api-server-address", "", "Address of mizu AP
|
|||||||
var namespace = flag.String("namespace", "", "Resolve IPs if they belong to resources in this namespace (default is all)")
|
var namespace = flag.String("namespace", "", "Resolve IPs if they belong to resources in this namespace (default is all)")
|
||||||
var harsReaderMode = flag.Bool("hars-read", false, "Run in hars-read mode")
|
var harsReaderMode = flag.Bool("hars-read", false, "Run in hars-read mode")
|
||||||
var harsDir = flag.String("hars-dir", "", "Directory to read hars from")
|
var harsDir = flag.String("hars-dir", "", "Directory to read hars from")
|
||||||
|
var profiler = flag.Bool("profiler", false, "Run pprof server")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
socketConnectionRetries = 30
|
socketConnectionRetries = 30
|
||||||
@@ -62,7 +63,7 @@ func main() {
|
|||||||
app.LoadExtensions()
|
app.LoadExtensions()
|
||||||
|
|
||||||
if !*tapperMode && !*apiServerMode && !*standaloneMode && !*harsReaderMode {
|
if !*tapperMode && !*apiServerMode && !*standaloneMode && !*harsReaderMode {
|
||||||
panic("One of the flags --tap, --api or --standalone or --hars-read must be provided")
|
panic("One of the flags --tap, --api-server, --standalone or --hars-read must be provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *standaloneMode {
|
if *standaloneMode {
|
||||||
@@ -70,7 +71,14 @@ func main() {
|
|||||||
} else if *tapperMode {
|
} else if *tapperMode {
|
||||||
runInTapperMode()
|
runInTapperMode()
|
||||||
} else if *apiServerMode {
|
} else if *apiServerMode {
|
||||||
utils.StartServer(runInApiServerMode(*namespace))
|
ginApp := runInApiServerMode(*namespace)
|
||||||
|
|
||||||
|
if *profiler {
|
||||||
|
pprof.Register(ginApp)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.StartServer(ginApp)
|
||||||
|
|
||||||
} else if *harsReaderMode {
|
} else if *harsReaderMode {
|
||||||
runInHarReaderMode()
|
runInHarReaderMode()
|
||||||
}
|
}
|
||||||
@@ -83,9 +91,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func hostApi(socketHarOutputChannel chan<- *tapApi.OutputChannelItem) *gin.Engine {
|
func hostApi(socketHarOutputChannel chan<- *tapApi.OutputChannelItem) *gin.Engine {
|
||||||
app := gin.Default()
|
ginApp := gin.Default()
|
||||||
|
|
||||||
app.GET("/echo", func(c *gin.Context) {
|
ginApp.GET("/echo", func(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, "Here is Mizu agent")
|
c.JSON(http.StatusOK, "Here is Mizu agent")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -93,7 +101,7 @@ func hostApi(socketHarOutputChannel chan<- *tapApi.OutputChannelItem) *gin.Engin
|
|||||||
SocketOutChannel: socketHarOutputChannel,
|
SocketOutChannel: socketHarOutputChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Use(disableRootStaticCache())
|
ginApp.Use(disableRootStaticCache())
|
||||||
|
|
||||||
staticFolder := "./site"
|
staticFolder := "./site"
|
||||||
indexStaticFile := staticFolder + "/index.html"
|
indexStaticFile := staticFolder + "/index.html"
|
||||||
@@ -101,30 +109,30 @@ func hostApi(socketHarOutputChannel chan<- *tapApi.OutputChannelItem) *gin.Engin
|
|||||||
logger.Log.Errorf("Error setting ui flags, err: %v", err)
|
logger.Log.Errorf("Error setting ui flags, err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Use(static.ServeRoot("/", staticFolder))
|
ginApp.Use(static.ServeRoot("/", staticFolder))
|
||||||
app.NoRoute(func(c *gin.Context) {
|
ginApp.NoRoute(func(c *gin.Context) {
|
||||||
c.File(indexStaticFile)
|
c.File(indexStaticFile)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.Use(middlewares.CORSMiddleware()) // This has to be called after the static middleware, does not work if its called before
|
ginApp.Use(middlewares.CORSMiddleware()) // This has to be called after the static middleware, does not work if it's called before
|
||||||
|
|
||||||
api.WebSocketRoutes(app, &eventHandlers)
|
api.WebSocketRoutes(ginApp, &eventHandlers)
|
||||||
|
|
||||||
if config.Config.OAS {
|
if config.Config.OAS {
|
||||||
routes.OASRoutes(app)
|
routes.OASRoutes(ginApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Config.ServiceMap {
|
if config.Config.ServiceMap {
|
||||||
routes.ServiceMapRoutes(app)
|
routes.ServiceMapRoutes(ginApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
routes.QueryRoutes(app)
|
routes.QueryRoutes(ginApp)
|
||||||
routes.EntriesRoutes(app)
|
routes.EntriesRoutes(ginApp)
|
||||||
routes.MetadataRoutes(app)
|
routes.MetadataRoutes(ginApp)
|
||||||
routes.StatusRoutes(app)
|
routes.StatusRoutes(ginApp)
|
||||||
routes.DbRoutes(app)
|
routes.DbRoutes(ginApp)
|
||||||
|
|
||||||
return app
|
return ginApp
|
||||||
}
|
}
|
||||||
|
|
||||||
func runInApiServerMode(namespace string) *gin.Engine {
|
func runInApiServerMode(namespace string) *gin.Engine {
|
||||||
@@ -136,13 +144,6 @@ func runInApiServerMode(namespace string) *gin.Engine {
|
|||||||
|
|
||||||
enableExpFeatureIfNeeded()
|
enableExpFeatureIfNeeded()
|
||||||
|
|
||||||
syncEntriesConfig := getSyncEntriesConfig()
|
|
||||||
if syncEntriesConfig != nil {
|
|
||||||
if err := up9.SyncEntries(syncEntriesConfig); err != nil {
|
|
||||||
logger.Log.Error("Error syncing entries, err: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostApi(app.GetEntryInputChannel())
|
return hostApi(app.GetEntryInputChannel())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +154,9 @@ func runInTapperMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostMode := os.Getenv(shared.HostModeEnvVar) == "1"
|
hostMode := os.Getenv(shared.HostModeEnvVar) == "1"
|
||||||
tapOpts := &tap.TapOpts{HostMode: hostMode}
|
tapOpts := &tap.TapOpts{
|
||||||
|
HostMode: hostMode,
|
||||||
|
}
|
||||||
|
|
||||||
filteredOutputItemsChannel := make(chan *tapApi.OutputChannelItem)
|
filteredOutputItemsChannel := make(chan *tapApi.OutputChannelItem)
|
||||||
|
|
||||||
@@ -199,28 +202,12 @@ func runInHarReaderMode() {
|
|||||||
func enableExpFeatureIfNeeded() {
|
func enableExpFeatureIfNeeded() {
|
||||||
if config.Config.OAS {
|
if config.Config.OAS {
|
||||||
oasGenerator := dependency.GetInstance(dependency.OasGeneratorDependency).(oas.OasGenerator)
|
oasGenerator := dependency.GetInstance(dependency.OasGeneratorDependency).(oas.OasGenerator)
|
||||||
oasGenerator.Start(nil)
|
oasGenerator.Start()
|
||||||
}
|
}
|
||||||
if config.Config.ServiceMap {
|
if config.Config.ServiceMap {
|
||||||
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMap)
|
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMap)
|
||||||
serviceMapGenerator.Enable()
|
serviceMapGenerator.Enable()
|
||||||
}
|
}
|
||||||
elastic.GetInstance().Configure(config.Config.Elastic)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSyncEntriesConfig() *shared.SyncEntriesConfig {
|
|
||||||
syncEntriesConfigJson := os.Getenv(shared.SyncEntriesConfigEnvVar)
|
|
||||||
if syncEntriesConfigJson == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var syncEntriesConfig = &shared.SyncEntriesConfig{}
|
|
||||||
err := json.Unmarshal([]byte(syncEntriesConfigJson), syncEntriesConfig)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("env var %s's value of %s is invalid! json must match the shared.SyncEntriesConfig struct, err: %v", shared.SyncEntriesConfigEnvVar, syncEntriesConfigJson, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return syncEntriesConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func disableRootStaticCache() gin.HandlerFunc {
|
func disableRootStaticCache() gin.HandlerFunc {
|
||||||
@@ -283,6 +270,10 @@ func pipeTapChannelToSocket(connection *websocket.Conn, messageDataChannel <-cha
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dbgctl.MizuTapperDisableSending {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: This is where the `*tapApi.OutputChannelItem` leaves the code
|
// NOTE: This is where the `*tapApi.OutputChannelItem` leaves the code
|
||||||
// and goes into the intermediate WebSocket.
|
// and goes into the intermediate WebSocket.
|
||||||
err = connection.WriteMessage(websocket.TextMessage, marshaledData)
|
err = connection.WriteMessage(websocket.TextMessage, marshaledData)
|
||||||
@@ -373,6 +364,7 @@ func handleIncomingMessageAsTapper(socketConnection *websocket.Conn) {
|
|||||||
func initializeDependencies() {
|
func initializeDependencies() {
|
||||||
dependency.RegisterGenerator(dependency.ServiceMapGeneratorDependency, func() interface{} { return servicemap.GetDefaultServiceMapInstance() })
|
dependency.RegisterGenerator(dependency.ServiceMapGeneratorDependency, func() interface{} { return servicemap.GetDefaultServiceMapInstance() })
|
||||||
dependency.RegisterGenerator(dependency.OasGeneratorDependency, func() interface{} { return oas.GetDefaultOasGeneratorInstance() })
|
dependency.RegisterGenerator(dependency.OasGeneratorDependency, func() interface{} { return oas.GetDefaultOasGeneratorInstance() })
|
||||||
|
dependency.RegisterGenerator(dependency.EntriesInserter, func() interface{} { return api.GetBasenineEntryInserterInstance() })
|
||||||
dependency.RegisterGenerator(dependency.EntriesProvider, func() interface{} { return &entries.BasenineEntriesProvider{} })
|
dependency.RegisterGenerator(dependency.EntriesProvider, func() interface{} { return &entries.BasenineEntriesProvider{} })
|
||||||
dependency.RegisterGenerator(dependency.EntriesSocketStreamer, func() interface{} { return &api.BasenineEntryStreamer{} })
|
dependency.RegisterGenerator(dependency.EntriesSocketStreamer, func() interface{} { return &api.BasenineEntryStreamer{} })
|
||||||
dependency.RegisterGenerator(dependency.EntryStreamerSocketConnector, func() interface{} { return &api.DefaultEntryStreamerSocketConnector{} })
|
dependency.RegisterGenerator(dependency.EntryStreamerSocketConnector, func() interface{} { return &api.DefaultEntryStreamerSocketConnector{} })
|
||||||
|
|||||||
@@ -5,20 +5,19 @@ import (
|
|||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntryStreamerSocketConnector interface {
|
type EntryStreamerSocketConnector interface {
|
||||||
SendEntry(socketId int, entry *tapApi.Entry, params *WebSocketParams)
|
SendEntry(socketId int, entry *tapApi.Entry, params *WebSocketParams) error
|
||||||
SendMetadata(socketId int, metadata *basenine.Metadata)
|
SendMetadata(socketId int, metadata *basenine.Metadata) error
|
||||||
SendToastError(socketId int, err error)
|
SendToastError(socketId int, err error) error
|
||||||
CleanupSocket(socketId int)
|
CleanupSocket(socketId int)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultEntryStreamerSocketConnector struct{}
|
type DefaultEntryStreamerSocketConnector struct{}
|
||||||
|
|
||||||
func (e *DefaultEntryStreamerSocketConnector) SendEntry(socketId int, entry *tapApi.Entry, params *WebSocketParams) {
|
func (e *DefaultEntryStreamerSocketConnector) SendEntry(socketId int, entry *tapApi.Entry, params *WebSocketParams) error {
|
||||||
var message []byte
|
var message []byte
|
||||||
if params.EnableFullEntries {
|
if params.EnableFullEntries {
|
||||||
message, _ = models.CreateFullEntryWebSocketMessage(entry)
|
message, _ = models.CreateFullEntryWebSocketMessage(entry)
|
||||||
@@ -29,26 +28,32 @@ func (e *DefaultEntryStreamerSocketConnector) SendEntry(socketId int, entry *tap
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := SendToSocket(socketId, message); err != nil {
|
if err := SendToSocket(socketId, message); err != nil {
|
||||||
logger.Log.Error(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *DefaultEntryStreamerSocketConnector) SendMetadata(socketId int, metadata *basenine.Metadata) {
|
func (e *DefaultEntryStreamerSocketConnector) SendMetadata(socketId int, metadata *basenine.Metadata) error {
|
||||||
metadataBytes, _ := models.CreateWebsocketQueryMetadataMessage(metadata)
|
metadataBytes, _ := models.CreateWebsocketQueryMetadataMessage(metadata)
|
||||||
if err := SendToSocket(socketId, metadataBytes); err != nil {
|
if err := SendToSocket(socketId, metadataBytes); err != nil {
|
||||||
logger.Log.Error(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *DefaultEntryStreamerSocketConnector) SendToastError(socketId int, err error) {
|
func (e *DefaultEntryStreamerSocketConnector) SendToastError(socketId int, err error) error {
|
||||||
toastBytes, _ := models.CreateWebsocketToastMessage(&models.ToastMessage{
|
toastBytes, _ := models.CreateWebsocketToastMessage(&models.ToastMessage{
|
||||||
Type: "error",
|
Type: "error",
|
||||||
AutoClose: 5000,
|
AutoClose: 5000,
|
||||||
Text: fmt.Sprintf("Syntax error: %s", err.Error()),
|
Text: fmt.Sprintf("Syntax error: %s", err.Error()),
|
||||||
})
|
})
|
||||||
if err := SendToSocket(socketId, toastBytes); err != nil {
|
if err := SendToSocket(socketId, toastBytes); err != nil {
|
||||||
logger.Log.Error(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *DefaultEntryStreamerSocketConnector) CleanupSocket(socketId int) {
|
func (e *DefaultEntryStreamerSocketConnector) CleanupSocket(socketId int) {
|
||||||
|
|||||||
@@ -14,21 +14,18 @@ import (
|
|||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/dependency"
|
"github.com/up9inc/mizu/agent/pkg/dependency"
|
||||||
"github.com/up9inc/mizu/agent/pkg/elastic"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
"github.com/up9inc/mizu/agent/pkg/har"
|
||||||
"github.com/up9inc/mizu/agent/pkg/holder"
|
"github.com/up9inc/mizu/agent/pkg/holder"
|
||||||
"github.com/up9inc/mizu/agent/pkg/providers"
|
"github.com/up9inc/mizu/agent/pkg/providers"
|
||||||
|
|
||||||
|
"github.com/up9inc/mizu/agent/pkg/oas"
|
||||||
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/resolver"
|
"github.com/up9inc/mizu/agent/pkg/resolver"
|
||||||
"github.com/up9inc/mizu/agent/pkg/utils"
|
"github.com/up9inc/mizu/agent/pkg/utils"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var k8sResolver *resolver.Resolver
|
var k8sResolver *resolver.Resolver
|
||||||
@@ -103,20 +100,6 @@ 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)
|
|
||||||
if err != nil {
|
|
||||||
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 {
|
|
||||||
logger.Log.Errorf("Insert mode call failed: %v", err)
|
|
||||||
connection.Close()
|
|
||||||
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
|
||||||
goto BasenineReconnect
|
|
||||||
}
|
|
||||||
|
|
||||||
disableOASValidation := false
|
disableOASValidation := false
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
doc, contractContent, router, err := loadOAS(ctx)
|
doc, contractContent, router, err := loadOAS(ctx)
|
||||||
@@ -163,17 +146,16 @@ BasenineReconnect:
|
|||||||
|
|
||||||
providers.EntryAdded(len(data))
|
providers.EntryAdded(len(data))
|
||||||
|
|
||||||
if err = connection.SendText(string(data)); err != nil {
|
entryInserter := dependency.GetInstance(dependency.EntriesInserter).(EntryInserter)
|
||||||
logger.Log.Errorf("An error occured while inserting a new record to database: %v", err)
|
if err := entryInserter.Insert(mizuEntry); err != nil {
|
||||||
connection.Close()
|
logger.Log.Errorf("Error inserting entry, err: %v", err)
|
||||||
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
|
||||||
goto BasenineReconnect
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMapSink)
|
serviceMapGenerator := dependency.GetInstance(dependency.ServiceMapGeneratorDependency).(servicemap.ServiceMapSink)
|
||||||
serviceMapGenerator.NewTCPEntry(mizuEntry.Source, mizuEntry.Destination, &item.Protocol)
|
serviceMapGenerator.NewTCPEntry(mizuEntry.Source, mizuEntry.Destination, &item.Protocol)
|
||||||
|
|
||||||
elastic.GetInstance().PushEntry(mizuEntry)
|
oasGenerator := dependency.GetInstance(dependency.OasGeneratorDependency).(oas.OasGeneratorSink)
|
||||||
|
oasGenerator.HandleEntry(mizuEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
71
agent/pkg/api/socket_data_inserter.go
Normal file
71
agent/pkg/api/socket_data_inserter.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
|
"github.com/up9inc/mizu/logger"
|
||||||
|
"github.com/up9inc/mizu/shared"
|
||||||
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EntryInserter interface {
|
||||||
|
Insert(entry *api.Entry) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasenineEntryInserter struct {
|
||||||
|
connection *basenine.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
var instance *BasenineEntryInserter
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
func GetBasenineEntryInserterInstance() *BasenineEntryInserter {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &BasenineEntryInserter{}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BasenineEntryInserter) Insert(entry *api.Entry) error {
|
||||||
|
if e.connection == nil {
|
||||||
|
e.connection = initializeConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(entry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error marshling entry, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := e.connection.SendText(string(data)); err != nil {
|
||||||
|
e.connection.Close()
|
||||||
|
e.connection = nil
|
||||||
|
|
||||||
|
return fmt.Errorf("error sending text to database, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeConnection() *basenine.Connection{
|
||||||
|
for {
|
||||||
|
connection, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Errorf("Can't establish a new connection to Basenine server: %v", err)
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = connection.InsertMode(); err != nil {
|
||||||
|
logger.Log.Errorf("Insert mode call failed: %v", err)
|
||||||
|
connection.Close()
|
||||||
|
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
"github.com/up9inc/mizu/agent/pkg/dependency"
|
"github.com/up9inc/mizu/agent/pkg/dependency"
|
||||||
@@ -33,9 +34,18 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
meta := make(chan []byte)
|
meta := make(chan []byte)
|
||||||
|
|
||||||
query := params.Query
|
query := params.Query
|
||||||
err = basenine.Validate(shared.BasenineHost, shared.BaseninePort, query)
|
if err = basenine.Validate(shared.BasenineHost, shared.BaseninePort, query); err != nil {
|
||||||
|
if err := entryStreamerSocketConnector.SendToastError(socketId, err); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entryStreamerSocketConnector.CleanupSocket(socketId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
leftOff, err := e.fetch(socketId, params, entryStreamerSocketConnector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
entryStreamerSocketConnector.SendToastError(socketId, err)
|
logger.Log.Errorf("Fetch error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDataChannel := func(c *basenine.Connection, data chan []byte) {
|
handleDataChannel := func(c *basenine.Connection, data chan []byte) {
|
||||||
@@ -47,13 +57,15 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
}
|
}
|
||||||
|
|
||||||
var entry *tapApi.Entry
|
var entry *tapApi.Entry
|
||||||
err = json.Unmarshal(bytes, &entry)
|
if err = json.Unmarshal(bytes, &entry); err != nil {
|
||||||
if err != nil {
|
logger.Log.Debugf("Error unmarshalling entry: %v", err)
|
||||||
logger.Log.Debugf("Error unmarshalling entry: %v", err.Error())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entryStreamerSocketConnector.SendEntry(socketId, entry, params)
|
if err := entryStreamerSocketConnector.SendEntry(socketId, entry, params); err != nil {
|
||||||
|
logger.Log.Errorf("Error sending entry to socket, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,20 +78,22 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metadata *basenine.Metadata
|
var metadata *basenine.Metadata
|
||||||
err = json.Unmarshal(bytes, &metadata)
|
if err = json.Unmarshal(bytes, &metadata); err != nil {
|
||||||
if err != nil {
|
logger.Log.Debugf("Error unmarshalling metadata: %v", err)
|
||||||
logger.Log.Debugf("Error unmarshalling metadata: %v", err.Error())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entryStreamerSocketConnector.SendMetadata(socketId, metadata)
|
if err := entryStreamerSocketConnector.SendMetadata(socketId, metadata); err != nil {
|
||||||
|
logger.Log.Errorf("Error sending metadata to socket, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go handleDataChannel(connection, data)
|
go handleDataChannel(connection, data)
|
||||||
go handleMetaChannel(connection, meta)
|
go handleMetaChannel(connection, meta)
|
||||||
|
|
||||||
if err = connection.Query(query, data, meta); err != nil {
|
if err = connection.Query(leftOff, query, data, meta); err != nil {
|
||||||
logger.Log.Errorf("Query mode call failed: %v", err)
|
logger.Log.Errorf("Query mode call failed: %v", err)
|
||||||
entryStreamerSocketConnector.CleanupSocket(socketId)
|
entryStreamerSocketConnector.CleanupSocket(socketId)
|
||||||
return err
|
return err
|
||||||
@@ -94,3 +108,64 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverses a []byte slice.
|
||||||
|
func (e *BasenineEntryStreamer) fetch(socketId int, params *WebSocketParams, connector EntryStreamerSocketConnector) (leftOff string, err error) {
|
||||||
|
if params.Fetch <= 0 {
|
||||||
|
leftOff = params.LeftOff
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var data [][]byte
|
||||||
|
var firstMeta []byte
|
||||||
|
var lastMeta []byte
|
||||||
|
data, firstMeta, lastMeta, err = basenine.Fetch(
|
||||||
|
shared.BasenineHost,
|
||||||
|
shared.BaseninePort,
|
||||||
|
params.LeftOff,
|
||||||
|
-1,
|
||||||
|
params.Query,
|
||||||
|
params.Fetch,
|
||||||
|
time.Duration(params.TimeoutMs)*time.Millisecond,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstMetadata *basenine.Metadata
|
||||||
|
if err = json.Unmarshal(firstMeta, &firstMetadata); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
leftOff = firstMetadata.LeftOff
|
||||||
|
|
||||||
|
var lastMetadata *basenine.Metadata
|
||||||
|
if err = json.Unmarshal(lastMeta, &lastMetadata); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = connector.SendMetadata(socketId, lastMetadata); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data = e.reverseBytesSlice(data)
|
||||||
|
for _, row := range data {
|
||||||
|
var entry *tapApi.Entry
|
||||||
|
if err = json.Unmarshal(row, &entry); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = connector.SendEntry(socketId, entry, params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverses a []byte slice.
|
||||||
|
func (e *BasenineEntryStreamer) reverseBytesSlice(arr [][]byte) (newArr [][]byte) {
|
||||||
|
for i := len(arr) - 1; i >= 0; i-- {
|
||||||
|
newArr = append(newArr, arr[i])
|
||||||
|
}
|
||||||
|
return newArr
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,8 +34,11 @@ type SocketConnection struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WebSocketParams struct {
|
type WebSocketParams struct {
|
||||||
|
LeftOff string `json:"leftOff"`
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
EnableFullEntries bool `json:"enableFullEntries"`
|
EnableFullEntries bool `json:"enableFullEntries"`
|
||||||
|
Fetch int `json:"fetch"`
|
||||||
|
TimeoutMs int `json:"timeoutMs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
"github.com/up9inc/mizu/agent/pkg/providers/tappedPods"
|
"github.com/up9inc/mizu/agent/pkg/providers/tappedPods"
|
||||||
"github.com/up9inc/mizu/agent/pkg/providers/tappers"
|
"github.com/up9inc/mizu/agent/pkg/providers/tappers"
|
||||||
"github.com/up9inc/mizu/agent/pkg/up9"
|
|
||||||
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
@@ -31,10 +30,6 @@ type RoutesEventHandlers struct {
|
|||||||
SocketOutChannel chan<- *tapApi.OutputChannelItem
|
SocketOutChannel chan<- *tapApi.OutputChannelItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
go up9.UpdateAnalyzeStatus(BroadcastToBrowserClients)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *RoutesEventHandlers) WebSocketConnect(_ *gin.Context, socketId int, isTapper bool) {
|
func (h *RoutesEventHandlers) WebSocketConnect(_ *gin.Context, socketId int, isTapper bool) {
|
||||||
if isTapper {
|
if isTapper {
|
||||||
logger.Log.Infof("Websocket event - Tapper connected, socket ID: %d", socketId)
|
logger.Log.Infof("Websocket event - Tapper connected, socket ID: %d", socketId)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/up9inc/mizu/agent/pkg/api"
|
"github.com/up9inc/mizu/agent/pkg/api"
|
||||||
"github.com/up9inc/mizu/agent/pkg/utils"
|
"github.com/up9inc/mizu/agent/pkg/utils"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
amqpExt "github.com/up9inc/mizu/tap/extensions/amqp"
|
amqpExt "github.com/up9inc/mizu/tap/extensions/amqp"
|
||||||
httpExt "github.com/up9inc/mizu/tap/extensions/http"
|
httpExt "github.com/up9inc/mizu/tap/extensions/http"
|
||||||
@@ -24,36 +25,38 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func LoadExtensions() {
|
func LoadExtensions() {
|
||||||
Extensions = make([]*tapApi.Extension, 4)
|
Extensions = make([]*tapApi.Extension, 0)
|
||||||
ExtensionsMap = make(map[string]*tapApi.Extension)
|
ExtensionsMap = make(map[string]*tapApi.Extension)
|
||||||
|
|
||||||
extensionAmqp := &tapApi.Extension{}
|
|
||||||
dissectorAmqp := amqpExt.NewDissector()
|
|
||||||
dissectorAmqp.Register(extensionAmqp)
|
|
||||||
extensionAmqp.Dissector = dissectorAmqp
|
|
||||||
Extensions[0] = extensionAmqp
|
|
||||||
ExtensionsMap[extensionAmqp.Protocol.Name] = extensionAmqp
|
|
||||||
|
|
||||||
extensionHttp := &tapApi.Extension{}
|
extensionHttp := &tapApi.Extension{}
|
||||||
dissectorHttp := httpExt.NewDissector()
|
dissectorHttp := httpExt.NewDissector()
|
||||||
dissectorHttp.Register(extensionHttp)
|
dissectorHttp.Register(extensionHttp)
|
||||||
extensionHttp.Dissector = dissectorHttp
|
extensionHttp.Dissector = dissectorHttp
|
||||||
Extensions[1] = extensionHttp
|
Extensions = append(Extensions, extensionHttp)
|
||||||
ExtensionsMap[extensionHttp.Protocol.Name] = extensionHttp
|
ExtensionsMap[extensionHttp.Protocol.Name] = extensionHttp
|
||||||
|
|
||||||
extensionKafka := &tapApi.Extension{}
|
if !dbgctl.MizuTapperDisableNonHttpExtensions {
|
||||||
dissectorKafka := kafkaExt.NewDissector()
|
extensionAmqp := &tapApi.Extension{}
|
||||||
dissectorKafka.Register(extensionKafka)
|
dissectorAmqp := amqpExt.NewDissector()
|
||||||
extensionKafka.Dissector = dissectorKafka
|
dissectorAmqp.Register(extensionAmqp)
|
||||||
Extensions[2] = extensionKafka
|
extensionAmqp.Dissector = dissectorAmqp
|
||||||
ExtensionsMap[extensionKafka.Protocol.Name] = extensionKafka
|
Extensions = append(Extensions, extensionAmqp)
|
||||||
|
ExtensionsMap[extensionAmqp.Protocol.Name] = extensionAmqp
|
||||||
|
|
||||||
extensionRedis := &tapApi.Extension{}
|
extensionKafka := &tapApi.Extension{}
|
||||||
dissectorRedis := redisExt.NewDissector()
|
dissectorKafka := kafkaExt.NewDissector()
|
||||||
dissectorRedis.Register(extensionRedis)
|
dissectorKafka.Register(extensionKafka)
|
||||||
extensionRedis.Dissector = dissectorRedis
|
extensionKafka.Dissector = dissectorKafka
|
||||||
Extensions[3] = extensionRedis
|
Extensions = append(Extensions, extensionKafka)
|
||||||
ExtensionsMap[extensionRedis.Protocol.Name] = extensionRedis
|
ExtensionsMap[extensionKafka.Protocol.Name] = extensionKafka
|
||||||
|
|
||||||
|
extensionRedis := &tapApi.Extension{}
|
||||||
|
dissectorRedis := redisExt.NewDissector()
|
||||||
|
dissectorRedis.Register(extensionRedis)
|
||||||
|
extensionRedis.Dissector = dissectorRedis
|
||||||
|
Extensions = append(Extensions, extensionRedis)
|
||||||
|
ExtensionsMap[extensionRedis.Protocol.Name] = extensionRedis
|
||||||
|
}
|
||||||
|
|
||||||
sort.Slice(Extensions, func(i, j int) bool {
|
sort.Slice(Extensions, func(i, j int) bool {
|
||||||
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
||||||
|
|||||||
@@ -1,17 +1,12 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
|
||||||
"net"
|
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/dependency"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/oas"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/up9inc/mizu/agent/pkg/dependency"
|
||||||
|
"github.com/up9inc/mizu/agent/pkg/oas"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetOASServers(t *testing.T) {
|
func TestGetOASServers(t *testing.T) {
|
||||||
@@ -37,33 +32,14 @@ func TestGetOASSpec(t *testing.T) {
|
|||||||
t.Logf("Written body: %s", recorder.Body.String())
|
t.Logf("Written body: %s", recorder.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeConn struct {
|
|
||||||
sendBuffer *bytes.Buffer
|
|
||||||
receiveBuffer *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeConn) Read(p []byte) (int, error) { return f.sendBuffer.Read(p) }
|
|
||||||
func (f fakeConn) Write(p []byte) (int, error) { return f.receiveBuffer.Write(p) }
|
|
||||||
func (fakeConn) Close() error { return nil }
|
|
||||||
func (fakeConn) LocalAddr() net.Addr { return nil }
|
|
||||||
func (fakeConn) RemoteAddr() net.Addr { return nil }
|
|
||||||
func (fakeConn) SetDeadline(t time.Time) error { return nil }
|
|
||||||
func (fakeConn) SetReadDeadline(t time.Time) error { return nil }
|
|
||||||
func (fakeConn) SetWriteDeadline(t time.Time) error { return nil }
|
|
||||||
|
|
||||||
func getRecorderAndContext() (*httptest.ResponseRecorder, *gin.Context) {
|
func getRecorderAndContext() (*httptest.ResponseRecorder, *gin.Context) {
|
||||||
dummyConn := new(basenine.Connection)
|
|
||||||
dummyConn.Conn = fakeConn{
|
|
||||||
sendBuffer: bytes.NewBufferString("\n"),
|
|
||||||
receiveBuffer: bytes.NewBufferString("\n"),
|
|
||||||
}
|
|
||||||
dependency.RegisterGenerator(dependency.OasGeneratorDependency, func() interface{} {
|
dependency.RegisterGenerator(dependency.OasGeneratorDependency, func() interface{} {
|
||||||
return oas.GetDefaultOasGeneratorInstance()
|
return oas.GetDefaultOasGeneratorInstance()
|
||||||
})
|
})
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
c, _ := gin.CreateTestContext(recorder)
|
c, _ := gin.CreateTestContext(recorder)
|
||||||
oas.GetDefaultOasGeneratorInstance().Start(dummyConn)
|
oas.GetDefaultOasGeneratorInstance().Start()
|
||||||
oas.GetDefaultOasGeneratorInstance().GetServiceSpecs().Store("some", oas.NewGen("some"))
|
oas.GetDefaultOasGeneratorInstance().GetServiceSpecs().Store("some", oas.NewGen("some"))
|
||||||
return recorder, c
|
return recorder, c
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/up9inc/mizu/agent/pkg/providers"
|
"github.com/up9inc/mizu/agent/pkg/providers"
|
||||||
"github.com/up9inc/mizu/agent/pkg/providers/tappedPods"
|
"github.com/up9inc/mizu/agent/pkg/providers/tappedPods"
|
||||||
"github.com/up9inc/mizu/agent/pkg/providers/tappers"
|
"github.com/up9inc/mizu/agent/pkg/providers/tappers"
|
||||||
"github.com/up9inc/mizu/agent/pkg/up9"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/validation"
|
"github.com/up9inc/mizu/agent/pkg/validation"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
@@ -71,25 +70,11 @@ func GetConnectedTappersCount(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, tappers.GetConnectedCount())
|
c.JSON(http.StatusOK, tappers.GetConnectedCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAuthStatus(c *gin.Context) {
|
|
||||||
authStatus, err := providers.GetAuthStatus()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, authStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetTappingStatus(c *gin.Context) {
|
func GetTappingStatus(c *gin.Context) {
|
||||||
tappedPodsStatus := tappedPods.GetTappedPodsStatus()
|
tappedPodsStatus := tappedPods.GetTappedPodsStatus()
|
||||||
c.JSON(http.StatusOK, tappedPodsStatus)
|
c.JSON(http.StatusOK, tappedPodsStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AnalyzeInformation(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, up9.GetAnalyzeInfo())
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetGeneralStats(c *gin.Context) {
|
func GetGeneralStats(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, providers.GetGeneralStats())
|
c.JSON(http.StatusOK, providers.GetGeneralStats())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ type DependencyContainerType string
|
|||||||
const (
|
const (
|
||||||
ServiceMapGeneratorDependency = "ServiceMapGeneratorDependency"
|
ServiceMapGeneratorDependency = "ServiceMapGeneratorDependency"
|
||||||
OasGeneratorDependency = "OasGeneratorDependency"
|
OasGeneratorDependency = "OasGeneratorDependency"
|
||||||
|
EntriesInserter = "EntriesInserter"
|
||||||
EntriesProvider = "EntriesProvider"
|
EntriesProvider = "EntriesProvider"
|
||||||
EntriesSocketStreamer = "EntriesSocketStreamer"
|
EntriesSocketStreamer = "EntriesSocketStreamer"
|
||||||
EntryStreamerSocketConnector = "EntryStreamerSocketConnector"
|
EntryStreamerSocketConnector = "EntryStreamerSocketConnector"
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
package elastic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/v7"
|
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type client struct {
|
|
||||||
es *elasticsearch.Client
|
|
||||||
index string
|
|
||||||
insertedCount int
|
|
||||||
}
|
|
||||||
|
|
||||||
var instance *client
|
|
||||||
var once sync.Once
|
|
||||||
|
|
||||||
func GetInstance() *client {
|
|
||||||
once.Do(func() {
|
|
||||||
instance = newClient()
|
|
||||||
})
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *client) Configure(config shared.ElasticConfig) {
|
|
||||||
if config.Url == "" || config.User == "" || config.Password == "" {
|
|
||||||
if client.es != nil {
|
|
||||||
client.es = nil
|
|
||||||
}
|
|
||||||
logger.Log.Infof("No elastic configuration was supplied, elastic exporter disabled")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
transport := http.DefaultTransport
|
|
||||||
tlsClientConfig := &tls.Config{InsecureSkipVerify: true}
|
|
||||||
transport.(*http.Transport).TLSClientConfig = tlsClientConfig
|
|
||||||
cfg := elasticsearch.Config{
|
|
||||||
Addresses: []string{config.Url},
|
|
||||||
Username: config.User,
|
|
||||||
Password: config.Password,
|
|
||||||
Transport: transport,
|
|
||||||
}
|
|
||||||
|
|
||||||
es, err := elasticsearch.NewClient(cfg)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("Failed to initialize elastic client %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Have the client instance return a response
|
|
||||||
res, err := es.Info()
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("Elastic client.Info() ERROR: %v", err)
|
|
||||||
} else {
|
|
||||||
client.es = es
|
|
||||||
client.index = "mizu_traffic_http_" + time.Now().Format("2006_01_02_15_04")
|
|
||||||
client.insertedCount = 0
|
|
||||||
logger.Log.Infof("Elastic client configured, index: %s, cluster info: %v", client.index, res)
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClient() *client {
|
|
||||||
return &client{
|
|
||||||
es: nil,
|
|
||||||
index: "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type httpEntry struct {
|
|
||||||
Source *api.TCP `json:"src"`
|
|
||||||
Destination *api.TCP `json:"dst"`
|
|
||||||
Outgoing bool `json:"outgoing"`
|
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
|
||||||
Request map[string]interface{} `json:"request"`
|
|
||||||
Response map[string]interface{} `json:"response"`
|
|
||||||
ElapsedTime int64 `json:"elapsedTime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *client) PushEntry(entry *api.Entry) {
|
|
||||||
if client.es == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if entry.Protocol.Name != "http" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
entryToPush := httpEntry{
|
|
||||||
Source: entry.Source,
|
|
||||||
Destination: entry.Destination,
|
|
||||||
Outgoing: entry.Outgoing,
|
|
||||||
CreatedAt: entry.StartTime,
|
|
||||||
Request: entry.Request,
|
|
||||||
Response: entry.Response,
|
|
||||||
ElapsedTime: entry.ElapsedTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
entryJson, err := json.Marshal(entryToPush)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("json.Marshal ERROR: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
buffer.WriteString(string(entryJson))
|
|
||||||
res, _ := client.es.Index(client.index, &buffer)
|
|
||||||
if res.StatusCode == 201 {
|
|
||||||
client.insertedCount += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@ type EntriesProvider interface {
|
|||||||
type BasenineEntriesProvider struct{}
|
type BasenineEntriesProvider struct{}
|
||||||
|
|
||||||
func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesRequest) ([]*tapApi.EntryWrapper, *basenine.Metadata, error) {
|
func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesRequest) ([]*tapApi.EntryWrapper, *basenine.Metadata, error) {
|
||||||
data, meta, err := basenine.Fetch(shared.BasenineHost, shared.BaseninePort,
|
data, _, lastMeta, err := basenine.Fetch(shared.BasenineHost, shared.BaseninePort,
|
||||||
entriesRequest.LeftOff, entriesRequest.Direction, entriesRequest.Query,
|
entriesRequest.LeftOff, entriesRequest.Direction, entriesRequest.Query,
|
||||||
entriesRequest.Limit, time.Duration(entriesRequest.TimeoutMs)*time.Millisecond)
|
entriesRequest.Limit, time.Duration(entriesRequest.TimeoutMs)*time.Millisecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -49,7 +49,7 @@ func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesReque
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metadata *basenine.Metadata
|
var metadata *basenine.Metadata
|
||||||
err = json.Unmarshal(meta, &metadata)
|
err = json.Unmarshal(lastMeta, &metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Debugf("Error recieving metadata: %v", err.Error())
|
logger.Log.Debugf("Error recieving metadata: %v", err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ func NewRequest(request map[string]interface{}) (harRequest *Request, err error)
|
|||||||
|
|
||||||
postData, _ := request["postData"].(map[string]interface{})
|
postData, _ := request["postData"].(map[string]interface{})
|
||||||
mimeType := postData["mimeType"]
|
mimeType := postData["mimeType"]
|
||||||
if mimeType == nil || len(mimeType.(string)) == 0 {
|
if mimeType == nil {
|
||||||
mimeType = "text/html"
|
mimeType = ""
|
||||||
}
|
}
|
||||||
text := postData["text"]
|
text := postData["text"]
|
||||||
postDataText := ""
|
postDataText := ""
|
||||||
@@ -177,8 +177,8 @@ func NewResponse(response map[string]interface{}) (harResponse *Response, err er
|
|||||||
|
|
||||||
content, _ := response["content"].(map[string]interface{})
|
content, _ := response["content"].(map[string]interface{})
|
||||||
mimeType := content["mimeType"]
|
mimeType := content["mimeType"]
|
||||||
if mimeType == nil || len(mimeType.(string)) == 0 {
|
if mimeType == nil {
|
||||||
mimeType = "text/html"
|
mimeType = ""
|
||||||
}
|
}
|
||||||
encoding := content["encoding"]
|
encoding := content["encoding"]
|
||||||
text := content["text"]
|
text := content["text"]
|
||||||
|
|||||||
@@ -43,11 +43,6 @@ type WebSocketTappedEntryMessage struct {
|
|||||||
Data *tapApi.OutputChannelItem
|
Data *tapApi.OutputChannelItem
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthStatus struct {
|
|
||||||
Email string `json:"email"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ToastMessage struct {
|
type ToastMessage struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
AutoClose uint `json:"autoClose"`
|
AutoClose uint `json:"autoClose"`
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package oas
|
package oas
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
"github.com/up9inc/mizu/agent/pkg/har"
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
@@ -19,22 +16,20 @@ var (
|
|||||||
instance *defaultOasGenerator
|
instance *defaultOasGenerator
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OasGeneratorSink interface {
|
||||||
|
HandleEntry(mizuEntry *api.Entry)
|
||||||
|
}
|
||||||
|
|
||||||
type OasGenerator interface {
|
type OasGenerator interface {
|
||||||
Start(conn *basenine.Connection)
|
Start()
|
||||||
Stop()
|
Stop()
|
||||||
IsStarted() bool
|
IsStarted() bool
|
||||||
GetServiceSpecs() *sync.Map
|
GetServiceSpecs() *sync.Map
|
||||||
SetEntriesQuery(query string) bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultOasGenerator struct {
|
type defaultOasGenerator struct {
|
||||||
started bool
|
started bool
|
||||||
ctx context.Context
|
|
||||||
cancel context.CancelFunc
|
|
||||||
serviceSpecs *sync.Map
|
serviceSpecs *sync.Map
|
||||||
dbConn *basenine.Connection
|
|
||||||
dbMutex sync.Mutex
|
|
||||||
entriesQuery string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDefaultOasGeneratorInstance() *defaultOasGenerator {
|
func GetDefaultOasGeneratorInstance() *defaultOasGenerator {
|
||||||
@@ -45,102 +40,29 @@ func GetDefaultOasGeneratorInstance() *defaultOasGenerator {
|
|||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) Start(conn *basenine.Connection) {
|
func (g *defaultOasGenerator) Start() {
|
||||||
if g.started {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.dbConn == nil {
|
|
||||||
if conn == nil {
|
|
||||||
logger.Log.Infof("Creating new DB connection for OAS generator to address %s:%s", shared.BasenineHost, shared.BaseninePort)
|
|
||||||
newConn, err := basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Error("Error connecting to DB for OAS generator, err: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
conn = newConn
|
|
||||||
}
|
|
||||||
|
|
||||||
g.dbConn = conn
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
g.cancel = cancel
|
|
||||||
g.ctx = ctx
|
|
||||||
g.serviceSpecs = &sync.Map{}
|
|
||||||
|
|
||||||
g.started = true
|
g.started = true
|
||||||
|
|
||||||
go g.runGenerator()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) Stop() {
|
func (g *defaultOasGenerator) Stop() {
|
||||||
if !g.started {
|
if !g.started {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g.started = false
|
g.started = false
|
||||||
|
|
||||||
g.cancel()
|
|
||||||
g.reset()
|
g.reset()
|
||||||
|
|
||||||
g.dbMutex.Lock()
|
|
||||||
defer g.dbMutex.Unlock()
|
|
||||||
if g.dbConn != nil {
|
|
||||||
g.dbConn.Close()
|
|
||||||
g.dbConn = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) IsStarted() bool {
|
func (g *defaultOasGenerator) IsStarted() bool {
|
||||||
return g.started
|
return g.started
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) runGenerator() {
|
func (g *defaultOasGenerator) HandleEntry(mizuEntry *api.Entry) {
|
||||||
// Make []byte channels to receive the data and the meta
|
if !g.started {
|
||||||
dataChan := make(chan []byte)
|
return
|
||||||
metaChan := make(chan []byte)
|
|
||||||
|
|
||||||
g.dbMutex.Lock()
|
|
||||||
defer g.dbMutex.Unlock()
|
|
||||||
logger.Log.Infof("Querying DB for OAS generator with query '%s'", g.entriesQuery)
|
|
||||||
if err := g.dbConn.Query(g.entriesQuery, dataChan, metaChan); err != nil {
|
|
||||||
logger.Log.Errorf("Query mode call failed: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-g.ctx.Done():
|
|
||||||
logger.Log.Infof("OAS Generator was canceled")
|
|
||||||
close(dataChan)
|
|
||||||
close(metaChan)
|
|
||||||
return
|
|
||||||
|
|
||||||
case metaBytes, ok := <-metaChan:
|
|
||||||
if !ok {
|
|
||||||
logger.Log.Infof("OAS Generator - meta channel closed")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
logger.Log.Debugf("Meta: %s", metaBytes)
|
|
||||||
|
|
||||||
case dataBytes, ok := <-dataChan:
|
|
||||||
if !ok {
|
|
||||||
logger.Log.Infof("OAS Generator - entries channel closed")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Debugf("Data: %s", dataBytes)
|
|
||||||
e := new(api.Entry)
|
|
||||||
err := json.Unmarshal(dataBytes, e)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.handleEntry(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *defaultOasGenerator) handleEntry(mizuEntry *api.Entry) {
|
|
||||||
if mizuEntry.Protocol.Name == "http" {
|
if mizuEntry.Protocol.Name == "http" {
|
||||||
dest := mizuEntry.Destination.Name
|
dest := mizuEntry.Destination.Name
|
||||||
if dest == "" {
|
if dest == "" {
|
||||||
@@ -210,18 +132,9 @@ func (g *defaultOasGenerator) GetServiceSpecs() *sync.Map {
|
|||||||
return g.serviceSpecs
|
return g.serviceSpecs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *defaultOasGenerator) SetEntriesQuery(query string) bool {
|
|
||||||
changed := g.entriesQuery != query
|
|
||||||
g.entriesQuery = query
|
|
||||||
return changed
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultOasGenerator() *defaultOasGenerator {
|
func NewDefaultOasGenerator() *defaultOasGenerator {
|
||||||
return &defaultOasGenerator{
|
return &defaultOasGenerator{
|
||||||
started: false,
|
started: false,
|
||||||
ctx: nil,
|
serviceSpecs: &sync.Map{},
|
||||||
cancel: nil,
|
|
||||||
serviceSpecs: nil,
|
|
||||||
dbConn: nil,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestOASGen(t *testing.T) {
|
func TestOASGen(t *testing.T) {
|
||||||
gen := new(defaultOasGenerator)
|
gen := GetDefaultOasGeneratorInstance()
|
||||||
|
|
||||||
e := new(har.Entry)
|
e := new(har.Entry)
|
||||||
err := json.Unmarshal([]byte(`{"startedDateTime": "20000101","request": {"url": "https://host/path", "method": "GET"}, "response": {"status": 200}}`), e)
|
err := json.Unmarshal([]byte(`{"startedDateTime": "20000101","request": {"url": "https://host/path", "method": "GET"}, "response": {"status": 200}}`), e)
|
||||||
@@ -21,8 +21,7 @@ func TestOASGen(t *testing.T) {
|
|||||||
Entry: *e,
|
Entry: *e,
|
||||||
}
|
}
|
||||||
|
|
||||||
dummyConn := GetFakeDBConn(`{"startedDateTime": "20000101","request": {"url": "https://host/path", "method": "GET"}, "response": {"status": 200}}`)
|
gen.Start()
|
||||||
gen.Start(dummyConn)
|
|
||||||
gen.handleHARWithSource(ews)
|
gen.handleHARWithSource(ews)
|
||||||
g, ok := gen.serviceSpecs.Load("some")
|
g, ok := gen.serviceSpecs.Load("some")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package oas
|
package oas
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -13,22 +11,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/chanced/openapi"
|
"github.com/chanced/openapi"
|
||||||
|
"github.com/up9inc/mizu/agent/pkg/har"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/wI2L/jsondiff"
|
"github.com/wI2L/jsondiff"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetFakeDBConn(send string) *basenine.Connection {
|
|
||||||
dummyConn := new(basenine.Connection)
|
|
||||||
dummyConn.Conn = FakeConn{
|
|
||||||
sendBuffer: bytes.NewBufferString(send),
|
|
||||||
receiveBuffer: bytes.NewBufferString(""),
|
|
||||||
}
|
|
||||||
return dummyConn
|
|
||||||
}
|
|
||||||
|
|
||||||
// if started via env, write file into subdir
|
// if started via env, write file into subdir
|
||||||
func outputSpec(label string, spec *openapi.OpenAPI, t *testing.T) string {
|
func outputSpec(label string, spec *openapi.OpenAPI, t *testing.T) string {
|
||||||
content, err := json.MarshalIndent(spec, "", " ")
|
content, err := json.MarshalIndent(spec, "", " ")
|
||||||
@@ -278,17 +265,3 @@ func TestLoadValid3_1(t *testing.T) {
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FakeConn struct {
|
|
||||||
sendBuffer *bytes.Buffer
|
|
||||||
receiveBuffer *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FakeConn) Read(p []byte) (int, error) { return f.sendBuffer.Read(p) }
|
|
||||||
func (f FakeConn) Write(p []byte) (int, error) { return f.receiveBuffer.Write(p) }
|
|
||||||
func (FakeConn) Close() error { return nil }
|
|
||||||
func (FakeConn) LocalAddr() net.Addr { return nil }
|
|
||||||
func (FakeConn) RemoteAddr() net.Addr { return nil }
|
|
||||||
func (FakeConn) SetDeadline(t time.Time) error { return nil }
|
|
||||||
func (FakeConn) SetReadDeadline(t time.Time) error { return nil }
|
|
||||||
func (FakeConn) SetWriteDeadline(t time.Time) error { return nil }
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package providers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
authStatus *models.AuthStatus
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetAuthStatus() (*models.AuthStatus, error) {
|
|
||||||
if authStatus == nil {
|
|
||||||
syncEntriesConfigJson := os.Getenv(shared.SyncEntriesConfigEnvVar)
|
|
||||||
if syncEntriesConfigJson == "" {
|
|
||||||
authStatus = &models.AuthStatus{}
|
|
||||||
return authStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
syncEntriesConfig := &shared.SyncEntriesConfig{}
|
|
||||||
err := json.Unmarshal([]byte(syncEntriesConfigJson), syncEntriesConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to marshal sync entries config, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if syncEntriesConfig.Token == "" {
|
|
||||||
authStatus = &models.AuthStatus{}
|
|
||||||
return authStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenEmail, err := shared.GetTokenEmail(syncEntriesConfig.Token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get token email, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
authStatus = &models.AuthStatus{
|
|
||||||
Email: tokenEmail,
|
|
||||||
Model: syncEntriesConfig.Workspace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return authStatus, nil
|
|
||||||
}
|
|
||||||
@@ -15,10 +15,6 @@ func StatusRoutes(ginApp *gin.Engine) {
|
|||||||
routeGroup.GET("/connectedTappersCount", controllers.GetConnectedTappersCount)
|
routeGroup.GET("/connectedTappersCount", controllers.GetConnectedTappersCount)
|
||||||
routeGroup.GET("/tap", controllers.GetTappingStatus)
|
routeGroup.GET("/tap", controllers.GetTappingStatus)
|
||||||
|
|
||||||
routeGroup.GET("/auth", controllers.GetAuthStatus)
|
|
||||||
|
|
||||||
routeGroup.GET("/analyze", controllers.AnalyzeInformation)
|
|
||||||
|
|
||||||
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("/resolving", controllers.GetCurrentResolvingInformation)
|
routeGroup.GET("/resolving", controllers.GetCurrentResolvingInformation)
|
||||||
|
|||||||
@@ -1,353 +0,0 @@
|
|||||||
package up9
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"compress/zlib"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/utils"
|
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
AnalyzeCheckSleepTime = 5 * time.Second
|
|
||||||
SentCountLogInterval = 100
|
|
||||||
)
|
|
||||||
|
|
||||||
type GuestToken struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ModelStatus struct {
|
|
||||||
LastMajorGeneration float64 `json:"lastMajorGeneration"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRemoteUrl(analyzeDestination string, analyzeModel string, analyzeToken string, guestMode bool) string {
|
|
||||||
if guestMode {
|
|
||||||
return fmt.Sprintf("https://%s/share/%s", analyzeDestination, analyzeToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("https://%s/app/workspaces/%s", analyzeDestination, analyzeModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckIfModelReady(analyzeDestination string, analyzeModel string, analyzeToken string, guestMode bool) bool {
|
|
||||||
statusUrl, _ := url.Parse(fmt.Sprintf("https://trcc.%s/models/%s/status", analyzeDestination, analyzeModel))
|
|
||||||
|
|
||||||
authHeader := getAuthHeader(guestMode)
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodGet,
|
|
||||||
URL: statusUrl,
|
|
||||||
Header: map[string][]string{
|
|
||||||
"Content-Type": {"application/json"},
|
|
||||||
authHeader: {analyzeToken},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
statusResp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer statusResp.Body.Close()
|
|
||||||
|
|
||||||
target := &ModelStatus{}
|
|
||||||
_ = json.NewDecoder(statusResp.Body).Decode(&target)
|
|
||||||
|
|
||||||
return target.LastMajorGeneration > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthHeader(guestMode bool) string {
|
|
||||||
if guestMode {
|
|
||||||
return "Guest-Auth"
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Authorization"
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetTrafficDumpUrl(analyzeDestination string, analyzeModel string) *url.URL {
|
|
||||||
strUrl := fmt.Sprintf("https://traffic.%s/dumpTrafficBulk/%s", analyzeDestination, analyzeModel)
|
|
||||||
postUrl, _ := url.Parse(strUrl)
|
|
||||||
return postUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
type AnalyzeInformation struct {
|
|
||||||
IsAnalyzing bool
|
|
||||||
GuestMode bool
|
|
||||||
SentCount int
|
|
||||||
AnalyzedModel string
|
|
||||||
AnalyzeToken string
|
|
||||||
AnalyzeDestination string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *AnalyzeInformation) Reset() {
|
|
||||||
info.IsAnalyzing = false
|
|
||||||
info.GuestMode = true
|
|
||||||
info.AnalyzedModel = ""
|
|
||||||
info.AnalyzeToken = ""
|
|
||||||
info.AnalyzeDestination = ""
|
|
||||||
info.SentCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var analyzeInformation = &AnalyzeInformation{}
|
|
||||||
|
|
||||||
func GetAnalyzeInfo() *shared.AnalyzeStatus {
|
|
||||||
return &shared.AnalyzeStatus{
|
|
||||||
IsAnalyzing: analyzeInformation.IsAnalyzing,
|
|
||||||
RemoteUrl: GetRemoteUrl(analyzeInformation.AnalyzeDestination, analyzeInformation.AnalyzedModel, analyzeInformation.AnalyzeToken, analyzeInformation.GuestMode),
|
|
||||||
IsRemoteReady: CheckIfModelReady(analyzeInformation.AnalyzeDestination, analyzeInformation.AnalyzedModel, analyzeInformation.AnalyzeToken, analyzeInformation.GuestMode),
|
|
||||||
SentCount: analyzeInformation.SentCount,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SyncEntries(syncEntriesConfig *shared.SyncEntriesConfig) error {
|
|
||||||
logger.Log.Infof("Sync entries - started")
|
|
||||||
|
|
||||||
var (
|
|
||||||
token, model string
|
|
||||||
guestMode bool
|
|
||||||
)
|
|
||||||
if syncEntriesConfig.Token == "" {
|
|
||||||
logger.Log.Infof("Sync entries - creating anonymous token. env %s", syncEntriesConfig.Env)
|
|
||||||
guestToken, err := createAnonymousToken(syncEntriesConfig.Env)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed creating anonymous token, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
token = guestToken.Token
|
|
||||||
model = guestToken.Model
|
|
||||||
guestMode = true
|
|
||||||
} else {
|
|
||||||
token = fmt.Sprintf("bearer %s", syncEntriesConfig.Token)
|
|
||||||
model = syncEntriesConfig.Workspace
|
|
||||||
guestMode = false
|
|
||||||
|
|
||||||
logger.Log.Infof("Sync entries - upserting model. env %s, model %s", syncEntriesConfig.Env, model)
|
|
||||||
if err := upsertModel(token, model, syncEntriesConfig.Env); err != nil {
|
|
||||||
return fmt.Errorf("failed upserting model, err: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modelRegex, _ := regexp.Compile("[A-Za-z0-9][-A-Za-z0-9_.]*[A-Za-z0-9]+$")
|
|
||||||
if len(model) > 63 || !modelRegex.MatchString(model) {
|
|
||||||
return fmt.Errorf("invalid model name, model name: %s", model)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Infof("Sync entries - syncing. token: %s, model: %s, guest mode: %v", token, model, guestMode)
|
|
||||||
go syncEntriesImpl(token, model, syncEntriesConfig.Env, syncEntriesConfig.UploadIntervalSec, guestMode)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func upsertModel(token string, model string, envPrefix string) error {
|
|
||||||
upsertModelUrl, _ := url.Parse(fmt.Sprintf("https://trcc.%s/models/%s", envPrefix, model))
|
|
||||||
|
|
||||||
authHeader := getAuthHeader(false)
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodPost,
|
|
||||||
URL: upsertModelUrl,
|
|
||||||
Header: map[string][]string{
|
|
||||||
authHeader: {token},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed request to upsert model, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case the model is not created (not 201) and doesn't exists (not 409)
|
|
||||||
if response.StatusCode != 201 && response.StatusCode != 409 {
|
|
||||||
return fmt.Errorf("failed request to upsert model, status code: %v", response.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAnonymousToken(envPrefix string) (*GuestToken, error) {
|
|
||||||
tokenUrl := fmt.Sprintf("https://trcc.%s/anonymous/token", envPrefix)
|
|
||||||
if strings.HasPrefix(envPrefix, "http") {
|
|
||||||
tokenUrl = fmt.Sprintf("%s/api/token", envPrefix)
|
|
||||||
}
|
|
||||||
token := &GuestToken{}
|
|
||||||
if err := getGuestToken(tokenUrl, token); err != nil {
|
|
||||||
logger.Log.Infof("Failed to get token, %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGuestToken(url string, target *GuestToken) error {
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
logger.Log.Infof("Got token from the server, starting to json decode... status code: %v", resp.StatusCode)
|
|
||||||
return json.NewDecoder(resp.Body).Decode(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
func syncEntriesImpl(token string, model string, envPrefix string, uploadIntervalSec int, guestMode bool) {
|
|
||||||
analyzeInformation.IsAnalyzing = true
|
|
||||||
analyzeInformation.GuestMode = guestMode
|
|
||||||
analyzeInformation.AnalyzedModel = model
|
|
||||||
analyzeInformation.AnalyzeToken = token
|
|
||||||
analyzeInformation.AnalyzeDestination = envPrefix
|
|
||||||
analyzeInformation.SentCount = 0
|
|
||||||
|
|
||||||
// "http or grpc" filter indicates that we're only interested in HTTP and gRPC entries
|
|
||||||
query := "http or grpc"
|
|
||||||
|
|
||||||
logger.Log.Infof("Getting entries from the database")
|
|
||||||
|
|
||||||
BasenineReconnect:
|
|
||||||
var connection *basenine.Connection
|
|
||||||
var err error
|
|
||||||
connection, err = basenine.NewConnection(shared.BasenineHost, shared.BaseninePort)
|
|
||||||
if err != nil {
|
|
||||||
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)
|
|
||||||
meta := make(chan []byte)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
data <- []byte(basenine.CloseChannel)
|
|
||||||
meta <- []byte(basenine.CloseChannel)
|
|
||||||
connection.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
lastTimeSynced := time.Time{}
|
|
||||||
|
|
||||||
batch := make([]har.Entry, 0)
|
|
||||||
|
|
||||||
handleDataChannel := func(wg *sync.WaitGroup, connection *basenine.Connection, data chan []byte) {
|
|
||||||
defer wg.Done()
|
|
||||||
for {
|
|
||||||
dataBytes := <-data
|
|
||||||
|
|
||||||
if string(dataBytes) == basenine.CloseChannel {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var dataMap map[string]interface{}
|
|
||||||
err = json.Unmarshal(dataBytes, &dataMap)
|
|
||||||
|
|
||||||
var entry tapApi.Entry
|
|
||||||
if err := json.Unmarshal([]byte(dataBytes), &entry); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
harEntry, err := har.NewEntry(entry.Request, entry.Response, entry.StartTime, entry.ElapsedTime)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if entry.Source.Name != "" {
|
|
||||||
harEntry.Request.Headers = append(harEntry.Request.Headers, har.Header{Name: "x-mizu-source", Value: entry.Source.Name})
|
|
||||||
}
|
|
||||||
if entry.Destination.Name != "" {
|
|
||||||
harEntry.Request.Headers = append(harEntry.Request.Headers, har.Header{Name: "x-mizu-destination", Value: entry.Destination.Name})
|
|
||||||
harEntry.Request.URL = utils.SetHostname(harEntry.Request.URL, entry.Destination.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
batch = append(batch, *harEntry)
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
if lastTimeSynced.Add(time.Duration(uploadIntervalSec) * time.Second).After(now) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lastTimeSynced = now
|
|
||||||
|
|
||||||
body, jMarshalErr := json.Marshal(batch)
|
|
||||||
batchSize := len(batch)
|
|
||||||
if jMarshalErr != nil {
|
|
||||||
analyzeInformation.Reset()
|
|
||||||
logger.Log.Infof("Stopping sync entries")
|
|
||||||
logger.Log.Fatal(jMarshalErr)
|
|
||||||
}
|
|
||||||
batch = make([]har.Entry, 0)
|
|
||||||
|
|
||||||
var in bytes.Buffer
|
|
||||||
w := zlib.NewWriter(&in)
|
|
||||||
_, _ = w.Write(body)
|
|
||||||
_ = w.Close()
|
|
||||||
reqBody := ioutil.NopCloser(bytes.NewReader(in.Bytes()))
|
|
||||||
|
|
||||||
authHeader := getAuthHeader(guestMode)
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodPost,
|
|
||||||
URL: GetTrafficDumpUrl(envPrefix, model),
|
|
||||||
Header: map[string][]string{
|
|
||||||
"Content-Encoding": {"deflate"},
|
|
||||||
"Content-Type": {"application/octet-stream"},
|
|
||||||
authHeader: {token},
|
|
||||||
},
|
|
||||||
Body: reqBody,
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, postErr := http.DefaultClient.Do(req); postErr != nil {
|
|
||||||
analyzeInformation.Reset()
|
|
||||||
logger.Log.Info("Stopping sync entries")
|
|
||||||
logger.Log.Fatal(postErr)
|
|
||||||
}
|
|
||||||
analyzeInformation.SentCount += batchSize
|
|
||||||
|
|
||||||
if analyzeInformation.SentCount%SentCountLogInterval == 0 {
|
|
||||||
logger.Log.Infof("Uploaded %v entries until now", analyzeInformation.SentCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMetaChannel := func(wg *sync.WaitGroup, connection *basenine.Connection, meta chan []byte) {
|
|
||||||
defer wg.Done()
|
|
||||||
for {
|
|
||||||
metaBytes := <-meta
|
|
||||||
|
|
||||||
if string(metaBytes) == basenine.CloseChannel {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
go handleDataChannel(&wg, connection, data)
|
|
||||||
go handleMetaChannel(&wg, connection, meta)
|
|
||||||
wg.Add(2)
|
|
||||||
|
|
||||||
if err = connection.Query(query, data, meta); err != nil {
|
|
||||||
logger.Log.Errorf("Query mode call failed: %v", err)
|
|
||||||
connection.Close()
|
|
||||||
time.Sleep(shared.BasenineReconnectInterval * time.Second)
|
|
||||||
goto BasenineReconnect
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateAnalyzeStatus(callback func(data []byte)) {
|
|
||||||
for {
|
|
||||||
if !analyzeInformation.IsAnalyzing {
|
|
||||||
time.Sleep(AnalyzeCheckSleepTime)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
analyzeStatus := GetAnalyzeInfo()
|
|
||||||
socketMessage := shared.CreateWebSocketMessageTypeAnalyzeStatus(*analyzeStatus)
|
|
||||||
|
|
||||||
jsonMessage, _ := json.Marshal(socketMessage)
|
|
||||||
callback(jsonMessage)
|
|
||||||
time.Sleep(AnalyzeCheckSleepTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/up9inc/mizu/cli/config"
|
|
||||||
"github.com/up9inc/mizu/cli/config/configStructs"
|
|
||||||
"github.com/up9inc/mizu/cli/uiUtils"
|
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
)
|
|
||||||
|
|
||||||
const loginTimeoutInMin = 2
|
|
||||||
|
|
||||||
// Ports are configured in keycloak "cli" client as valid redirect URIs. A change here must be reflected there as well.
|
|
||||||
var listenPorts = []int{3141, 4001, 5002, 6003, 7004, 8005, 9006, 10007}
|
|
||||||
|
|
||||||
func Login() error {
|
|
||||||
token, loginErr := loginInteractively()
|
|
||||||
if loginErr != nil {
|
|
||||||
return fmt.Errorf("failed login interactively, err: %v", loginErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
authConfig := configStructs.AuthConfig{
|
|
||||||
EnvName: config.Config.Auth.EnvName,
|
|
||||||
Token: token.AccessToken,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := config.UpdateConfig(func(configStruct *config.ConfigStruct) { configStruct.Auth = authConfig }); err != nil {
|
|
||||||
return fmt.Errorf("failed updating config with auth, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Config.Auth = authConfig
|
|
||||||
|
|
||||||
logger.Log.Infof("Login successfully, token stored in config path: %s", fmt.Sprintf(uiUtils.Purple, config.Config.ConfigFilePath))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loginInteractively() (*oauth2.Token, error) {
|
|
||||||
tokenChannel := make(chan *oauth2.Token)
|
|
||||||
errorChannel := make(chan error)
|
|
||||||
|
|
||||||
server := http.Server{}
|
|
||||||
go startLoginServer(tokenChannel, errorChannel, &server)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := server.Shutdown(context.Background()); err != nil {
|
|
||||||
logger.Log.Debugf("Error shutting down server, err: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(loginTimeoutInMin * time.Minute):
|
|
||||||
return nil, errors.New("auth timed out")
|
|
||||||
case err := <-errorChannel:
|
|
||||||
return nil, err
|
|
||||||
case token := <-tokenChannel:
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startLoginServer(tokenChannel chan *oauth2.Token, errorChannel chan error, server *http.Server) {
|
|
||||||
for _, port := range listenPorts {
|
|
||||||
var authConfig = &oauth2.Config{
|
|
||||||
ClientID: "cli",
|
|
||||||
RedirectURL: fmt.Sprintf("http://localhost:%v/callback", port),
|
|
||||||
Endpoint: oauth2.Endpoint{
|
|
||||||
AuthURL: fmt.Sprintf("https://auth.%s/auth/realms/testr/protocol/openid-connect/auth", config.Config.Auth.EnvName),
|
|
||||||
TokenURL: fmt.Sprintf("https://auth.%s/auth/realms/testr/protocol/openid-connect/token", config.Config.Auth.EnvName),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
state := uuid.New()
|
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
|
||||||
server.Handler = mux
|
|
||||||
mux.Handle("/callback", loginCallbackHandler(tokenChannel, errorChannel, authConfig, state))
|
|
||||||
|
|
||||||
listener, listenErr := net.Listen("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", port))
|
|
||||||
if listenErr != nil {
|
|
||||||
logger.Log.Debugf("failed to start listening on port %v, err: %v", port, listenErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizationUrl := authConfig.AuthCodeURL(state.String())
|
|
||||||
uiUtils.OpenBrowser(authorizationUrl)
|
|
||||||
|
|
||||||
serveErr := server.Serve(listener)
|
|
||||||
if serveErr == http.ErrServerClosed {
|
|
||||||
logger.Log.Debugf("received server shutdown, server on port %v is closed", port)
|
|
||||||
return
|
|
||||||
} else if serveErr != nil {
|
|
||||||
logger.Log.Debugf("failed to start serving on port %v, err: %v", port, serveErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Debugf("didn't receive server closed on port %v", port)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
errorChannel <- fmt.Errorf("failed to start serving on all listen ports, ports: %v", listenPorts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loginCallbackHandler(tokenChannel chan *oauth2.Token, errorChannel chan error, authConfig *oauth2.Config, state uuid.UUID) http.Handler {
|
|
||||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
if err := request.ParseForm(); err != nil {
|
|
||||||
errorMsg := fmt.Sprintf("failed to parse form, err: %v", err)
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
requestState := request.Form.Get("state")
|
|
||||||
if requestState != state.String() {
|
|
||||||
errorMsg := fmt.Sprintf("state invalid, requestState: %v, authState:%v", requestState, state.String())
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
code := request.Form.Get("code")
|
|
||||||
if code == "" {
|
|
||||||
errorMsg := "code not found"
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := authConfig.Exchange(context.Background(), code)
|
|
||||||
if err != nil {
|
|
||||||
errorMsg := fmt.Sprintf("failed to create token, err: %v", err)
|
|
||||||
http.Error(writer, errorMsg, http.StatusInternalServerError)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenChannel <- token
|
|
||||||
|
|
||||||
http.Redirect(writer, request, fmt.Sprintf("https://%s/CliLogin", config.Config.Auth.EnvName), http.StatusFound)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/creasty/defaults"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/up9inc/mizu/cli/config/configStructs"
|
||||||
"github.com/up9inc/mizu/cli/telemetry"
|
"github.com/up9inc/mizu/cli/telemetry"
|
||||||
|
"github.com/up9inc/mizu/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var installCmd = &cobra.Command{
|
var installCmd = &cobra.Command{
|
||||||
@@ -17,4 +20,11 @@ var installCmd = &cobra.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(installCmd)
|
rootCmd.AddCommand(installCmd)
|
||||||
|
|
||||||
|
defaultInstallConfig := configStructs.InstallConfig{}
|
||||||
|
if err := defaults.Set(&defaultInstallConfig); err != nil {
|
||||||
|
logger.Log.Debug(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
installCmd.Flags().BoolP(configStructs.OutInstallName, "o", defaultInstallConfig.Out, "print (to stdout) Kubernetes manifest used to install Mizu Pro edition")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/cli/bucket"
|
"github.com/up9inc/mizu/cli/bucket"
|
||||||
"github.com/up9inc/mizu/cli/config"
|
"github.com/up9inc/mizu/cli/config"
|
||||||
@@ -9,12 +10,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func runMizuInstall() {
|
func runMizuInstall() {
|
||||||
bucketProvider := bucket.NewProvider(config.Config.Install.TemplateUrl, bucket.DefaultTimeout)
|
if config.Config.Install.Out {
|
||||||
installTemplate, err := bucketProvider.GetInstallTemplate(config.Config.Install.TemplateName)
|
bucketProvider := bucket.NewProvider(config.Config.Install.TemplateUrl, bucket.DefaultTimeout)
|
||||||
if err != nil {
|
installTemplate, err := bucketProvider.GetInstallTemplate(config.Config.Install.TemplateName)
|
||||||
logger.Log.Errorf("Failed getting install template, err: %v", err)
|
if err != nil {
|
||||||
|
logger.Log.Errorf("Failed getting install template, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print(installTemplate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print(installTemplate)
|
var sb strings.Builder
|
||||||
|
sb.WriteString("Hello! This command can be used to install Mizu Pro edition on your Kubernetes cluster.")
|
||||||
|
sb.WriteString("\nPlease run:")
|
||||||
|
sb.WriteString("\n\tmizu install -o | kubectl apply -n mizu -f -")
|
||||||
|
sb.WriteString("\n\nor use helm chart as described in https://getmizu.io/docs/installing-mizu/centralized-installation\n")
|
||||||
|
|
||||||
|
fmt.Print(sb.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,15 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/cli/up9"
|
|
||||||
|
|
||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/up9inc/mizu/cli/auth"
|
|
||||||
"github.com/up9inc/mizu/cli/config"
|
"github.com/up9inc/mizu/cli/config"
|
||||||
"github.com/up9inc/mizu/cli/config/configStructs"
|
"github.com/up9inc/mizu/cli/config/configStructs"
|
||||||
"github.com/up9inc/mizu/cli/errormessage"
|
"github.com/up9inc/mizu/cli/errormessage"
|
||||||
"github.com/up9inc/mizu/cli/uiUtils"
|
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const uploadTrafficMessageToConfirm = `NOTE: running mizu with --%s flag will upload recorded traffic for further analysis and enriched presentation options.`
|
|
||||||
|
|
||||||
var tapCmd = &cobra.Command{
|
var tapCmd = &cobra.Command{
|
||||||
Use: "tap [POD REGEX]",
|
Use: "tap [POD REGEX]",
|
||||||
Short: "Record ingoing traffic of a kubernetes pod",
|
Short: "Record ingoing traffic of a kubernetes pod",
|
||||||
@@ -40,67 +31,12 @@ Supported protocols are HTTP and gRPC.`,
|
|||||||
return errormessage.FormatError(err)
|
return errormessage.FormatError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Config.Tap.Workspace != "" {
|
|
||||||
askConfirmation(configStructs.WorkspaceTapName)
|
|
||||||
|
|
||||||
if config.Config.Auth.Token == "" {
|
|
||||||
logger.Log.Infof("This action requires authentication, please log in to continue")
|
|
||||||
if err := auth.Login(); err != nil {
|
|
||||||
logger.Log.Errorf("failed to log in, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tokenExpired, err := shared.IsTokenExpired(config.Config.Auth.Token)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("failed to check if token is expired, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if tokenExpired {
|
|
||||||
logger.Log.Infof("Token expired, please log in again to continue")
|
|
||||||
if err := auth.Login(); err != nil {
|
|
||||||
logger.Log.Errorf("failed to log in, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else if isValidToken := up9.IsTokenValid(config.Config.Auth.Token, config.Config.Auth.EnvName); !isValidToken {
|
|
||||||
logger.Log.Errorf("Token is not valid, please log in again to continue")
|
|
||||||
if err := auth.Login(); err != nil {
|
|
||||||
logger.Log.Errorf("failed to log in, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Config.Tap.Analysis {
|
|
||||||
askConfirmation(configStructs.AnalysisTapName)
|
|
||||||
|
|
||||||
config.Config.Auth.Token = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Infof("Mizu will store up to %s of traffic, old traffic will be cleared once the limit is reached.", config.Config.Tap.HumanMaxEntriesDBSize)
|
logger.Log.Infof("Mizu will store up to %s of traffic, old traffic will be cleared once the limit is reached.", config.Config.Tap.HumanMaxEntriesDBSize)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func askConfirmation(flagName string) {
|
|
||||||
logger.Log.Infof(fmt.Sprintf(uploadTrafficMessageToConfirm, flagName))
|
|
||||||
|
|
||||||
if !config.Config.Tap.AskUploadConfirmation {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !uiUtils.AskForConfirmation("Would you like to proceed [Y/n]: ") {
|
|
||||||
logger.Log.Infof("You can always run mizu without %s, aborting", flagName)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := config.UpdateConfig(func(configStruct *config.ConfigStruct) { configStruct.Tap.AskUploadConfirmation = false }); err != nil {
|
|
||||||
logger.Log.Debugf("failed updating config with upload confirmation, err: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(tapCmd)
|
rootCmd.AddCommand(tapCmd)
|
||||||
|
|
||||||
@@ -111,16 +47,15 @@ func init() {
|
|||||||
|
|
||||||
tapCmd.Flags().Uint16P(configStructs.GuiPortTapName, "p", defaultTapConfig.GuiPort, "Provide a custom port for the web interface webserver")
|
tapCmd.Flags().Uint16P(configStructs.GuiPortTapName, "p", defaultTapConfig.GuiPort, "Provide a custom port for the web interface webserver")
|
||||||
tapCmd.Flags().StringSliceP(configStructs.NamespacesTapName, "n", defaultTapConfig.Namespaces, "Namespaces selector")
|
tapCmd.Flags().StringSliceP(configStructs.NamespacesTapName, "n", defaultTapConfig.Namespaces, "Namespaces selector")
|
||||||
tapCmd.Flags().Bool(configStructs.AnalysisTapName, defaultTapConfig.Analysis, "Uploads traffic to UP9 for further analysis (Beta)")
|
|
||||||
tapCmd.Flags().BoolP(configStructs.AllNamespacesTapName, "A", defaultTapConfig.AllNamespaces, "Tap all namespaces")
|
tapCmd.Flags().BoolP(configStructs.AllNamespacesTapName, "A", defaultTapConfig.AllNamespaces, "Tap all namespaces")
|
||||||
tapCmd.Flags().StringSliceP(configStructs.PlainTextFilterRegexesTapName, "r", defaultTapConfig.PlainTextFilterRegexes, "List of regex expressions that are used to filter matching values from text/plain http bodies")
|
tapCmd.Flags().StringSliceP(configStructs.PlainTextFilterRegexesTapName, "r", defaultTapConfig.PlainTextFilterRegexes, "List of regex expressions that are used to filter matching values from text/plain http bodies")
|
||||||
tapCmd.Flags().Bool(configStructs.DisableRedactionTapName, defaultTapConfig.DisableRedaction, "Disables redaction of potentially sensitive request/response headers and body values")
|
tapCmd.Flags().Bool(configStructs.EnableRedactionTapName, defaultTapConfig.EnableRedaction, "Enables redaction of potentially sensitive request/response headers and body values")
|
||||||
tapCmd.Flags().String(configStructs.HumanMaxEntriesDBSizeTapName, defaultTapConfig.HumanMaxEntriesDBSize, "Override the default max entries db size")
|
tapCmd.Flags().String(configStructs.HumanMaxEntriesDBSizeTapName, defaultTapConfig.HumanMaxEntriesDBSize, "Override the default max entries db size")
|
||||||
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
||||||
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
||||||
tapCmd.Flags().StringP(configStructs.WorkspaceTapName, "w", defaultTapConfig.Workspace, "Uploads traffic to your UP9 workspace for further analysis (requires auth)")
|
|
||||||
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
||||||
tapCmd.Flags().String(configStructs.ContractFile, defaultTapConfig.ContractFile, "OAS/Swagger file to validate to monitor the contracts")
|
tapCmd.Flags().String(configStructs.ContractFile, defaultTapConfig.ContractFile, "OAS/Swagger file to validate to monitor the contracts")
|
||||||
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
||||||
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
||||||
|
tapCmd.Flags().Bool(configStructs.ProfilerName, defaultTapConfig.Profiler, "Run pprof server")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func RunMizuTap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
||||||
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedValidationRules, serializedContract, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, getSyncEntriesConfig(), config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel()); err != nil {
|
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedValidationRules, serializedContract, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel(), config.Config.Tap.Profiler); err != nil {
|
||||||
var statusError *k8serrors.StatusError
|
var statusError *k8serrors.StatusError
|
||||||
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
||||||
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
||||||
@@ -164,7 +164,6 @@ func getTapMizuAgentConfig() *shared.MizuAgentConfig {
|
|||||||
ServiceMap: config.Config.ServiceMap,
|
ServiceMap: config.Config.ServiceMap,
|
||||||
OAS: config.Config.OAS,
|
OAS: config.Config.OAS,
|
||||||
Telemetry: config.Config.Telemetry,
|
Telemetry: config.Config.Telemetry,
|
||||||
Elastic: config.Config.Elastic,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mizuAgentConfig
|
return &mizuAgentConfig
|
||||||
@@ -292,23 +291,10 @@ func getMizuApiFilteringOptions() (*api.TrafficFilteringOptions, error) {
|
|||||||
return &api.TrafficFilteringOptions{
|
return &api.TrafficFilteringOptions{
|
||||||
PlainTextMaskingRegexes: compiledRegexSlice,
|
PlainTextMaskingRegexes: compiledRegexSlice,
|
||||||
IgnoredUserAgents: config.Config.Tap.IgnoredUserAgents,
|
IgnoredUserAgents: config.Config.Tap.IgnoredUserAgents,
|
||||||
DisableRedaction: config.Config.Tap.DisableRedaction,
|
EnableRedaction: config.Config.Tap.EnableRedaction,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSyncEntriesConfig() *shared.SyncEntriesConfig {
|
|
||||||
if !config.Config.Tap.Analysis && config.Config.Tap.Workspace == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &shared.SyncEntriesConfig{
|
|
||||||
Token: config.Config.Auth.Token,
|
|
||||||
Env: config.Config.Auth.EnvName,
|
|
||||||
Workspace: config.Config.Tap.Workspace,
|
|
||||||
UploadIntervalSec: config.Config.Tap.UploadIntervalSec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func watchApiServerPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
func watchApiServerPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
||||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s$", kubernetes.ApiServerPodName))
|
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s$", kubernetes.ApiServerPodName))
|
||||||
podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex)
|
podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex)
|
||||||
|
|||||||
@@ -85,27 +85,6 @@ func WriteConfig(config *ConfigStruct) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateConfigStruct func(*ConfigStruct)
|
|
||||||
|
|
||||||
func UpdateConfig(updateConfigStruct updateConfigStruct) error {
|
|
||||||
configFile, err := GetConfigWithDefaults()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed getting config with defaults, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := loadConfigFile(Config.ConfigFilePath, configFile); err != nil && !os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("failed getting config file, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateConfigStruct(configFile)
|
|
||||||
|
|
||||||
if err := WriteConfig(configFile); err != nil {
|
|
||||||
return fmt.Errorf("failed writing config, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfigFile(configFilePath string, config *ConfigStruct) error {
|
func loadConfigFile(configFilePath string, config *ConfigStruct) error {
|
||||||
reader, openErr := os.Open(configFilePath)
|
reader, openErr := os.Open(configFilePath)
|
||||||
if openErr != nil {
|
if openErr != nil {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ type ConfigStruct struct {
|
|||||||
Version configStructs.VersionConfig `yaml:"version"`
|
Version configStructs.VersionConfig `yaml:"version"`
|
||||||
View configStructs.ViewConfig `yaml:"view"`
|
View configStructs.ViewConfig `yaml:"view"`
|
||||||
Logs configStructs.LogsConfig `yaml:"logs"`
|
Logs configStructs.LogsConfig `yaml:"logs"`
|
||||||
Auth configStructs.AuthConfig `yaml:"auth"`
|
|
||||||
Config configStructs.ConfigConfig `yaml:"config,omitempty"`
|
Config configStructs.ConfigConfig `yaml:"config,omitempty"`
|
||||||
AgentImage string `yaml:"agent-image,omitempty" readonly:""`
|
AgentImage string `yaml:"agent-image,omitempty" readonly:""`
|
||||||
ImagePullPolicyStr string `yaml:"image-pull-policy" default:"Always"`
|
ImagePullPolicyStr string `yaml:"image-pull-policy" default:"Always"`
|
||||||
@@ -41,7 +40,6 @@ type ConfigStruct struct {
|
|||||||
LogLevelStr string `yaml:"log-level,omitempty" default:"INFO" readonly:""`
|
LogLevelStr string `yaml:"log-level,omitempty" default:"INFO" readonly:""`
|
||||||
ServiceMap bool `yaml:"service-map" default:"true"`
|
ServiceMap bool `yaml:"service-map" default:"true"`
|
||||||
OAS bool `yaml:"oas" default:"true"`
|
OAS bool `yaml:"oas" default:"true"`
|
||||||
Elastic shared.ElasticConfig `yaml:"elastic"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *ConfigStruct) validate() error {
|
func (config *ConfigStruct) validate() error {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package configStructs
|
|
||||||
|
|
||||||
type AuthConfig struct {
|
|
||||||
EnvName string `yaml:"env-name" default:"up9.app"`
|
|
||||||
Token string `yaml:"token"`
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
package configStructs
|
package configStructs
|
||||||
|
|
||||||
|
const (
|
||||||
|
OutInstallName = "out"
|
||||||
|
)
|
||||||
|
|
||||||
type InstallConfig struct {
|
type InstallConfig struct {
|
||||||
TemplateUrl string `yaml:"template-url" default:"https://storage.googleapis.com/static.up9.io/mizu/helm-template"`
|
TemplateUrl string `yaml:"template-url" default:"https://storage.googleapis.com/static.up9.io/mizu/helm-template"`
|
||||||
TemplateName string `yaml:"template-name" default:"helm-template.yaml"`
|
TemplateName string `yaml:"template-name" default:"helm-template.yaml"`
|
||||||
|
Out bool `yaml:"out"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package configStructs
|
package configStructs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -18,42 +17,38 @@ import (
|
|||||||
const (
|
const (
|
||||||
GuiPortTapName = "gui-port"
|
GuiPortTapName = "gui-port"
|
||||||
NamespacesTapName = "namespaces"
|
NamespacesTapName = "namespaces"
|
||||||
AnalysisTapName = "analysis"
|
|
||||||
AllNamespacesTapName = "all-namespaces"
|
AllNamespacesTapName = "all-namespaces"
|
||||||
PlainTextFilterRegexesTapName = "regex-masking"
|
PlainTextFilterRegexesTapName = "regex-masking"
|
||||||
DisableRedactionTapName = "no-redact"
|
EnableRedactionTapName = "redact"
|
||||||
HumanMaxEntriesDBSizeTapName = "max-entries-db-size"
|
HumanMaxEntriesDBSizeTapName = "max-entries-db-size"
|
||||||
InsertionFilterName = "insertion-filter"
|
InsertionFilterName = "insertion-filter"
|
||||||
DryRunTapName = "dry-run"
|
DryRunTapName = "dry-run"
|
||||||
WorkspaceTapName = "workspace"
|
|
||||||
EnforcePolicyFile = "traffic-validation-file"
|
EnforcePolicyFile = "traffic-validation-file"
|
||||||
ContractFile = "contract"
|
ContractFile = "contract"
|
||||||
ServiceMeshName = "service-mesh"
|
ServiceMeshName = "service-mesh"
|
||||||
TlsName = "tls"
|
TlsName = "tls"
|
||||||
|
ProfilerName = "profiler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TapConfig struct {
|
type TapConfig struct {
|
||||||
UploadIntervalSec int `yaml:"upload-interval" default:"10"`
|
|
||||||
PodRegexStr string `yaml:"regex" default:".*"`
|
PodRegexStr string `yaml:"regex" default:".*"`
|
||||||
GuiPort uint16 `yaml:"gui-port" default:"8899"`
|
GuiPort uint16 `yaml:"gui-port" default:"8899"`
|
||||||
ProxyHost string `yaml:"proxy-host" default:"127.0.0.1"`
|
ProxyHost string `yaml:"proxy-host" default:"127.0.0.1"`
|
||||||
Namespaces []string `yaml:"namespaces"`
|
Namespaces []string `yaml:"namespaces"`
|
||||||
Analysis bool `yaml:"analysis" default:"false"`
|
|
||||||
AllNamespaces bool `yaml:"all-namespaces" default:"false"`
|
AllNamespaces bool `yaml:"all-namespaces" default:"false"`
|
||||||
PlainTextFilterRegexes []string `yaml:"regex-masking"`
|
PlainTextFilterRegexes []string `yaml:"regex-masking"`
|
||||||
IgnoredUserAgents []string `yaml:"ignored-user-agents"`
|
IgnoredUserAgents []string `yaml:"ignored-user-agents"`
|
||||||
DisableRedaction bool `yaml:"no-redact" default:"false"`
|
EnableRedaction bool `yaml:"redact" default:"false"`
|
||||||
HumanMaxEntriesDBSize string `yaml:"max-entries-db-size" default:"200MB"`
|
HumanMaxEntriesDBSize string `yaml:"max-entries-db-size" default:"200MB"`
|
||||||
InsertionFilter string `yaml:"insertion-filter" default:""`
|
InsertionFilter string `yaml:"insertion-filter" default:""`
|
||||||
DryRun bool `yaml:"dry-run" default:"false"`
|
DryRun bool `yaml:"dry-run" default:"false"`
|
||||||
Workspace string `yaml:"workspace"`
|
|
||||||
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
||||||
ContractFile string `yaml:"contract"`
|
ContractFile string `yaml:"contract"`
|
||||||
AskUploadConfirmation bool `yaml:"ask-upload-confirmation" default:"true"`
|
|
||||||
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
||||||
TapperResources shared.Resources `yaml:"tapper-resources"`
|
TapperResources shared.Resources `yaml:"tapper-resources"`
|
||||||
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
||||||
Tls bool `yaml:"tls" default:"false"`
|
Tls bool `yaml:"tls" default:"false"`
|
||||||
|
Profiler bool `yaml:"profiler" default:"false"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *TapConfig) PodRegex() *regexp.Regexp {
|
func (config *TapConfig) PodRegex() *regexp.Regexp {
|
||||||
@@ -92,16 +87,5 @@ func (config *TapConfig) Validate() error {
|
|||||||
return fmt.Errorf("Could not parse --%s value %s", HumanMaxEntriesDBSizeTapName, config.HumanMaxEntriesDBSize)
|
return fmt.Errorf("Could not parse --%s value %s", HumanMaxEntriesDBSizeTapName, config.HumanMaxEntriesDBSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Workspace != "" {
|
|
||||||
workspaceRegex, _ := regexp.Compile("[A-Za-z0-9][-A-Za-z0-9_.]*[A-Za-z0-9]+$")
|
|
||||||
if len(config.Workspace) > 63 || !workspaceRegex.MatchString(config.Workspace) {
|
|
||||||
return errors.New("invalid workspace name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Analysis && config.Workspace != "" {
|
|
||||||
return fmt.Errorf("Can't run with both --%s and --%s flags", AnalysisTapName, WorkspaceTapName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/russross/blackfriday v1.6.0 // indirect
|
github.com/russross/blackfriday v1.6.0 // indirect
|
||||||
github.com/stretchr/testify v1.7.0 // indirect
|
github.com/stretchr/testify v1.7.0 // indirect
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
github.com/xlab/treeprint v1.1.0 // indirect
|
github.com/xlab/treeprint v1.1.0 // indirect
|
||||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
||||||
@@ -104,3 +105,5 @@ replace github.com/up9inc/mizu/logger v0.0.0 => ../logger
|
|||||||
replace github.com/up9inc/mizu/shared v0.0.0 => ../shared
|
replace github.com/up9inc/mizu/shared v0.0.0 => ../shared
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../tap/dbgctl
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ var (
|
|||||||
BuildTimestamp = "" // this var is overridden using ldflags in makefile when building
|
BuildTimestamp = "" // this var is overridden using ldflags in makefile when building
|
||||||
RBACVersion = "v1"
|
RBACVersion = "v1"
|
||||||
Platform = ""
|
Platform = ""
|
||||||
InstallModePersistentVolumeSizeBufferBytes = int64(500 * 1000 * 1000) //500mb
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const DEVENVVAR = "MIZU_DISABLE_TELEMTRY"
|
const DEVENVVAR = "MIZU_DISABLE_TELEMTRY"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedContract string, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, syncEntriesConfig *shared.SyncEntriesConfig, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level) (bool, error) {
|
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedContract string, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level, profiler bool) (bool, error) {
|
||||||
if !isNsRestrictedMode {
|
if !isNsRestrictedMode {
|
||||||
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -45,11 +45,11 @@ func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.
|
|||||||
KetoImage: "",
|
KetoImage: "",
|
||||||
ServiceAccountName: serviceAccountName,
|
ServiceAccountName: serviceAccountName,
|
||||||
IsNamespaceRestricted: isNsRestrictedMode,
|
IsNamespaceRestricted: isNsRestrictedMode,
|
||||||
SyncEntriesConfig: syncEntriesConfig,
|
|
||||||
MaxEntriesDBSizeBytes: maxEntriesDBSizeBytes,
|
MaxEntriesDBSizeBytes: maxEntriesDBSizeBytes,
|
||||||
Resources: apiServerResources,
|
Resources: apiServerResources,
|
||||||
ImagePullPolicy: imagePullPolicy,
|
ImagePullPolicy: imagePullPolicy,
|
||||||
LogLevel: logLevel,
|
LogLevel: logLevel,
|
||||||
|
Profiler: profiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createMizuApiServerPod(ctx, kubernetesProvider, opts); err != nil {
|
if err := createMizuApiServerPod(ctx, kubernetesProvider, opts); err != nil {
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package uiUtils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AskForConfirmation(s string) bool {
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
|
|
||||||
fmt.Printf(Magenta, s)
|
|
||||||
|
|
||||||
response, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Fatalf("Error while reading confirmation string, err: %v", err)
|
|
||||||
}
|
|
||||||
response = strings.ToLower(strings.TrimSpace(response))
|
|
||||||
if response == "" || response == "y" || response == "yes" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package up9
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsTokenValid(tokenString string, envName string) bool {
|
|
||||||
whoAmIUrl, _ := url.Parse(fmt.Sprintf("https://trcc.%s/admin/whoami", envName))
|
|
||||||
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodGet,
|
|
||||||
URL: whoAmIUrl,
|
|
||||||
Header: map[string][]string{
|
|
||||||
"Authorization": {fmt.Sprintf("bearer %s", tokenString)},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer response.Body.Close()
|
|
||||||
|
|
||||||
return response.StatusCode == http.StatusOK
|
|
||||||
}
|
|
||||||
12
devops/install-capstone.sh
Executable file
12
devops/install-capstone.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SUDO=''
|
||||||
|
if (( $EUID != 0 )); then
|
||||||
|
SUDO='sudo'
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
||||||
|
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone \
|
||||||
|
&& cd capstone \
|
||||||
|
&& CAPSTONE_ARCHS="aarch64 x86" ./make.sh \
|
||||||
|
&& $SUDO ./make.sh install
|
||||||
@@ -17,4 +17,11 @@ RUN curl https://www.tcpdump.org/release/libpcap-1.10.1.tar.gz -Lo ./libpcap.tar
|
|||||||
WORKDIR /work/libpcap
|
WORKDIR /work/libpcap
|
||||||
RUN ./configure --host=arm && make \
|
RUN ./configure --host=arm && make \
|
||||||
&& cp /work/libpcap/libpcap.a /usr/xcc/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/*/
|
&& cp /work/libpcap/libpcap.a /usr/xcc/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/*/
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
|
# Build and install Capstone from source
|
||||||
|
RUN curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
||||||
|
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone
|
||||||
|
WORKDIR /work/capstone
|
||||||
|
RUN CAPSTONE_ARCHS="aarch64" CAPSTONE_STATIC=yes ./make.sh \
|
||||||
|
&& cp /work/capstone/libcapstone.a /usr/xcc/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/*/
|
||||||
4
devops/linux-arm64-musl-go-libpcap-capstone/build-push.sh
Executable file
4
devops/linux-arm64-musl-go-libpcap-capstone/build-push.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker build . -t up9inc/linux-arm64-musl-go-libpcap-capstone && docker push up9inc/linux-arm64-musl-go-libpcap-capstone
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
docker build . -t up9inc/linux-arm64-musl-go-libpcap && docker push up9inc/linux-arm64-musl-go-libpcap
|
|
||||||
@@ -29,3 +29,11 @@ RUN curl https://www.tcpdump.org/release/libpcap-1.10.1.tar.gz -Lo ./libpcap.tar
|
|||||||
WORKDIR /libpcap
|
WORKDIR /libpcap
|
||||||
RUN ./configure --host=x86_64 && make \
|
RUN ./configure --host=x86_64 && make \
|
||||||
&& cp /libpcap/libpcap.a /usr/local/musl/lib/gcc/x86_64-unknown-linux-musl/*/
|
&& cp /libpcap/libpcap.a /usr/local/musl/lib/gcc/x86_64-unknown-linux-musl/*/
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
# Build and install Capstone from source
|
||||||
|
RUN curl https://github.com/capstone-engine/capstone/archive/4.0.2.tar.gz -Lo ./capstone.tar.gz \
|
||||||
|
&& tar -xzf capstone.tar.gz && mv ./capstone-* ./capstone
|
||||||
|
WORKDIR /capstone
|
||||||
|
RUN ./make.sh \
|
||||||
|
&& cp /capstone/libcapstone.a /usr/local/musl/lib/gcc/x86_64-unknown-linux-musl/*/
|
||||||
4
devops/linux-x86_64-musl-go-libpcap-capstone/build-push.sh
Executable file
4
devops/linux-x86_64-musl-go-libpcap-capstone/build-push.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker build . -t up9inc/linux-x86_64-musl-go-libpcap-capstone && docker push up9inc/linux-x86_64-musl-go-libpcap-capstone
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
docker build . -t up9inc/linux-x86_64-musl-go-libpcap && docker push up9inc/linux-x86_64-musl-go-libpcap
|
|
||||||
107
performance_analysis/README.md
Normal file
107
performance_analysis/README.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
# Performance analysis
|
||||||
|
|
||||||
|
This directory contains tools for analyzing tapper performance.
|
||||||
|
|
||||||
|
# Periodic tapper logs
|
||||||
|
|
||||||
|
In tapper logs there are some periodic lines that shows its internal state and consumed resources.
|
||||||
|
|
||||||
|
Internal state example (formatted and commented):
|
||||||
|
```
|
||||||
|
stats - {
|
||||||
|
"processedBytes":468940592, // how many bytes we read from pcap
|
||||||
|
"packetsCount":174883, // how many packets we read from pcap
|
||||||
|
"tcpPacketsCount":174883, // how many tcp packets we read from pcap
|
||||||
|
"reassembledTcpPayloadsCount":66893, // how many chunks sent to tcp stream
|
||||||
|
"matchedPairs":24821, // how many request response pairs found
|
||||||
|
"droppedTcpStreams":2 // how many tcp streams remained stale and dropped
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Consumed resources example (formatted and commented):
|
||||||
|
```
|
||||||
|
mem: 24441240, // golang heap size
|
||||||
|
goroutines: 29, // how many goroutines
|
||||||
|
cpu: 91.208791, // how much cpu the tapper process consume (in percentage per core)
|
||||||
|
cores: 16, // how many cores there are on the machine
|
||||||
|
rss: 87052288 // how many bytes held by the tapper process
|
||||||
|
```
|
||||||
|
|
||||||
|
# Plot tapper logs
|
||||||
|
|
||||||
|
In order to plot a tapper log or many logs into a graph, use the `plot_from_tapper_logs.py` util.
|
||||||
|
|
||||||
|
It gets a list of tapper logs as a parameter, and output an image with a nice graph.
|
||||||
|
|
||||||
|
The log file names should be named in this format `XX_DESCRIPTION.log` when XX is the number between determining the color of the output graph and description is the name of the series. It allows for easy comparison between various modes.
|
||||||
|
|
||||||
|
Example run:
|
||||||
|
```
|
||||||
|
cd $MIZU_HOME/performance_analysis
|
||||||
|
virtualenv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
python plot_from_tapper_logs.py 00_tapper.log
|
||||||
|
```
|
||||||
|
|
||||||
|
# Tapper Modes
|
||||||
|
|
||||||
|
Every packet seen by the tapper is processed in a pipeline that contains various stages.
|
||||||
|
* Pcap - Read the packet from libpcap
|
||||||
|
* Assembler - Assemble the packet into a TcpStream
|
||||||
|
* TcpStream - Hold stream information and TcpReaders
|
||||||
|
* Dissectors - Read from TcpReader and recognize the packet content and protocol.
|
||||||
|
* Emit - Marshal the request response pair into a Json
|
||||||
|
* Send - Send the Json to Api Server
|
||||||
|
|
||||||
|
Tapper can be run with various debug modes:
|
||||||
|
* No Pcap - Start the tapper process, but don't read from any packets from pcap
|
||||||
|
* No Assembler - Read packets from pcap, but don't assemble them
|
||||||
|
* No TcpStream - Assemble the packets, but don't create TcpStream for them
|
||||||
|
* No Dissectors - Create a TcpStream for the packets, but don't dissect their content
|
||||||
|
* No Emit - Dissect the TcpStream, but don't emit the matched request response pair
|
||||||
|
* No Send - Emit the request response pair, but don't send them to the Api Server.
|
||||||
|
* Regular mode
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Run benchmark with various tapper modes
|
||||||
|
|
||||||
|
## Prerequisite
|
||||||
|
|
||||||
|
In order to run the benchmark you probably want:
|
||||||
|
1. An up and running Api Server
|
||||||
|
2. An up and running Basenine
|
||||||
|
3. An up and running UI (optional)
|
||||||
|
4. An up and running test server, like nginx, that can return a known payload at a known endpoint.
|
||||||
|
5. Set MIZU_HOME environment variable to points to mizu directory
|
||||||
|
6. Install the `hey` tool
|
||||||
|
|
||||||
|
## Running the benchmark
|
||||||
|
|
||||||
|
In order to run a benchmark use the `run_tapper_benchmark.sh` script.
|
||||||
|
|
||||||
|
Example run:
|
||||||
|
```
|
||||||
|
cd $MIZU_HOME/performance_analysis
|
||||||
|
source venv/bin/activate # Assuming you already run plot_from_tapper_logs.py
|
||||||
|
./run_tapper_benchmark.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Running it without params use the default values, use the following environment variables for customization:
|
||||||
|
```
|
||||||
|
export=MIZU_BENCHMARK_OUTPUT_DIR=/path/to/dir # Set the output directory for tapper logs and graph
|
||||||
|
export=MIZU_BENCHMARK_CLIENT_PERIOD=1m # How long each test run
|
||||||
|
export=MIZU_BENCHMARK_URL=http://server:port/path # The URL to use for the benchmarking process (the test server endpoint)
|
||||||
|
export=MIZU_BENCHMARK_RUN_COUNT=3 # How many times each tapper mode should run
|
||||||
|
export=MIZU_BENCHMARK_QPS=250 # How many queries per second the each client should send to the test server
|
||||||
|
export=MIZU_BENCHMARK_CLIENTS_COUNT=5 # How many clients should run in parallel during the benchmark
|
||||||
|
```
|
||||||
|
|
||||||
|
# Example output graph
|
||||||
|
|
||||||
|
An example output graph from a 15 min run with 15K payload and 1000 QPS looks like
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
BIN
performance_analysis/example-graph.png
Normal file
BIN
performance_analysis/example-graph.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 327 KiB |
182
performance_analysis/plot_from_tapper_logs.py
Normal file
182
performance_analysis/plot_from_tapper_logs.py
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import typing
|
||||||
|
|
||||||
|
COLORMAP = plt.get_cmap('turbo')
|
||||||
|
|
||||||
|
# Extract cpu and rss samples from log files and plot them
|
||||||
|
# Input: List of log files
|
||||||
|
#
|
||||||
|
# example:
|
||||||
|
# python plot_from_tapper_logs.py 01_no_pcap_01.log 99_normal_00.log
|
||||||
|
#
|
||||||
|
# The script assumes that the log file names start with a number (pattern '\d+')
|
||||||
|
# and groups based on this number. Files that start will the same number will be plotted with the same color.
|
||||||
|
# Change group_pattern to an empty string to disable this, or change to a regex of your liking.
|
||||||
|
|
||||||
|
|
||||||
|
def get_sample(name: str, line: str, default_value: float):
|
||||||
|
pattern = name + r': ?(\d+(\.\d+)?)'
|
||||||
|
maybe_sample = re.findall(pattern, line)
|
||||||
|
if len(maybe_sample) == 0:
|
||||||
|
return default_value
|
||||||
|
|
||||||
|
sample = float(maybe_sample[0][0])
|
||||||
|
return sample
|
||||||
|
|
||||||
|
|
||||||
|
def append_sample(name: str, line: str, samples: typing.List[float]):
|
||||||
|
sample = get_sample(name, line, -1)
|
||||||
|
|
||||||
|
if sample == -1:
|
||||||
|
return
|
||||||
|
|
||||||
|
samples.append(sample)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_samples(f: typing.IO) -> typing.Tuple[pd.Series, pd.Series, pd.Series, pd.Series, pd.Series, pd.Series, pd.Series, pd.Series]:
|
||||||
|
cpu_samples = []
|
||||||
|
rss_samples = []
|
||||||
|
count_samples = []
|
||||||
|
matched_samples = []
|
||||||
|
live_samples = []
|
||||||
|
processed_samples = []
|
||||||
|
heap_samples = []
|
||||||
|
goroutines_samples = []
|
||||||
|
for line in f:
|
||||||
|
append_sample('cpu', line, cpu_samples)
|
||||||
|
append_sample('rss', line, rss_samples)
|
||||||
|
ignored_packets_count = get_sample('"ignoredPacketsCount"', line, -1)
|
||||||
|
packets_count = get_sample('"packetsCount"', line, -1)
|
||||||
|
if ignored_packets_count != -1 and packets_count != -1:
|
||||||
|
count_samples.append(packets_count - ignored_packets_count)
|
||||||
|
append_sample('"matchedPairs"', line, matched_samples)
|
||||||
|
append_sample('"liveTcpStreams"', line, live_samples)
|
||||||
|
append_sample('"processedBytes"', line, processed_samples)
|
||||||
|
append_sample('mem', line, heap_samples)
|
||||||
|
append_sample('goroutines', line, goroutines_samples)
|
||||||
|
|
||||||
|
cpu_samples = pd.Series(cpu_samples)
|
||||||
|
rss_samples = pd.Series(rss_samples)
|
||||||
|
count_samples = pd.Series(count_samples)
|
||||||
|
matched_samples = pd.Series(matched_samples)
|
||||||
|
live_samples = pd.Series(live_samples)
|
||||||
|
processed_samples = pd.Series(processed_samples)
|
||||||
|
heap_samples = pd.Series(heap_samples)
|
||||||
|
goroutines_samples = pd.Series(goroutines_samples)
|
||||||
|
|
||||||
|
return cpu_samples, rss_samples, count_samples, matched_samples, live_samples, processed_samples, heap_samples, goroutines_samples
|
||||||
|
|
||||||
|
|
||||||
|
def plot(ax, df: pd.DataFrame, title: str, xlabel: str, ylabel: str, group_pattern: typing.Optional[str]):
|
||||||
|
if group_pattern:
|
||||||
|
color = get_group_color(df.columns, group_pattern)
|
||||||
|
df.plot(color=color, ax=ax)
|
||||||
|
else:
|
||||||
|
df.plot(cmap=COLORMAP, ax=ax)
|
||||||
|
|
||||||
|
ax.ticklabel_format(style='plain')
|
||||||
|
plt.title(title)
|
||||||
|
plt.legend()
|
||||||
|
plt.xlabel(xlabel)
|
||||||
|
plt.ylabel(ylabel)
|
||||||
|
|
||||||
|
|
||||||
|
def get_group_color(names, pattern):
|
||||||
|
props = [int(re.findall(pattern, pathlib.Path(name).name)[0]) for name in names]
|
||||||
|
key = dict(zip(sorted(list(set(props))), range(len(set(props)))))
|
||||||
|
n_colors = len(key)
|
||||||
|
color_options = plt.get_cmap('jet')(np.linspace(0, 1, n_colors))
|
||||||
|
groups = [key[prop] for prop in props]
|
||||||
|
color = color_options[groups] # type: ignore
|
||||||
|
return color
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
filenames = sys.argv[1:]
|
||||||
|
|
||||||
|
cpu_samples_all_files = []
|
||||||
|
rss_samples_all_files = []
|
||||||
|
count_samples_all_files = []
|
||||||
|
matched_samples_all_files = []
|
||||||
|
live_samples_all_files = []
|
||||||
|
processed_samples_all_files = []
|
||||||
|
heap_samples_all_files = []
|
||||||
|
goroutines_samples_all_files = []
|
||||||
|
|
||||||
|
for ii, filename in enumerate(filenames):
|
||||||
|
print("Analyzing {}".format(filename))
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
cpu_samples, rss_samples, count_samples, matched_samples, live_samples, processed_samples, heap_samples, goroutines_samples = extract_samples(f)
|
||||||
|
|
||||||
|
cpu_samples.name = pathlib.Path(filename).name
|
||||||
|
rss_samples.name = pathlib.Path(filename).name
|
||||||
|
count_samples.name = pathlib.Path(filename).name
|
||||||
|
matched_samples.name = pathlib.Path(filename).name
|
||||||
|
live_samples.name = pathlib.Path(filename).name
|
||||||
|
processed_samples.name = pathlib.Path(filename).name
|
||||||
|
heap_samples.name = pathlib.Path(filename).name
|
||||||
|
goroutines_samples.name = pathlib.Path(filename).name
|
||||||
|
|
||||||
|
cpu_samples_all_files.append(cpu_samples)
|
||||||
|
rss_samples_all_files.append(rss_samples)
|
||||||
|
count_samples_all_files.append(count_samples)
|
||||||
|
matched_samples_all_files.append(matched_samples)
|
||||||
|
live_samples_all_files.append(live_samples)
|
||||||
|
processed_samples_all_files.append(processed_samples)
|
||||||
|
heap_samples_all_files.append(heap_samples)
|
||||||
|
goroutines_samples_all_files.append(goroutines_samples)
|
||||||
|
|
||||||
|
cpu_samples_df = pd.concat(cpu_samples_all_files, axis=1)
|
||||||
|
rss_samples_df = pd.concat(rss_samples_all_files, axis=1)
|
||||||
|
count_samples_df = pd.concat(count_samples_all_files, axis=1)
|
||||||
|
matched_samples_df = pd.concat(matched_samples_all_files, axis=1)
|
||||||
|
live_samples_df = pd.concat(live_samples_all_files, axis=1)
|
||||||
|
processed_samples_df = pd.concat(processed_samples_all_files, axis=1)
|
||||||
|
heap_samples_df = pd.concat(heap_samples_all_files, axis=1)
|
||||||
|
goroutines_samples_df = pd.concat(goroutines_samples_all_files, axis=1)
|
||||||
|
|
||||||
|
group_pattern = r'^\d+'
|
||||||
|
|
||||||
|
cpu_plot = plt.subplot(8, 2, 1)
|
||||||
|
plot(cpu_plot, cpu_samples_df, 'cpu', '', 'cpu (%)', group_pattern)
|
||||||
|
cpu_plot.legend().remove()
|
||||||
|
|
||||||
|
mem_plot = plt.subplot(8, 2, 2)
|
||||||
|
plot(mem_plot, (rss_samples_df / 1024 / 1024), 'rss', '', 'mem (mega)', group_pattern)
|
||||||
|
mem_plot.legend(loc='center left', bbox_to_anchor=(1, 0.5))
|
||||||
|
|
||||||
|
packets_plot = plt.subplot(8, 2, 3)
|
||||||
|
plot(packets_plot, count_samples_df, 'packetsCount', '', 'packetsCount', group_pattern)
|
||||||
|
packets_plot.legend().remove()
|
||||||
|
|
||||||
|
matched_plot = plt.subplot(8, 2, 4)
|
||||||
|
plot(matched_plot, matched_samples_df, 'matchedCount', '', 'matchedCount', group_pattern)
|
||||||
|
matched_plot.legend().remove()
|
||||||
|
|
||||||
|
live_plot = plt.subplot(8, 2, 5)
|
||||||
|
plot(live_plot, live_samples_df, 'liveStreamsCount', '', 'liveStreamsCount', group_pattern)
|
||||||
|
live_plot.legend().remove()
|
||||||
|
|
||||||
|
processed_plot = plt.subplot(8, 2, 6)
|
||||||
|
plot(processed_plot, (processed_samples_df / 1024 / 1024), 'processedBytes', '', 'bytes (mega)', group_pattern)
|
||||||
|
processed_plot.legend().remove()
|
||||||
|
|
||||||
|
heap_plot = plt.subplot(8, 2, 7)
|
||||||
|
plot(heap_plot, (heap_samples_df / 1024 / 1024), 'heap', '', 'heap (mega)', group_pattern)
|
||||||
|
heap_plot.legend().remove()
|
||||||
|
|
||||||
|
goroutines_plot = plt.subplot(8, 2, 8)
|
||||||
|
plot(goroutines_plot, goroutines_samples_df, 'goroutines', '', 'goroutines', group_pattern)
|
||||||
|
goroutines_plot.legend().remove()
|
||||||
|
|
||||||
|
fig = plt.gcf()
|
||||||
|
fig.set_size_inches(20, 18)
|
||||||
|
|
||||||
|
print('Saving graph to graph.png')
|
||||||
|
plt.savefig('graph.png', bbox_inches='tight')
|
||||||
|
|
||||||
2
performance_analysis/requirements.txt
Normal file
2
performance_analysis/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
matplotlib
|
||||||
|
pandas
|
||||||
100
performance_analysis/run_tapper_benchmark.sh
Executable file
100
performance_analysis/run_tapper_benchmark.sh
Executable file
@@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
[ -z "$MIZU_HOME" ] && { echo "MIZU_HOME is missing"; exit 1; }
|
||||||
|
[ -z "$MIZU_BENCHMARK_OUTPUT_DIR" ] && export MIZU_BENCHMARK_OUTPUT_DIR="/tmp/mizu-benchmark-results-$(date +%d-%m-%H-%M)"
|
||||||
|
[ -z "$MIZU_BENCHMARK_CLIENT_PERIOD" ] && export MIZU_BENCHMARK_CLIENT_PERIOD="1m"
|
||||||
|
[ -z "$MIZU_BENCHMARK_URL" ] && export MIZU_BENCHMARK_URL="http://localhost:8081/data/b.1000.json"
|
||||||
|
[ -z "$MIZU_BENCHMARK_RUN_COUNT" ] && export MIZU_BENCHMARK_RUN_COUNT="3"
|
||||||
|
[ -z "$MIZU_BENCHMARK_QPS" ] && export MIZU_BENCHMARK_QPS="500"
|
||||||
|
[ -z "$MIZU_BENCHMARK_CLIENTS_COUNT" ] && export MIZU_BENCHMARK_CLIENTS_COUNT="5"
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
local message=$@
|
||||||
|
printf "[%s] %s\n" "$(date "+%d-%m %H:%M:%S")" "$message"
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_single_bench() {
|
||||||
|
local mode_num=$1
|
||||||
|
local mode_str=$2
|
||||||
|
|
||||||
|
log "Starting ${mode_num}_${mode_str} (runs: $MIZU_BENCHMARK_RUN_COUNT) (period: $MIZU_BENCHMARK_CLIENT_PERIOD)"
|
||||||
|
|
||||||
|
for ((i=0;i<"$MIZU_BENCHMARK_RUN_COUNT";i++)); do
|
||||||
|
log " $i: Running tapper"
|
||||||
|
rm -f tapper.log
|
||||||
|
tapper_args=("--tap" "--api-server-address" "ws://localhost:8899/wsTapper" "-stats" "10" "-ignore-ports" "8899,9099")
|
||||||
|
if [[ $(uname) == "Darwin" ]]
|
||||||
|
then
|
||||||
|
tapper_args+=("-i" "lo0" "-"decoder "Loopback")
|
||||||
|
else
|
||||||
|
tapper_args+=("-i" "lo")
|
||||||
|
fi
|
||||||
|
nohup ./agent/build/mizuagent ${tapper_args[@]} > tapper.log 2>&1 &
|
||||||
|
|
||||||
|
log " $i: Running client (hey)"
|
||||||
|
hey -z $MIZU_BENCHMARK_CLIENT_PERIOD -c $MIZU_BENCHMARK_CLIENTS_COUNT -q $MIZU_BENCHMARK_QPS $MIZU_BENCHMARK_URL > /dev/null || return 1
|
||||||
|
|
||||||
|
log " $i: Killing tapper"
|
||||||
|
kill -9 $(ps -ef | grep agent/build/mizuagent | grep tap | grep -v grep | awk '{ print $2 }') > /dev/null 2>&1
|
||||||
|
|
||||||
|
local output_file=$MIZU_BENCHMARK_OUTPUT_DIR/${mode_num}_${mode_str}_${i}.log
|
||||||
|
log " $i: Moving output to $output_file"
|
||||||
|
mv tapper.log $output_file || return 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_bench_graph() {
|
||||||
|
cd performance_analysis/ || return 1
|
||||||
|
source venv/bin/activate
|
||||||
|
python plot_from_tapper_logs.py $MIZU_BENCHMARK_OUTPUT_DIR/*.log || return 1
|
||||||
|
mv graph.png $MIZU_BENCHMARK_OUTPUT_DIR || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p $MIZU_BENCHMARK_OUTPUT_DIR
|
||||||
|
rm -f $MIZU_BENCHMARK_OUTPUT_DIR/*
|
||||||
|
log "Writing output to $MIZU_BENCHMARK_OUTPUT_DIR"
|
||||||
|
|
||||||
|
cd $MIZU_HOME || exit 1
|
||||||
|
|
||||||
|
export HOST_MODE=0
|
||||||
|
export SENSITIVE_DATA_FILTERING_OPTIONS='{"EnableRedaction": false}'
|
||||||
|
export MIZU_DEBUG_DISABLE_PCAP=false
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_REASSEMBLY=false
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_STREAM=false
|
||||||
|
export MIZU_DEBUG_DISABLE_NON_HTTP_EXTENSSION=false
|
||||||
|
export MIZU_DEBUG_DISABLE_DISSECTORS=false
|
||||||
|
export MIZU_DEBUG_DISABLE_EMITTING=false
|
||||||
|
export MIZU_DEBUG_DISABLE_SENDING=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_PCAP=true
|
||||||
|
run_single_bench "01" "no_pcap" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_PCAP=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_REASSEMBLY=true
|
||||||
|
run_single_bench "02" "no_assembler" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_REASSEMBLY=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_STREAM=true
|
||||||
|
run_single_bench "03" "no_tcp_stream" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_TCP_STREAM=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_NON_HTTP_EXTENSSION=true
|
||||||
|
run_single_bench "04" "only_http" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_NON_HTTP_EXTENSSION=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_DISSECTORS=true
|
||||||
|
run_single_bench "05" "no_dissectors" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_DISSECTORS=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_EMITTING=true
|
||||||
|
run_single_bench "06" "no_emit" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_EMITTING=false
|
||||||
|
|
||||||
|
export MIZU_DEBUG_DISABLE_SENDING=true
|
||||||
|
run_single_bench "07" "no_send" || exit 1
|
||||||
|
export MIZU_DEBUG_DISABLE_SENDING=false
|
||||||
|
|
||||||
|
run_single_bench "08" "normal" || exit 1
|
||||||
|
|
||||||
|
generate_bench_graph || exit 1
|
||||||
|
log "Output written to to $MIZU_BENCHMARK_OUTPUT_DIR"
|
||||||
BIN
performance_analysis/tapper-modes.png
Normal file
BIN
performance_analysis/tapper-modes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 259 KiB |
@@ -2,7 +2,6 @@ package shared
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS"
|
MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS"
|
||||||
SyncEntriesConfigEnvVar = "SYNC_ENTRIES_CONFIG"
|
|
||||||
HostModeEnvVar = "HOST_MODE"
|
HostModeEnvVar = "HOST_MODE"
|
||||||
NodeNameEnvVar = "NODE_NAME"
|
NodeNameEnvVar = "NODE_NAME"
|
||||||
ConfigDirPath = "/app/config/"
|
ConfigDirPath = "/app/config/"
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ require (
|
|||||||
github.com/spf13/cobra v1.3.0 // indirect
|
github.com/spf13/cobra v1.3.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/stretchr/testify v1.7.0 // indirect
|
github.com/stretchr/testify v1.7.0 // indirect
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
github.com/xlab/treeprint v1.1.0 // indirect
|
github.com/xlab/treeprint v1.1.0 // indirect
|
||||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
||||||
@@ -95,3 +96,5 @@ require (
|
|||||||
replace github.com/up9inc/mizu/logger v0.0.0 => ../logger
|
replace github.com/up9inc/mizu/logger v0.0.0 => ../logger
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../tap/api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../tap/dbgctl
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
watchtools "k8s.io/client-go/tools/watch"
|
watchtools "k8s.io/client-go/tools/watch"
|
||||||
@@ -41,7 +40,7 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
clientSet *kubernetes.Clientset
|
clientSet *kubernetes.Clientset
|
||||||
kubernetesConfig clientcmd.ClientConfig
|
kubernetesConfig clientcmd.ClientConfig
|
||||||
clientConfig restclient.Config
|
clientConfig rest.Config
|
||||||
managedBy string
|
managedBy string
|
||||||
createdBy string
|
createdBy string
|
||||||
}
|
}
|
||||||
@@ -88,6 +87,7 @@ func NewProvider(kubeConfigPath string, contextName string) (*Provider, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NewProviderInCluster Used in another repo that calls this function
|
||||||
func NewProviderInCluster() (*Provider, error) {
|
func NewProviderInCluster() (*Provider, error) {
|
||||||
restClientConfig, err := rest.InClusterConfig()
|
restClientConfig, err := rest.InClusterConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -176,22 +176,14 @@ type ApiServerOptions struct {
|
|||||||
KetoImage string
|
KetoImage string
|
||||||
ServiceAccountName string
|
ServiceAccountName string
|
||||||
IsNamespaceRestricted bool
|
IsNamespaceRestricted bool
|
||||||
SyncEntriesConfig *shared.SyncEntriesConfig
|
|
||||||
MaxEntriesDBSizeBytes int64
|
MaxEntriesDBSizeBytes int64
|
||||||
Resources shared.Resources
|
Resources shared.Resources
|
||||||
ImagePullPolicy core.PullPolicy
|
ImagePullPolicy core.PullPolicy
|
||||||
LogLevel logging.Level
|
LogLevel logging.Level
|
||||||
|
Profiler bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, mountVolumeClaim bool, volumeClaimName string, createAuthContainer bool) (*core.Pod, error) {
|
func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, mountVolumeClaim bool, volumeClaimName string, createAuthContainer bool) (*core.Pod, error) {
|
||||||
var marshaledSyncEntriesConfig []byte
|
|
||||||
if opts.SyncEntriesConfig != nil {
|
|
||||||
var err error
|
|
||||||
if marshaledSyncEntriesConfig, err = json.Marshal(opts.SyncEntriesConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configMapVolume := &core.ConfigMapVolumeSource{}
|
configMapVolume := &core.ConfigMapVolumeSource{}
|
||||||
configMapVolume.Name = ConfigMapName
|
configMapVolume.Name = ConfigMapName
|
||||||
|
|
||||||
@@ -212,7 +204,15 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun
|
|||||||
return nil, fmt.Errorf("invalid memory request for %s container", opts.PodName)
|
return nil, fmt.Errorf("invalid memory request for %s container", opts.PodName)
|
||||||
}
|
}
|
||||||
|
|
||||||
command := []string{"./mizuagent", "--api-server"}
|
command := []string{
|
||||||
|
"./mizuagent",
|
||||||
|
"--api-server",
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Profiler {
|
||||||
|
command = append(command, "--profiler")
|
||||||
|
}
|
||||||
|
|
||||||
if opts.IsNamespaceRestricted {
|
if opts.IsNamespaceRestricted {
|
||||||
command = append(command, "--namespace", opts.Namespace)
|
command = append(command, "--namespace", opts.Namespace)
|
||||||
}
|
}
|
||||||
@@ -255,10 +255,6 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun
|
|||||||
VolumeMounts: volumeMounts,
|
VolumeMounts: volumeMounts,
|
||||||
Command: command,
|
Command: command,
|
||||||
Env: []core.EnvVar{
|
Env: []core.EnvVar{
|
||||||
{
|
|
||||||
Name: shared.SyncEntriesConfigEnvVar,
|
|
||||||
Value: string(marshaledSyncEntriesConfig),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: shared.LogLevelEnvVar,
|
Name: shared.LogLevelEnvVar,
|
||||||
Value: opts.LogLevel.String(),
|
Value: opts.LogLevel.String(),
|
||||||
@@ -383,6 +379,16 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun
|
|||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
DNSPolicy: core.DNSClusterFirstWithHostNet,
|
DNSPolicy: core.DNSClusterFirstWithHostNet,
|
||||||
TerminationGracePeriodSeconds: new(int64),
|
TerminationGracePeriodSeconds: new(int64),
|
||||||
|
Tolerations: []core.Toleration{
|
||||||
|
{
|
||||||
|
Operator: core.TolerationOpExists,
|
||||||
|
Effect: core.TaintEffectNoExecute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Operator: core.TolerationOpExists,
|
||||||
|
Effect: core.TaintEffectNoSchedule,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,7 +1100,7 @@ func (provider *Provider) GetKubernetesVersion() (*semver.SemVersion, error) {
|
|||||||
return &serverVersionSemVer, nil
|
return &serverVersionSemVer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getClientSet(config *restclient.Config) (*kubernetes.Clientset, error) {
|
func getClientSet(config *rest.Config) (*kubernetes.Clientset, error) {
|
||||||
clientSet, err := kubernetes.NewForConfig(config)
|
clientSet, err := kubernetes.NewForConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ const (
|
|||||||
WebSocketMessageTypeTappedEntry WebSocketMessageType = "tappedEntry"
|
WebSocketMessageTypeTappedEntry WebSocketMessageType = "tappedEntry"
|
||||||
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
||||||
WebSocketMessageTypeUpdateTappedPods WebSocketMessageType = "tappedPods"
|
WebSocketMessageTypeUpdateTappedPods WebSocketMessageType = "tappedPods"
|
||||||
WebSocketMessageTypeAnalyzeStatus WebSocketMessageType = "analyzeStatus"
|
|
||||||
WebSocketMessageTypeToast WebSocketMessageType = "toast"
|
WebSocketMessageTypeToast WebSocketMessageType = "toast"
|
||||||
WebSocketMessageTypeQueryMetadata WebSocketMessageType = "queryMetadata"
|
WebSocketMessageTypeQueryMetadata WebSocketMessageType = "queryMetadata"
|
||||||
WebSocketMessageTypeStartTime WebSocketMessageType = "startTime"
|
WebSocketMessageTypeStartTime WebSocketMessageType = "startTime"
|
||||||
@@ -45,30 +44,12 @@ type MizuAgentConfig struct {
|
|||||||
ServiceMap bool `json:"serviceMap"`
|
ServiceMap bool `json:"serviceMap"`
|
||||||
OAS bool `json:"oas"`
|
OAS bool `json:"oas"`
|
||||||
Telemetry bool `json:"telemetry"`
|
Telemetry bool `json:"telemetry"`
|
||||||
Elastic ElasticConfig `json:"elastic"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ElasticConfig struct {
|
|
||||||
User string `yaml:"user,omitempty" default:"" readonly:""`
|
|
||||||
Password string `yaml:"password,omitempty" default:"" readonly:""`
|
|
||||||
Url string `yaml:"url,omitempty" default:"" readonly:""`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSocketMessageMetadata struct {
|
type WebSocketMessageMetadata struct {
|
||||||
MessageType WebSocketMessageType `json:"messageType,omitempty"`
|
MessageType WebSocketMessageType `json:"messageType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSocketAnalyzeStatusMessage struct {
|
|
||||||
*WebSocketMessageMetadata
|
|
||||||
AnalyzeStatus AnalyzeStatus `json:"analyzeStatus"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AnalyzeStatus struct {
|
|
||||||
IsAnalyzing bool `json:"isAnalyzing"`
|
|
||||||
RemoteUrl string `json:"remoteUrl"`
|
|
||||||
IsRemoteReady bool `json:"isRemoteReady"`
|
|
||||||
SentCount int `json:"sentCount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebSocketStatusMessage struct {
|
type WebSocketStatusMessage struct {
|
||||||
*WebSocketMessageMetadata
|
*WebSocketMessageMetadata
|
||||||
@@ -123,13 +104,6 @@ type TLSLinkInfo struct {
|
|||||||
ResolvedSourceName string `json:"resolvedSourceName"`
|
ResolvedSourceName string `json:"resolvedSourceName"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncEntriesConfig struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
Env string `json:"env"`
|
|
||||||
Workspace string `json:"workspace"`
|
|
||||||
UploadIntervalSec int `json:"interval"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateWebSocketStatusMessage(tappedPodsStatus []TappedPodStatus) WebSocketStatusMessage {
|
func CreateWebSocketStatusMessage(tappedPodsStatus []TappedPodStatus) WebSocketStatusMessage {
|
||||||
return WebSocketStatusMessage{
|
return WebSocketStatusMessage{
|
||||||
WebSocketMessageMetadata: &WebSocketMessageMetadata{
|
WebSocketMessageMetadata: &WebSocketMessageMetadata{
|
||||||
@@ -148,15 +122,6 @@ func CreateWebSocketTappedPodsMessage(nodeToTappedPodMap NodeToPodsMap) WebSocke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateWebSocketMessageTypeAnalyzeStatus(analyzeStatus AnalyzeStatus) WebSocketAnalyzeStatusMessage {
|
|
||||||
return WebSocketAnalyzeStatusMessage{
|
|
||||||
WebSocketMessageMetadata: &WebSocketMessageMetadata{
|
|
||||||
MessageType: WebSocketMessageTypeAnalyzeStatus,
|
|
||||||
},
|
|
||||||
AnalyzeStatus: analyzeStatus,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HealthResponse struct {
|
type HealthResponse struct {
|
||||||
TappedPods []*PodInfo `json:"tappedPods"`
|
TappedPods []*PodInfo `json:"tappedPods"`
|
||||||
ConnectedTappersCount int `json:"connectedTappersCount"`
|
ConnectedTappersCount int `json:"connectedTappersCount"`
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package shared
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsTokenExpired(tokenString string) (bool, error) {
|
|
||||||
claims, err := getTokenClaims(tokenString)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
expiry := time.Unix(int64(claims["exp"].(float64)), 0)
|
|
||||||
|
|
||||||
return time.Now().After(expiry), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetTokenEmail(tokenString string) (string, error) {
|
|
||||||
claims, err := getTokenClaims(tokenString)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return claims["email"].(string), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTokenClaims(tokenString string) (jwt.MapClaims, error) {
|
|
||||||
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse token, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
claims, ok := token.Claims.(jwt.MapClaims)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("can't convert token's claims to standard claims")
|
|
||||||
}
|
|
||||||
|
|
||||||
return claims, nil
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/martian/har"
|
"github.com/google/martian/har"
|
||||||
|
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const mizuTestEnvVar = "MIZU_TEST"
|
const mizuTestEnvVar = "MIZU_TEST"
|
||||||
@@ -104,11 +106,6 @@ type OutputChannelItem struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProtoIdentifier struct {
|
|
||||||
Protocol *Protocol
|
|
||||||
IsClosedOthers bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReadProgress struct {
|
type ReadProgress struct {
|
||||||
readBytes int
|
readBytes int
|
||||||
lastCurrent int
|
lastCurrent int
|
||||||
@@ -123,6 +120,11 @@ func (p *ReadProgress) Current() (n int) {
|
|||||||
return p.lastCurrent
|
return p.lastCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ReadProgress) Reset() {
|
||||||
|
p.readBytes = 0
|
||||||
|
p.lastCurrent = 0
|
||||||
|
}
|
||||||
|
|
||||||
type Dissector interface {
|
type Dissector interface {
|
||||||
Register(*Extension)
|
Register(*Extension)
|
||||||
Ping()
|
Ping()
|
||||||
@@ -149,8 +151,13 @@ type Emitter interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Emitting) Emit(item *OutputChannelItem) {
|
func (e *Emitting) Emit(item *OutputChannelItem) {
|
||||||
e.OutputChannel <- item
|
|
||||||
e.AppStats.IncMatchedPairs()
|
e.AppStats.IncMatchedPairs()
|
||||||
|
|
||||||
|
if dbgctl.MizuTapperDisableEmitting {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OutputChannel <- item
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
@@ -419,13 +426,11 @@ type TcpReader interface {
|
|||||||
GetCaptureTime() time.Time
|
GetCaptureTime() time.Time
|
||||||
GetEmitter() Emitter
|
GetEmitter() Emitter
|
||||||
GetIsClosed() bool
|
GetIsClosed() bool
|
||||||
GetExtension() *Extension
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TcpStream interface {
|
type TcpStream interface {
|
||||||
SetProtocol(protocol *Protocol)
|
SetProtocol(protocol *Protocol)
|
||||||
GetOrigin() Capture
|
GetOrigin() Capture
|
||||||
GetProtoIdentifier() *ProtoIdentifier
|
|
||||||
GetReqResMatchers() []RequestResponseMatcher
|
GetReqResMatchers() []RequestResponseMatcher
|
||||||
GetIsTapTarget() bool
|
GetIsTapTarget() bool
|
||||||
GetIsClosed() bool
|
GetIsClosed() bool
|
||||||
|
|||||||
@@ -2,4 +2,9 @@ module github.com/up9inc/mizu/tap/api
|
|||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require github.com/google/martian v2.1.0+incompatible
|
require (
|
||||||
|
github.com/google/martian v2.1.0+incompatible
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../dbgctl
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ package api
|
|||||||
type TrafficFilteringOptions struct {
|
type TrafficFilteringOptions struct {
|
||||||
IgnoredUserAgents []string
|
IgnoredUserAgents []string
|
||||||
PlainTextMaskingRegexes []*SerializableRegexp
|
PlainTextMaskingRegexes []*SerializableRegexp
|
||||||
DisableRedaction bool
|
EnableRedaction bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ type AppStats struct {
|
|||||||
ProcessedBytes uint64 `json:"processedBytes"`
|
ProcessedBytes uint64 `json:"processedBytes"`
|
||||||
PacketsCount uint64 `json:"packetsCount"`
|
PacketsCount uint64 `json:"packetsCount"`
|
||||||
TcpPacketsCount uint64 `json:"tcpPacketsCount"`
|
TcpPacketsCount uint64 `json:"tcpPacketsCount"`
|
||||||
|
IgnoredPacketsCount uint64 `json:"ignoredPacketsCount"`
|
||||||
ReassembledTcpPayloadsCount uint64 `json:"reassembledTcpPayloadsCount"`
|
ReassembledTcpPayloadsCount uint64 `json:"reassembledTcpPayloadsCount"`
|
||||||
TlsConnectionsCount uint64 `json:"tlsConnectionsCount"`
|
TlsConnectionsCount uint64 `json:"tlsConnectionsCount"`
|
||||||
MatchedPairs uint64 `json:"matchedPairs"`
|
MatchedPairs uint64 `json:"matchedPairs"`
|
||||||
DroppedTcpStreams uint64 `json:"droppedTcpStreams"`
|
DroppedTcpStreams uint64 `json:"droppedTcpStreams"`
|
||||||
|
LiveTcpStreams uint64 `json:"liveTcpStreams"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *AppStats) IncMatchedPairs() {
|
func (as *AppStats) IncMatchedPairs() {
|
||||||
@@ -33,6 +35,10 @@ func (as *AppStats) IncTcpPacketsCount() {
|
|||||||
atomic.AddUint64(&as.TcpPacketsCount, 1)
|
atomic.AddUint64(&as.TcpPacketsCount, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (as *AppStats) IncIgnoredPacketsCount() {
|
||||||
|
atomic.AddUint64(&as.IgnoredPacketsCount, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func (as *AppStats) IncReassembledTcpPayloadsCount() {
|
func (as *AppStats) IncReassembledTcpPayloadsCount() {
|
||||||
atomic.AddUint64(&as.ReassembledTcpPayloadsCount, 1)
|
atomic.AddUint64(&as.ReassembledTcpPayloadsCount, 1)
|
||||||
}
|
}
|
||||||
@@ -41,6 +47,14 @@ func (as *AppStats) IncTlsConnectionsCount() {
|
|||||||
atomic.AddUint64(&as.TlsConnectionsCount, 1)
|
atomic.AddUint64(&as.TlsConnectionsCount, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (as *AppStats) IncLiveTcpStreams() {
|
||||||
|
atomic.AddUint64(&as.LiveTcpStreams, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AppStats) DecLiveTcpStreams() {
|
||||||
|
atomic.AddUint64(&as.LiveTcpStreams, ^uint64(0))
|
||||||
|
}
|
||||||
|
|
||||||
func (as *AppStats) UpdateProcessedBytes(size uint64) {
|
func (as *AppStats) UpdateProcessedBytes(size uint64) {
|
||||||
atomic.AddUint64(&as.ProcessedBytes, size)
|
atomic.AddUint64(&as.ProcessedBytes, size)
|
||||||
}
|
}
|
||||||
@@ -55,10 +69,12 @@ func (as *AppStats) DumpStats() *AppStats {
|
|||||||
currentAppStats.ProcessedBytes = resetUint64(&as.ProcessedBytes)
|
currentAppStats.ProcessedBytes = resetUint64(&as.ProcessedBytes)
|
||||||
currentAppStats.PacketsCount = resetUint64(&as.PacketsCount)
|
currentAppStats.PacketsCount = resetUint64(&as.PacketsCount)
|
||||||
currentAppStats.TcpPacketsCount = resetUint64(&as.TcpPacketsCount)
|
currentAppStats.TcpPacketsCount = resetUint64(&as.TcpPacketsCount)
|
||||||
|
currentAppStats.IgnoredPacketsCount = resetUint64(&as.IgnoredPacketsCount)
|
||||||
currentAppStats.ReassembledTcpPayloadsCount = resetUint64(&as.ReassembledTcpPayloadsCount)
|
currentAppStats.ReassembledTcpPayloadsCount = resetUint64(&as.ReassembledTcpPayloadsCount)
|
||||||
currentAppStats.TlsConnectionsCount = resetUint64(&as.TlsConnectionsCount)
|
currentAppStats.TlsConnectionsCount = resetUint64(&as.TlsConnectionsCount)
|
||||||
currentAppStats.MatchedPairs = resetUint64(&as.MatchedPairs)
|
currentAppStats.MatchedPairs = resetUint64(&as.MatchedPairs)
|
||||||
currentAppStats.DroppedTcpStreams = resetUint64(&as.DroppedTcpStreams)
|
currentAppStats.DroppedTcpStreams = resetUint64(&as.DroppedTcpStreams)
|
||||||
|
currentAppStats.LiveTcpStreams = as.LiveTcpStreams
|
||||||
|
|
||||||
return currentAppStats
|
return currentAppStats
|
||||||
}
|
}
|
||||||
|
|||||||
15
tap/dbgctl/debug_control.go
Normal file
15
tap/dbgctl/debug_control.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package dbgctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MizuTapperDisablePcap bool = os.Getenv("MIZU_DEBUG_DISABLE_PCAP") == "true"
|
||||||
|
MizuTapperDisableTcpReassembly bool = os.Getenv("MIZU_DEBUG_DISABLE_TCP_REASSEMBLY") == "true"
|
||||||
|
MizuTapperDisableTcpStream bool = os.Getenv("MIZU_DEBUG_DISABLE_TCP_STREAM") == "true"
|
||||||
|
MizuTapperDisableDissectors bool = os.Getenv("MIZU_DEBUG_DISABLE_DISSECTORS") == "true"
|
||||||
|
MizuTapperDisableEmitting bool = os.Getenv("MIZU_DEBUG_DISABLE_EMITTING") == "true"
|
||||||
|
MizuTapperDisableSending bool = os.Getenv("MIZU_DEBUG_DISABLE_SENDING") == "true"
|
||||||
|
MizuTapperDisableNonHttpExtensions bool = os.Getenv("MIZU_DEBUG_DISABLE_NON_HTTP_EXTENSSION") == "true"
|
||||||
|
)
|
||||||
3
tap/dbgctl/go.mod
Normal file
3
tap/dbgctl/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/up9inc/mizu/tap/dbgctl
|
||||||
|
|
||||||
|
go 1.18
|
||||||
@@ -11,7 +11,10 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
github.com/google/martian v2.1.0+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../../dbgctl
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package amqp
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -75,14 +74,10 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
var lastMethodFrameMessage Message
|
var lastMethodFrameMessage Message
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if reader.GetParent().GetProtoIdentifier().Protocol != nil && reader.GetParent().GetProtoIdentifier().Protocol != &protocol {
|
|
||||||
return errors.New("Identified by another protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
frame, err := r.ReadFrame()
|
frame, err := r.ReadFrame()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
// We must read until we see an EOF... very important!
|
// We must read until we see an EOF... very important!
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch f := frame.(type) {
|
switch f := frame.(type) {
|
||||||
@@ -90,6 +85,8 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
// drop
|
// drop
|
||||||
|
|
||||||
case *HeaderFrame:
|
case *HeaderFrame:
|
||||||
|
reader.GetParent().SetProtocol(&protocol)
|
||||||
|
|
||||||
// start content state
|
// start content state
|
||||||
header = f
|
header = f
|
||||||
remaining = int(header.Size)
|
remaining = int(header.Size)
|
||||||
@@ -107,20 +104,22 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *BodyFrame:
|
case *BodyFrame:
|
||||||
|
reader.GetParent().SetProtocol(&protocol)
|
||||||
|
|
||||||
// continue until terminated
|
// continue until terminated
|
||||||
remaining -= len(f.Body)
|
remaining -= len(f.Body)
|
||||||
switch lastMethodFrameMessage.(type) {
|
switch lastMethodFrameMessage.(type) {
|
||||||
case *BasicPublish:
|
case *BasicPublish:
|
||||||
eventBasicPublish.Body = f.Body
|
eventBasicPublish.Body = f.Body
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventBasicPublish, amqpRequest, basicMethodMap[40], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventBasicPublish, amqpRequest, basicMethodMap[40], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
case *BasicDeliver:
|
case *BasicDeliver:
|
||||||
eventBasicDeliver.Body = f.Body
|
eventBasicDeliver.Body = f.Body
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventBasicDeliver, amqpRequest, basicMethodMap[60], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventBasicDeliver, amqpRequest, basicMethodMap[60], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
}
|
}
|
||||||
|
|
||||||
case *MethodFrame:
|
case *MethodFrame:
|
||||||
|
reader.GetParent().SetProtocol(&protocol)
|
||||||
|
|
||||||
lastMethodFrameMessage = f.Method
|
lastMethodFrameMessage = f.Method
|
||||||
switch m := f.Method.(type) {
|
switch m := f.Method.(type) {
|
||||||
case *BasicPublish:
|
case *BasicPublish:
|
||||||
@@ -137,7 +136,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
NoWait: m.NoWait,
|
NoWait: m.NoWait,
|
||||||
Arguments: m.Arguments,
|
Arguments: m.Arguments,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventQueueBind, amqpRequest, queueMethodMap[20], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventQueueBind, amqpRequest, queueMethodMap[20], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
|
|
||||||
case *BasicConsume:
|
case *BasicConsume:
|
||||||
@@ -150,7 +148,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
NoWait: m.NoWait,
|
NoWait: m.NoWait,
|
||||||
Arguments: m.Arguments,
|
Arguments: m.Arguments,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventBasicConsume, amqpRequest, basicMethodMap[20], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventBasicConsume, amqpRequest, basicMethodMap[20], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
|
|
||||||
case *BasicDeliver:
|
case *BasicDeliver:
|
||||||
@@ -170,7 +167,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
NoWait: m.NoWait,
|
NoWait: m.NoWait,
|
||||||
Arguments: m.Arguments,
|
Arguments: m.Arguments,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventQueueDeclare, amqpRequest, queueMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventQueueDeclare, amqpRequest, queueMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
|
|
||||||
case *ExchangeDeclare:
|
case *ExchangeDeclare:
|
||||||
@@ -184,7 +180,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
NoWait: m.NoWait,
|
NoWait: m.NoWait,
|
||||||
Arguments: m.Arguments,
|
Arguments: m.Arguments,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventExchangeDeclare, amqpRequest, exchangeMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventExchangeDeclare, amqpRequest, exchangeMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
|
|
||||||
case *ConnectionStart:
|
case *ConnectionStart:
|
||||||
@@ -195,7 +190,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
Mechanisms: m.Mechanisms,
|
Mechanisms: m.Mechanisms,
|
||||||
Locales: m.Locales,
|
Locales: m.Locales,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventConnectionStart, amqpRequest, connectionMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventConnectionStart, amqpRequest, connectionMethodMap[10], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
|
|
||||||
case *ConnectionClose:
|
case *ConnectionClose:
|
||||||
@@ -205,7 +199,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
ClassId: m.ClassId,
|
ClassId: m.ClassId,
|
||||||
MethodId: m.MethodId,
|
MethodId: m.MethodId,
|
||||||
}
|
}
|
||||||
reader.GetParent().SetProtocol(&protocol)
|
|
||||||
emitAMQP(*eventConnectionClose, amqpRequest, connectionMethodMap[50], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
emitAMQP(*eventConnectionClose, amqpRequest, connectionMethodMap[50], connectionInfo, reader.GetCaptureTime(), reader.GetReadProgress().Current(), reader.GetEmitter(), reader.GetParent().GetOrigin())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,3 @@ func (reader *tcpReader) GetEmitter() api.Emitter {
|
|||||||
func (reader *tcpReader) GetIsClosed() bool {
|
func (reader *tcpReader) GetIsClosed() bool {
|
||||||
return reader.isClosed
|
return reader.isClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reader *tcpReader) GetExtension() *api.Extension {
|
|
||||||
return reader.extension
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,18 +7,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tcpStream struct {
|
type tcpStream struct {
|
||||||
isClosed bool
|
isClosed bool
|
||||||
protoIdentifier *api.ProtoIdentifier
|
isTapTarget bool
|
||||||
isTapTarget bool
|
origin api.Capture
|
||||||
origin api.Capture
|
reqResMatchers []api.RequestResponseMatcher
|
||||||
reqResMatchers []api.RequestResponseMatcher
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpStream(capture api.Capture) api.TcpStream {
|
func NewTcpStream(capture api.Capture) api.TcpStream {
|
||||||
return &tcpStream{
|
return &tcpStream{
|
||||||
origin: capture,
|
origin: capture,
|
||||||
protoIdentifier: &api.ProtoIdentifier{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,10 +26,6 @@ func (t *tcpStream) GetOrigin() api.Capture {
|
|||||||
return t.origin
|
return t.origin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) GetProtoIdentifier() *api.ProtoIdentifier {
|
|
||||||
return t.protoIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
func (t *tcpStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
||||||
return t.reqResMatchers
|
return t.reqResMatchers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect8/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/expect10/http/\* expect
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
github.com/google/martian v2.1.0+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../../dbgctl
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func filterAndEmit(item *api.OutputChannelItem, emitter api.Emitter, options *ap
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !options.DisableRedaction {
|
if options.EnableRedaction {
|
||||||
FilterSensitiveData(item, options)
|
FilterSensitiveData(item, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package http
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -66,7 +65,7 @@ var grpcProtocol api.Protocol = api.Protocol{
|
|||||||
BackgroundColor: "#244c5a",
|
BackgroundColor: "#244c5a",
|
||||||
ForegroundColor: "#ffffff",
|
ForegroundColor: "#ffffff",
|
||||||
FontSize: 11,
|
FontSize: 11,
|
||||||
ReferenceLink: "https://grpc.github.io/grpc/core/md_doc_statuscodes.html",
|
ReferenceLink: "https://grpc.github.io/grpc/core/md_doc__p_r_o_t_o_c_o_l-_h_t_t_p2.html",
|
||||||
Ports: []string{"80", "443", "8080", "50051"},
|
Ports: []string{"80", "443", "8080", "50051"},
|
||||||
Priority: 0,
|
Priority: 0,
|
||||||
}
|
}
|
||||||
@@ -144,10 +143,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
http2Assembler = createHTTP2Assembler(b)
|
http2Assembler = createHTTP2Assembler(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if reader.GetParent().GetProtoIdentifier().Protocol != nil && reader.GetParent().GetProtoIdentifier().Protocol != &http11protocol {
|
|
||||||
return errors.New("Identified by another protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
if isHTTP2 {
|
if isHTTP2 {
|
||||||
err = handleHTTP2Stream(http2Assembler, reader.GetReadProgress(), reader.GetParent().GetOrigin(), reader.GetTcpID(), reader.GetCaptureTime(), reader.GetEmitter(), options, reqResMatcher)
|
err = handleHTTP2Stream(http2Assembler, reader.GetReadProgress(), reader.GetParent().GetOrigin(), reader.GetTcpID(), reader.GetCaptureTime(), reader.GetEmitter(), options, reqResMatcher)
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
@@ -200,10 +195,6 @@ func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if reader.GetParent().GetProtoIdentifier().Protocol == nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,8 +392,8 @@ func representRequest(request map[string]interface{}) (repRequest []interface{})
|
|||||||
|
|
||||||
postData, _ := request["postData"].(map[string]interface{})
|
postData, _ := request["postData"].(map[string]interface{})
|
||||||
mimeType := postData["mimeType"]
|
mimeType := postData["mimeType"]
|
||||||
if mimeType == nil || len(mimeType.(string)) == 0 {
|
if mimeType == nil {
|
||||||
mimeType = "text/html"
|
mimeType = ""
|
||||||
}
|
}
|
||||||
text := postData["text"]
|
text := postData["text"]
|
||||||
if text != nil {
|
if text != nil {
|
||||||
@@ -483,8 +474,8 @@ func representResponse(response map[string]interface{}) (repResponse []interface
|
|||||||
|
|
||||||
content, _ := response["content"].(map[string]interface{})
|
content, _ := response["content"].(map[string]interface{})
|
||||||
mimeType := content["mimeType"]
|
mimeType := content["mimeType"]
|
||||||
if mimeType == nil || len(mimeType.(string)) == 0 {
|
if mimeType == nil {
|
||||||
mimeType = "text/html"
|
mimeType = ""
|
||||||
}
|
}
|
||||||
encoding := content["encoding"]
|
encoding := content["encoding"]
|
||||||
text := content["text"]
|
text := content["text"]
|
||||||
|
|||||||
@@ -78,7 +78,3 @@ func (reader *tcpReader) GetEmitter() api.Emitter {
|
|||||||
func (reader *tcpReader) GetIsClosed() bool {
|
func (reader *tcpReader) GetIsClosed() bool {
|
||||||
return reader.isClosed
|
return reader.isClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reader *tcpReader) GetExtension() *api.Extension {
|
|
||||||
return reader.extension
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,18 +7,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tcpStream struct {
|
type tcpStream struct {
|
||||||
isClosed bool
|
isClosed bool
|
||||||
protoIdentifier *api.ProtoIdentifier
|
isTapTarget bool
|
||||||
isTapTarget bool
|
origin api.Capture
|
||||||
origin api.Capture
|
reqResMatchers []api.RequestResponseMatcher
|
||||||
reqResMatchers []api.RequestResponseMatcher
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpStream(capture api.Capture) api.TcpStream {
|
func NewTcpStream(capture api.Capture) api.TcpStream {
|
||||||
return &tcpStream{
|
return &tcpStream{
|
||||||
origin: capture,
|
origin: capture,
|
||||||
protoIdentifier: &api.ProtoIdentifier{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,10 +26,6 @@ func (t *tcpStream) GetOrigin() api.Capture {
|
|||||||
return t.origin
|
return t.origin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) GetProtoIdentifier() *api.ProtoIdentifier {
|
|
||||||
return t.protoIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
func (t *tcpStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
||||||
return t.reqResMatchers
|
return t.reqResMatchers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect8/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/expect9/kafka/\* expect
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ require (
|
|||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ../../api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../../dbgctl
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user