mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-02 17:50:30 +00:00
Compare commits
40 Commits
33.0-dev2
...
33.0-dev39
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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 }}
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -55,4 +55,4 @@ tap/extensions/*/expect
|
|||||||
*.editorconfig
|
*.editorconfig
|
||||||
|
|
||||||
# Ignore *.log files
|
# Ignore *.log files
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -68,6 +68,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 +95,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.8.1/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
ADD https://github.com/up9inc/basenine/releases/download/v0.8.2/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.8.1/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
ADD https://github.com/up9inc/basenine/releases/download/v0.8.2/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
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export function rightOnHoverCheck(path, expectedText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -69,47 +69,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').should('not.have.text', '0').then(() => {
|
waitForFetch(numberOfRecords);
|
||||||
cy.get(`#list [id]`).then(elements => {
|
pauseStream();
|
||||||
const listElmWithIdAttr = Object.values(elements);
|
|
||||||
let doneCheckOnFirst = false;
|
|
||||||
|
|
||||||
cy.get('#entries-length').invoke('text').then(len => {
|
cy.get(`#list [id^=entry]`).then(elements => {
|
||||||
resizeIfNeeded(len);
|
const listElmWithIdAttr = Object.values(elements);
|
||||||
listElmWithIdAttr.forEach(entry => {
|
let doneCheckOnFirst = false;
|
||||||
if (entry?.id && entry.id.match(RegExp(/entry-(\d{24})$/gm))) {
|
|
||||||
const entryId = getEntryId(entry.id);
|
|
||||||
|
|
||||||
leftTextCheck(entryId, methodDict.pathLeft, methodDict.expectedText);
|
cy.get('#entries-length').invoke('text').then(len => {
|
||||||
leftTextCheck(entryId, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
listElmWithIdAttr.forEach(entry => {
|
||||||
if (summaryDict)
|
if (entry?.id && entry.id.match(RegExp(/entry-(\d{24})$/gm))) {
|
||||||
leftTextCheck(entryId, summaryDict.pathLeft, summaryDict.expectedText);
|
const entryId = getEntryId(entry.id);
|
||||||
|
|
||||||
if (!doneCheckOnFirst) {
|
leftTextCheck(entryId, methodDict.pathLeft, methodDict.expectedText);
|
||||||
deepCheck(funcDict, protocolDict, methodDict, entry);
|
leftTextCheck(entryId, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
||||||
doneCheckOnFirst = true;
|
if (summaryDict)
|
||||||
}
|
leftTextCheck(entryId, summaryDict.pathLeft, summaryDict.expectedText);
|
||||||
}
|
|
||||||
});
|
if (!doneCheckOnFirst) {
|
||||||
resizeIfNeeded(len);
|
deepCheck(funcDict, protocolDict, methodDict, entry);
|
||||||
});
|
doneCheckOnFirst = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|||||||
@@ -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,63 +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();
|
||||||
});
|
});
|
||||||
|
|
||||||
resizeToHugeMizu();
|
resizeToHugeMizu();
|
||||||
|
|
||||||
// checking only 'leftTextCheck' on all entries because the rest of the checks require more time
|
// checking only 'leftTextCheck' on all entries because the rest of the checks require more time
|
||||||
cy.get(`#list [id^=entry]`).each(elem => {
|
cy.get(`#list [id^=entry]`).each(elem => {
|
||||||
const element = elem[0];
|
const element = elem[0];
|
||||||
let entryId = getEntryId(element.id);
|
let entryId = getEntryId(element.id);
|
||||||
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
||||||
});
|
});
|
||||||
|
|
||||||
// making the other 3 checks on the first X entries (longer time for each check)
|
// making the other 3 checks on the first X entries (longer time for each check)
|
||||||
deeperCheck(leftSidePath, rightSidePath, name, leftSideExpectedText, rightSideExpectedText, entriesForDeeperCheck);
|
deeperCheck(leftSidePath, rightSidePath, filter, rightSideExpectedText, entriesForDeeperCheck);
|
||||||
|
|
||||||
// reloading then waiting for the entries number to load
|
// reloading then waiting for the entries number to load
|
||||||
resizeToNormalMizu();
|
resizeToNormalMizu();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
waitForFetch(numberOfRecords);
|
||||||
})
|
pauseStream();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -262,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')
|
||||||
}
|
}
|
||||||
@@ -283,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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -302,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);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ func TestRedis(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RunCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/Redis.js\"")
|
RunCypressTests(t, "npx cypress@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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
|
||||||
|
|||||||
@@ -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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/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@9.5.4 run --spec \"cypress/integration/tests/IgnoredUserAgents.js\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTapDumpLogs(t *testing.T) {
|
func TestTapDumpLogs(t *testing.T) {
|
||||||
|
|||||||
13
agent/go.mod
13
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-20220508080324-c66c4e1b9337
|
github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4
|
||||||
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
|
||||||
@@ -61,6 +62,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
|
||||||
@@ -102,15 +104,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
|
||||||
@@ -152,3 +159,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
|
||||||
|
|||||||
23
agent/go.sum
23
agent/go.sum
@@ -166,8 +166,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 +213,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 +241,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=
|
||||||
@@ -620,6 +623,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=
|
||||||
@@ -661,6 +666,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=
|
||||||
@@ -674,6 +681,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=
|
||||||
@@ -683,8 +694,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-20220508080324-c66c4e1b9337 h1:eRXRZnojrZyhbiSuGHl0EPvFtWvx1ZMrsY/bSoBzYNE=
|
github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4 h1:nNOrU1HVH0fnaG7GNhxCc8kNPVL035Iix7ihUF6lZT8=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4/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=
|
||||||
@@ -704,6 +715,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=
|
||||||
@@ -896,6 +909,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=
|
||||||
@@ -964,6 +978,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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,14 +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 != nil {
|
if err := entryStreamerSocketConnector.SendToastError(socketId, err); err != nil {
|
||||||
entryStreamerSocketConnector.SendToastError(socketId, err)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entryStreamerSocketConnector.CleanupSocket(socketId)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
leftOff, err := e.fetch(socketId, params, entryStreamerSocketConnector)
|
leftOff, err := e.fetch(socketId, params, entryStreamerSocketConnector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Errorf("Fetch error: %v", err.Error())
|
logger.Log.Errorf("Fetch error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDataChannel := func(c *basenine.Connection, data chan []byte) {
|
handleDataChannel := func(c *basenine.Connection, data chan []byte) {
|
||||||
@@ -53,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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,13 +78,15 @@ 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,28 +133,31 @@ func (e *BasenineEntryStreamer) fetch(socketId int, params *WebSocketParams, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
var firstMetadata *basenine.Metadata
|
var firstMetadata *basenine.Metadata
|
||||||
err = json.Unmarshal(firstMeta, &firstMetadata)
|
if err = json.Unmarshal(firstMeta, &firstMetadata); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftOff = firstMetadata.LeftOff
|
leftOff = firstMetadata.LeftOff
|
||||||
|
|
||||||
var lastMetadata *basenine.Metadata
|
var lastMetadata *basenine.Metadata
|
||||||
err = json.Unmarshal(lastMeta, &lastMetadata)
|
if err = json.Unmarshal(lastMeta, &lastMetadata); err != nil {
|
||||||
if err != nil {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = connector.SendMetadata(socketId, lastMetadata); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connector.SendMetadata(socketId, lastMetadata)
|
|
||||||
|
|
||||||
data = e.reverseBytesSlice(data)
|
data = e.reverseBytesSlice(data)
|
||||||
for _, row := range data {
|
for _, row := range data {
|
||||||
var entry *tapApi.Entry
|
var entry *tapApi.Entry
|
||||||
err = json.Unmarshal(row, &entry)
|
if err = json.Unmarshal(row, &entry); err != nil {
|
||||||
if err != nil {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
connector.SendEntry(socketId, entry, params)
|
if err = connector.SendEntry(socketId, entry, params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 -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
|
|
||||||
}
|
|
||||||
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/expect9/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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ package kafka
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/text/cases"
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/fatih/camelcase"
|
"github.com/fatih/camelcase"
|
||||||
"github.com/ohler55/ojg/jp"
|
"github.com/ohler55/ojg/jp"
|
||||||
"github.com/ohler55/ojg/oj"
|
"github.com/ohler55/ojg/oj"
|
||||||
@@ -36,9 +37,14 @@ type KafkaWrapper struct {
|
|||||||
|
|
||||||
func representRequestHeader(data map[string]interface{}, rep []interface{}) []interface{} {
|
func representRequestHeader(data map[string]interface{}, rep []interface{}) []interface{} {
|
||||||
requestHeader, _ := json.Marshal([]api.TableData{
|
requestHeader, _ := json.Marshal([]api.TableData{
|
||||||
|
{
|
||||||
|
Name: "ApiKeyName",
|
||||||
|
Value: data["apiKeyName"].(string),
|
||||||
|
Selector: `request.apiKeyName`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "ApiKey",
|
Name: "ApiKey",
|
||||||
Value: apiNames[int(data["apiKey"].(float64))],
|
Value: int(data["apiKey"].(float64)),
|
||||||
Selector: `request.apiKey`,
|
Selector: `request.apiKey`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package kafka
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
@@ -38,10 +37,6 @@ func (d dissecting) Ping() {
|
|||||||
func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.TrafficFilteringOptions) error {
|
func (d dissecting) Dissect(b *bufio.Reader, reader api.TcpReader, options *api.TrafficFilteringOptions) error {
|
||||||
reqResMatcher := reader.GetReqResMatcher().(*requestResponseMatcher)
|
reqResMatcher := reader.GetReqResMatcher().(*requestResponseMatcher)
|
||||||
for {
|
for {
|
||||||
if reader.GetParent().GetProtoIdentifier().Protocol != nil && reader.GetParent().GetProtoIdentifier().Protocol != &_protocol {
|
|
||||||
return errors.New("Identified by another protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
if reader.GetIsClient() {
|
if reader.GetIsClient() {
|
||||||
_, _, err := ReadRequest(b, reader.GetTcpID(), reader.GetCounterPair(), reader.GetCaptureTime(), reqResMatcher)
|
_, _, err := ReadRequest(b, reader.GetTcpID(), reader.GetCounterPair(), reader.GetCaptureTime(), reqResMatcher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,8 +91,8 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
statusQuery := ""
|
statusQuery := ""
|
||||||
|
|
||||||
apiKey := ApiKey(entry.Request["apiKey"].(float64))
|
apiKey := ApiKey(entry.Request["apiKey"].(float64))
|
||||||
method := apiNames[apiKey]
|
method := entry.Request["apiKeyName"].(string)
|
||||||
methodQuery := fmt.Sprintf("request.apiKey == %d", int(entry.Request["apiKey"].(float64)))
|
methodQuery := fmt.Sprintf(`request.apiKeyName == "%s"`, method)
|
||||||
|
|
||||||
summary := ""
|
summary := ""
|
||||||
summaryQuery := ""
|
summaryQuery := ""
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Size int32 `json:"size"`
|
Size int32 `json:"size"`
|
||||||
|
ApiKeyName string `json:"apiKeyName"`
|
||||||
ApiKey ApiKey `json:"apiKey"`
|
ApiKey ApiKey `json:"apiKey"`
|
||||||
ApiVersion int16 `json:"apiVersion"`
|
ApiVersion int16 `json:"apiVersion"`
|
||||||
CorrelationID int32 `json:"correlationID"`
|
CorrelationID int32 `json:"correlationID"`
|
||||||
@@ -202,6 +203,7 @@ func ReadRequest(r io.Reader, tcpID *api.TcpID, counterPair *api.CounterPair, ca
|
|||||||
|
|
||||||
request := &Request{
|
request := &Request{
|
||||||
Size: size,
|
Size: size,
|
||||||
|
ApiKeyName: apiNames[apiKey],
|
||||||
ApiKey: apiKey,
|
ApiKey: apiKey,
|
||||||
ApiVersion: apiVersion,
|
ApiVersion: apiVersion,
|
||||||
CorrelationID: correlationID,
|
CorrelationID: correlationID,
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
11
tap/go.mod
11
tap/go.mod
@@ -6,23 +6,30 @@ require (
|
|||||||
github.com/cilium/ebpf v0.8.0
|
github.com/cilium/ebpf v0.8.0
|
||||||
github.com/go-errors/errors v1.4.2
|
github.com/go-errors/errors v1.4.2
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
|
github.com/struCoder/pidusage v0.2.1
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger 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/vishvananda/netns v0.0.0-20211101163701-50045581ed74
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
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/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/google/go-cmp v0.5.7 // indirect
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
github.com/google/martian v2.1.0+incompatible // indirect
|
||||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
@@ -39,3 +46,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 => ./api
|
replace github.com/up9inc/mizu/tap/api v0.0.0 => ./api
|
||||||
|
|
||||||
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ./dbgctl
|
||||||
|
|||||||
17
tap/go.sum
17
tap/go.sum
@@ -31,6 +31,8 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
|
|||||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
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-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/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||||
@@ -117,6 +119,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
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/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
@@ -126,11 +130,19 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
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/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/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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
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/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
@@ -170,6 +182,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -184,6 +197,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/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-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=
|
||||||
@@ -276,6 +290,5 @@ sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz
|
|||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||||
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
|
||||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/cpu"
|
||||||
|
"github.com/struCoder/pidusage"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
"github.com/up9inc/mizu/tap/diagnose"
|
"github.com/up9inc/mizu/tap/diagnose"
|
||||||
@@ -41,6 +44,7 @@ var debug = flag.Bool("debug", false, "Display debug information")
|
|||||||
var quiet = flag.Bool("quiet", false, "Be quiet regarding errors")
|
var quiet = flag.Bool("quiet", false, "Be quiet regarding errors")
|
||||||
var hexdumppkt = flag.Bool("dumppkt", false, "Dump packet as hex")
|
var hexdumppkt = flag.Bool("dumppkt", false, "Dump packet as hex")
|
||||||
var procfs = flag.String("procfs", "/proc", "The procfs directory, used when mapping host volumes into a container")
|
var procfs = flag.String("procfs", "/proc", "The procfs directory, used when mapping host volumes into a container")
|
||||||
|
var ignoredPorts = flag.String("ignore-ports", "", "A comma separated list of ports to ignore")
|
||||||
|
|
||||||
// capture
|
// capture
|
||||||
var iface = flag.String("i", "en0", "Interface to read packets from")
|
var iface = flag.String("i", "en0", "Interface to read packets from")
|
||||||
@@ -55,7 +59,8 @@ var tls = flag.Bool("tls", false, "Enable TLS tapper")
|
|||||||
var memprofile = flag.String("memprofile", "", "Write memory profile")
|
var memprofile = flag.String("memprofile", "", "Write memory profile")
|
||||||
|
|
||||||
type TapOpts struct {
|
type TapOpts struct {
|
||||||
HostMode bool
|
HostMode bool
|
||||||
|
IgnoredPorts []uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
var extensions []*api.Extension // global
|
var extensions []*api.Extension // global
|
||||||
@@ -123,6 +128,16 @@ func printPeriodicStats(cleaner *Cleaner) {
|
|||||||
statsPeriod := time.Second * time.Duration(*statsevery)
|
statsPeriod := time.Second * time.Duration(*statsevery)
|
||||||
ticker := time.NewTicker(statsPeriod)
|
ticker := time.NewTicker(statsPeriod)
|
||||||
|
|
||||||
|
logicalCoreCount, err := cpu.Counts(true)
|
||||||
|
if err != nil {
|
||||||
|
logicalCoreCount = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
physicalCoreCount, err := cpu.Counts(false)
|
||||||
|
if err != nil {
|
||||||
|
physicalCoreCount = -1
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
<-ticker.C
|
||||||
|
|
||||||
@@ -139,11 +154,21 @@ func printPeriodicStats(cleaner *Cleaner) {
|
|||||||
// At this moment
|
// At this moment
|
||||||
memStats := runtime.MemStats{}
|
memStats := runtime.MemStats{}
|
||||||
runtime.ReadMemStats(&memStats)
|
runtime.ReadMemStats(&memStats)
|
||||||
|
sysInfo, err := pidusage.GetStat(os.Getpid())
|
||||||
|
if err != nil {
|
||||||
|
sysInfo = &pidusage.SysInfo{
|
||||||
|
CPU: -1,
|
||||||
|
Memory: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
logger.Log.Infof(
|
logger.Log.Infof(
|
||||||
"mem: %d, goroutines: %d",
|
"mem: %d, goroutines: %d, cpu: %f, cores: %d/%d, rss: %f",
|
||||||
memStats.HeapAlloc,
|
memStats.HeapAlloc,
|
||||||
runtime.NumGoroutine(),
|
runtime.NumGoroutine(),
|
||||||
)
|
sysInfo.CPU,
|
||||||
|
logicalCoreCount,
|
||||||
|
physicalCoreCount,
|
||||||
|
sysInfo.Memory)
|
||||||
|
|
||||||
// Since the last print
|
// Since the last print
|
||||||
cleanStats := cleaner.dumpStats()
|
cleanStats := cleaner.dumpStats()
|
||||||
@@ -193,6 +218,8 @@ func initializePassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelI
|
|||||||
logger.Log.Fatal(err)
|
logger.Log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts.IgnoredPorts = append(opts.IgnoredPorts, buildIgnoredPortsList(*ignoredPorts)...)
|
||||||
|
|
||||||
assembler := NewTcpAssembler(outputItems, streamsMap, opts)
|
assembler := NewTcpAssembler(outputItems, streamsMap, opts)
|
||||||
|
|
||||||
return assembler
|
return assembler
|
||||||
@@ -267,3 +294,19 @@ func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChanne
|
|||||||
|
|
||||||
return &tls
|
return &tls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildIgnoredPortsList(ignoredPorts string) []uint16 {
|
||||||
|
tmp := strings.Split(ignoredPorts, ",")
|
||||||
|
result := make([]uint16, len(tmp))
|
||||||
|
|
||||||
|
for i, raw := range tmp {
|
||||||
|
v, err := strconv.Atoi(raw)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = uint16(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
"github.com/up9inc/mizu/tap/diagnose"
|
"github.com/up9inc/mizu/tap/diagnose"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -116,6 +117,9 @@ func (source *tcpPacketSource) close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (source *tcpPacketSource) readPackets(ipdefrag bool, packets chan<- TcpPacketInfo) {
|
func (source *tcpPacketSource) readPackets(ipdefrag bool, packets chan<- TcpPacketInfo) {
|
||||||
|
if dbgctl.MizuTapperDisablePcap {
|
||||||
|
return
|
||||||
|
}
|
||||||
logger.Log.Infof("Start reading packets from %v", source.name)
|
logger.Log.Infof("Start reading packets from %v", source.name)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/google/gopacket/reassembly"
|
"github.com/google/gopacket/reassembly"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
"github.com/up9inc/mizu/tap/diagnose"
|
"github.com/up9inc/mizu/tap/diagnose"
|
||||||
"github.com/up9inc/mizu/tap/source"
|
"github.com/up9inc/mizu/tap/source"
|
||||||
)
|
)
|
||||||
@@ -23,6 +24,7 @@ type tcpAssembler struct {
|
|||||||
streamPool *reassembly.StreamPool
|
streamPool *reassembly.StreamPool
|
||||||
streamFactory *tcpStreamFactory
|
streamFactory *tcpStreamFactory
|
||||||
assemblerMutex sync.Mutex
|
assemblerMutex sync.Mutex
|
||||||
|
ignoredPorts []uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context
|
// Context
|
||||||
@@ -48,8 +50,8 @@ func NewTcpAssembler(outputItems chan *api.OutputChannelItem, streamsMap api.Tcp
|
|||||||
|
|
||||||
maxBufferedPagesTotal := GetMaxBufferedPagesPerConnection()
|
maxBufferedPagesTotal := GetMaxBufferedPagesPerConnection()
|
||||||
maxBufferedPagesPerConnection := GetMaxBufferedPagesTotal()
|
maxBufferedPagesPerConnection := GetMaxBufferedPagesTotal()
|
||||||
logger.Log.Infof("Assembler options: maxBufferedPagesTotal=%d, maxBufferedPagesPerConnection=%d",
|
logger.Log.Infof("Assembler options: maxBufferedPagesTotal=%d, maxBufferedPagesPerConnection=%d, opts=%v",
|
||||||
maxBufferedPagesTotal, maxBufferedPagesPerConnection)
|
maxBufferedPagesTotal, maxBufferedPagesPerConnection, opts)
|
||||||
assembler.AssemblerOptions.MaxBufferedPagesTotal = maxBufferedPagesTotal
|
assembler.AssemblerOptions.MaxBufferedPagesTotal = maxBufferedPagesTotal
|
||||||
assembler.AssemblerOptions.MaxBufferedPagesPerConnection = maxBufferedPagesPerConnection
|
assembler.AssemblerOptions.MaxBufferedPagesPerConnection = maxBufferedPagesPerConnection
|
||||||
|
|
||||||
@@ -57,6 +59,7 @@ func NewTcpAssembler(outputItems chan *api.OutputChannelItem, streamsMap api.Tcp
|
|||||||
Assembler: assembler,
|
Assembler: assembler,
|
||||||
streamPool: streamPool,
|
streamPool: streamPool,
|
||||||
streamFactory: streamFactory,
|
streamFactory: streamFactory,
|
||||||
|
ignoredPorts: opts.IgnoredPorts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,14 +86,20 @@ func (a *tcpAssembler) processPackets(dumpPacket bool, packets <-chan source.Tcp
|
|||||||
diagnose.AppStats.IncTcpPacketsCount()
|
diagnose.AppStats.IncTcpPacketsCount()
|
||||||
tcp := tcp.(*layers.TCP)
|
tcp := tcp.(*layers.TCP)
|
||||||
|
|
||||||
c := context{
|
if a.shouldIgnorePort(uint16(tcp.DstPort)) {
|
||||||
CaptureInfo: packet.Metadata().CaptureInfo,
|
diagnose.AppStats.IncIgnoredPacketsCount()
|
||||||
Origin: packetInfo.Source.Origin,
|
} else {
|
||||||
|
c := context{
|
||||||
|
CaptureInfo: packet.Metadata().CaptureInfo,
|
||||||
|
Origin: packetInfo.Source.Origin,
|
||||||
|
}
|
||||||
|
diagnose.InternalStats.Totalsz += len(tcp.Payload)
|
||||||
|
if !dbgctl.MizuTapperDisableTcpReassembly {
|
||||||
|
a.assemblerMutex.Lock()
|
||||||
|
a.AssembleWithContext(packet.NetworkLayer().NetworkFlow(), tcp, &c)
|
||||||
|
a.assemblerMutex.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
diagnose.InternalStats.Totalsz += len(tcp.Payload)
|
|
||||||
a.assemblerMutex.Lock()
|
|
||||||
a.AssembleWithContext(packet.NetworkLayer().NetworkFlow(), tcp, &c)
|
|
||||||
a.assemblerMutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done := *maxcount > 0 && int64(diagnose.AppStats.PacketsCount) >= *maxcount
|
done := *maxcount > 0 && int64(diagnose.AppStats.PacketsCount) >= *maxcount
|
||||||
@@ -132,3 +141,13 @@ func (a *tcpAssembler) waitAndDump() {
|
|||||||
logger.Log.Debugf("%s", a.Dump())
|
logger.Log.Debugf("%s", a.Dump())
|
||||||
a.assemblerMutex.Unlock()
|
a.assemblerMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *tcpAssembler) shouldIgnorePort(port uint16) bool {
|
||||||
|
for _, p := range a.ignoredPorts {
|
||||||
|
if port == p {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ package tap
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* TcpReader gets reads from a channel of bytes of tcp payload, and parses it into requests and responses.
|
/* TcpReader gets reads from a channel of bytes of tcp payload, and parses it into requests and responses.
|
||||||
@@ -17,50 +16,55 @@ import (
|
|||||||
* Implements io.Reader interface (Read)
|
* Implements io.Reader interface (Read)
|
||||||
*/
|
*/
|
||||||
type tcpReader struct {
|
type tcpReader struct {
|
||||||
ident string
|
ident string
|
||||||
tcpID *api.TcpID
|
tcpID *api.TcpID
|
||||||
isClosed bool
|
isClosed bool
|
||||||
isClient bool
|
isClient bool
|
||||||
isOutgoing bool
|
isOutgoing bool
|
||||||
msgQueue chan api.TcpReaderDataMsg // Channel of captured reassembled tcp payload
|
msgQueue chan api.TcpReaderDataMsg // Channel of captured reassembled tcp payload
|
||||||
data []byte
|
msgBuffer []api.TcpReaderDataMsg
|
||||||
progress *api.ReadProgress
|
msgBufferMaster []api.TcpReaderDataMsg
|
||||||
captureTime time.Time
|
data []byte
|
||||||
parent *tcpStream
|
progress *api.ReadProgress
|
||||||
packetsSeen uint
|
captureTime time.Time
|
||||||
extension *api.Extension
|
parent *tcpStream
|
||||||
emitter api.Emitter
|
emitter api.Emitter
|
||||||
counterPair *api.CounterPair
|
counterPair *api.CounterPair
|
||||||
reqResMatcher api.RequestResponseMatcher
|
reqResMatcher api.RequestResponseMatcher
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpReader(msgQueue chan api.TcpReaderDataMsg, progress *api.ReadProgress, ident string, tcpId *api.TcpID, captureTime time.Time, parent *tcpStream, isClient bool, isOutgoing bool, extension *api.Extension, emitter api.Emitter, counterPair *api.CounterPair, reqResMatcher api.RequestResponseMatcher) *tcpReader {
|
func NewTcpReader(ident string, tcpId *api.TcpID, parent *tcpStream, isClient bool, isOutgoing bool, emitter api.Emitter) *tcpReader {
|
||||||
return &tcpReader{
|
return &tcpReader{
|
||||||
msgQueue: msgQueue,
|
msgQueue: make(chan api.TcpReaderDataMsg),
|
||||||
progress: progress,
|
progress: &api.ReadProgress{},
|
||||||
ident: ident,
|
ident: ident,
|
||||||
tcpID: tcpId,
|
tcpID: tcpId,
|
||||||
captureTime: captureTime,
|
parent: parent,
|
||||||
parent: parent,
|
isClient: isClient,
|
||||||
isClient: isClient,
|
isOutgoing: isOutgoing,
|
||||||
isOutgoing: isOutgoing,
|
emitter: emitter,
|
||||||
extension: extension,
|
|
||||||
emitter: emitter,
|
|
||||||
counterPair: counterPair,
|
|
||||||
reqResMatcher: reqResMatcher,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reader *tcpReader) run(options *api.TrafficFilteringOptions, wg *sync.WaitGroup) {
|
func (reader *tcpReader) run(options *api.TrafficFilteringOptions, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
b := bufio.NewReader(reader)
|
|
||||||
err := reader.extension.Dissector.Dissect(b, reader, options)
|
if dbgctl.MizuTapperDisableDissectors {
|
||||||
if err != nil {
|
b := bufio.NewReader(reader)
|
||||||
_, err = io.Copy(ioutil.Discard, reader)
|
_, _ = io.ReadAll(b)
|
||||||
if err != nil {
|
return
|
||||||
logger.Log.Errorf("%v", err)
|
}
|
||||||
|
|
||||||
|
for i, extension := range extensions {
|
||||||
|
reader.reqResMatcher = reader.parent.reqResMatchers[i]
|
||||||
|
reader.counterPair = reader.parent.counterPairs[i]
|
||||||
|
b := bufio.NewReader(reader)
|
||||||
|
extension.Dissector.Dissect(b, reader, options) //nolint
|
||||||
|
if reader.isProtocolIdentified() {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
reader.rewind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,21 +85,60 @@ func (reader *tcpReader) sendMsgIfNotClosed(msg api.TcpReaderDataMsg) {
|
|||||||
reader.Unlock()
|
reader.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (reader *tcpReader) isProtocolIdentified() bool {
|
||||||
|
return reader.parent.protocol != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *tcpReader) rewind() {
|
||||||
|
// Reset the data
|
||||||
|
reader.data = make([]byte, 0)
|
||||||
|
|
||||||
|
// Reset msgBuffer from the master record
|
||||||
|
reader.parent.Lock()
|
||||||
|
reader.msgBuffer = make([]api.TcpReaderDataMsg, len(reader.msgBufferMaster))
|
||||||
|
copy(reader.msgBuffer, reader.msgBufferMaster)
|
||||||
|
reader.parent.Unlock()
|
||||||
|
|
||||||
|
// Reset the read progress
|
||||||
|
reader.progress.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *tcpReader) populateData(msg api.TcpReaderDataMsg) {
|
||||||
|
reader.data = msg.GetBytes()
|
||||||
|
reader.captureTime = msg.GetTimestamp()
|
||||||
|
}
|
||||||
|
|
||||||
func (reader *tcpReader) Read(p []byte) (int, error) {
|
func (reader *tcpReader) Read(p []byte) (int, error) {
|
||||||
var msg api.TcpReaderDataMsg
|
var msg api.TcpReaderDataMsg
|
||||||
|
|
||||||
|
for len(reader.msgBuffer) > 0 && len(reader.data) == 0 {
|
||||||
|
// Pop first message
|
||||||
|
if len(reader.msgBuffer) > 1 {
|
||||||
|
msg, reader.msgBuffer = reader.msgBuffer[0], reader.msgBuffer[1:]
|
||||||
|
} else {
|
||||||
|
msg = reader.msgBuffer[0]
|
||||||
|
reader.msgBuffer = make([]api.TcpReaderDataMsg, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the bytes
|
||||||
|
reader.populateData(msg)
|
||||||
|
}
|
||||||
|
|
||||||
ok := true
|
ok := true
|
||||||
for ok && len(reader.data) == 0 {
|
for ok && len(reader.data) == 0 {
|
||||||
msg, ok = <-reader.msgQueue
|
msg, ok = <-reader.msgQueue
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
reader.data = msg.GetBytes()
|
reader.populateData(msg)
|
||||||
reader.captureTime = msg.GetTimestamp()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(reader.data) > 0 {
|
if !reader.isProtocolIdentified() {
|
||||||
reader.packetsSeen += 1
|
reader.msgBufferMaster = append(
|
||||||
|
reader.msgBufferMaster,
|
||||||
|
msg,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok || len(reader.data) == 0 {
|
if !ok || len(reader.data) == 0 {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
@@ -142,7 +185,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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,26 +6,19 @@ import (
|
|||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers" // pulls in all layers decoders
|
"github.com/google/gopacket/layers" // pulls in all layers decoders
|
||||||
"github.com/google/gopacket/reassembly"
|
"github.com/google/gopacket/reassembly"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
|
||||||
"github.com/up9inc/mizu/tap/diagnose"
|
"github.com/up9inc/mizu/tap/diagnose"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReassemblyStream interface {
|
|
||||||
Accept(tcp *layers.TCP, ci gopacket.CaptureInfo, dir reassembly.TCPFlowDirection, nextSeq reassembly.Sequence, start *bool, ac reassembly.AssemblerContext) bool
|
|
||||||
ReassembledSG(sg reassembly.ScatterGather, ac reassembly.AssemblerContext)
|
|
||||||
ReassemblyComplete(ac reassembly.AssemblerContext) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type tcpReassemblyStream struct {
|
type tcpReassemblyStream struct {
|
||||||
ident string
|
ident string
|
||||||
tcpState *reassembly.TCPSimpleFSM
|
tcpState *reassembly.TCPSimpleFSM
|
||||||
fsmerr bool
|
fsmerr bool
|
||||||
optchecker reassembly.TCPOptionCheck
|
optchecker reassembly.TCPOptionCheck
|
||||||
isDNS bool
|
isDNS bool
|
||||||
tcpStream api.TcpStream
|
tcpStream *tcpStream
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpReassemblyStream(ident string, tcp *layers.TCP, fsmOptions reassembly.TCPSimpleFSMOptions, stream api.TcpStream) ReassemblyStream {
|
func NewTcpReassemblyStream(ident string, tcp *layers.TCP, fsmOptions reassembly.TCPSimpleFSMOptions, stream *tcpStream) reassembly.Stream {
|
||||||
return &tcpReassemblyStream{
|
return &tcpReassemblyStream{
|
||||||
ident: ident,
|
ident: ident,
|
||||||
tcpState: reassembly.NewTCPSimpleFSM(fsmOptions),
|
tcpState: reassembly.NewTCPSimpleFSM(fsmOptions),
|
||||||
@@ -145,17 +138,10 @@ func (t *tcpReassemblyStream) ReassembledSG(sg reassembly.ScatterGather, ac reas
|
|||||||
// This channel is read by an tcpReader object
|
// This channel is read by an tcpReader object
|
||||||
diagnose.AppStats.IncReassembledTcpPayloadsCount()
|
diagnose.AppStats.IncReassembledTcpPayloadsCount()
|
||||||
timestamp := ac.GetCaptureInfo().Timestamp
|
timestamp := ac.GetCaptureInfo().Timestamp
|
||||||
stream := t.tcpStream.(*tcpStream)
|
|
||||||
if dir == reassembly.TCPDirClientToServer {
|
if dir == reassembly.TCPDirClientToServer {
|
||||||
for i := range stream.getClients() {
|
t.tcpStream.client.sendMsgIfNotClosed(NewTcpReaderDataMsg(data, timestamp))
|
||||||
reader := stream.getClient(i)
|
|
||||||
reader.sendMsgIfNotClosed(NewTcpReaderDataMsg(data, timestamp))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for i := range stream.getServers() {
|
t.tcpStream.server.sendMsgIfNotClosed(NewTcpReaderDataMsg(data, timestamp))
|
||||||
reader := stream.getServer(i)
|
|
||||||
reader.sendMsgIfNotClosed(NewTcpReaderDataMsg(data, timestamp))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +149,7 @@ func (t *tcpReassemblyStream) ReassembledSG(sg reassembly.ScatterGather, ac reas
|
|||||||
|
|
||||||
func (t *tcpReassemblyStream) ReassemblyComplete(ac reassembly.AssemblerContext) bool {
|
func (t *tcpReassemblyStream) ReassemblyComplete(ac reassembly.AssemblerContext) bool {
|
||||||
if t.tcpStream.GetIsTapTarget() && !t.tcpStream.GetIsClosed() {
|
if t.tcpStream.GetIsTapTarget() && !t.tcpStream.GetIsClosed() {
|
||||||
t.tcpStream.(*tcpStream).close()
|
t.tcpStream.close()
|
||||||
}
|
}
|
||||||
// do not remove the connection to allow last ACK
|
// do not remove the connection to allow last ACK
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* It's a connection (bidirectional)
|
/* It's a connection (bidirectional)
|
||||||
@@ -13,25 +14,26 @@ import (
|
|||||||
* In our implementation, we pass information from ReassembledSG to the TcpReader through a shared channel.
|
* In our implementation, we pass information from ReassembledSG to the TcpReader through a shared channel.
|
||||||
*/
|
*/
|
||||||
type tcpStream struct {
|
type tcpStream struct {
|
||||||
id int64
|
id int64
|
||||||
isClosed bool
|
isClosed bool
|
||||||
protoIdentifier *api.ProtoIdentifier
|
protocol *api.Protocol
|
||||||
isTapTarget bool
|
isTapTarget bool
|
||||||
clients []*tcpReader
|
client *tcpReader
|
||||||
servers []*tcpReader
|
server *tcpReader
|
||||||
origin api.Capture
|
origin api.Capture
|
||||||
reqResMatchers []api.RequestResponseMatcher
|
counterPairs []*api.CounterPair
|
||||||
createdAt time.Time
|
reqResMatchers []api.RequestResponseMatcher
|
||||||
streamsMap api.TcpStreamMap
|
createdAt time.Time
|
||||||
|
streamsMap api.TcpStreamMap
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpStream(isTapTarget bool, streamsMap api.TcpStreamMap, capture api.Capture) *tcpStream {
|
func NewTcpStream(isTapTarget bool, streamsMap api.TcpStreamMap, capture api.Capture) *tcpStream {
|
||||||
return &tcpStream{
|
return &tcpStream{
|
||||||
isTapTarget: isTapTarget,
|
isTapTarget: isTapTarget,
|
||||||
protoIdentifier: &api.ProtoIdentifier{},
|
streamsMap: streamsMap,
|
||||||
streamsMap: streamsMap,
|
origin: capture,
|
||||||
origin: capture,
|
createdAt: time.Now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,38 +57,12 @@ func (t *tcpStream) close() {
|
|||||||
|
|
||||||
t.streamsMap.Delete(t.id)
|
t.streamsMap.Delete(t.id)
|
||||||
|
|
||||||
for i := range t.clients {
|
t.client.close()
|
||||||
reader := t.clients[i]
|
t.server.close()
|
||||||
reader.close()
|
|
||||||
}
|
|
||||||
for i := range t.servers {
|
|
||||||
reader := t.servers[i]
|
|
||||||
reader.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) addClient(reader *tcpReader) {
|
func (t *tcpStream) addCounterPair(counterPair *api.CounterPair) {
|
||||||
t.clients = append(t.clients, reader)
|
t.counterPairs = append(t.counterPairs, counterPair)
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) addServer(reader *tcpReader) {
|
|
||||||
t.servers = append(t.servers, reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) getClients() []*tcpReader {
|
|
||||||
return t.clients
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) getServers() []*tcpReader {
|
|
||||||
return t.servers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) getClient(index int) *tcpReader {
|
|
||||||
return t.clients[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tcpStream) getServer(index int) *tcpReader {
|
|
||||||
return t.servers[index]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) addReqResMatcher(reqResMatcher api.RequestResponseMatcher) {
|
func (t *tcpStream) addReqResMatcher(reqResMatcher api.RequestResponseMatcher) {
|
||||||
@@ -94,44 +70,27 @@ func (t *tcpStream) addReqResMatcher(reqResMatcher api.RequestResponseMatcher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) SetProtocol(protocol *api.Protocol) {
|
func (t *tcpStream) SetProtocol(protocol *api.Protocol) {
|
||||||
|
t.protocol = protocol
|
||||||
|
|
||||||
|
// Clean the buffers
|
||||||
t.Lock()
|
t.Lock()
|
||||||
defer t.Unlock()
|
t.client.msgBufferMaster = make([]api.TcpReaderDataMsg, 0)
|
||||||
|
t.server.msgBufferMaster = make([]api.TcpReaderDataMsg, 0)
|
||||||
if t.protoIdentifier.IsClosedOthers {
|
t.Unlock()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.protoIdentifier.Protocol = protocol
|
|
||||||
|
|
||||||
for i := range t.clients {
|
|
||||||
reader := t.clients[i]
|
|
||||||
if reader.GetExtension().Protocol != t.protoIdentifier.Protocol {
|
|
||||||
reader.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range t.servers {
|
|
||||||
reader := t.servers[i]
|
|
||||||
if reader.GetExtension().Protocol != t.protoIdentifier.Protocol {
|
|
||||||
reader.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.protoIdentifier.IsClosedOthers = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) GetOrigin() api.Capture {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcpStream) GetIsTapTarget() bool {
|
func (t *tcpStream) GetIsTapTarget() bool {
|
||||||
|
if dbgctl.MizuTapperDisableTcpStream {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return t.isTapTarget
|
return t.isTapTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package tap
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
@@ -62,62 +61,50 @@ func (factory *tcpStreamFactory) New(net, transport gopacket.Flow, tcpLayer *lay
|
|||||||
reassemblyStream := NewTcpReassemblyStream(fmt.Sprintf("%s:%s", net, transport), tcpLayer, fsmOptions, stream)
|
reassemblyStream := NewTcpReassemblyStream(fmt.Sprintf("%s:%s", net, transport), tcpLayer, fsmOptions, stream)
|
||||||
if stream.GetIsTapTarget() {
|
if stream.GetIsTapTarget() {
|
||||||
stream.setId(factory.streamsMap.NextId())
|
stream.setId(factory.streamsMap.NextId())
|
||||||
for i, extension := range extensions {
|
for _, extension := range extensions {
|
||||||
reqResMatcher := extension.Dissector.NewResponseRequestMatcher()
|
|
||||||
stream.addReqResMatcher(reqResMatcher)
|
|
||||||
counterPair := &api.CounterPair{
|
counterPair := &api.CounterPair{
|
||||||
Request: 0,
|
Request: 0,
|
||||||
Response: 0,
|
Response: 0,
|
||||||
}
|
}
|
||||||
stream.addClient(
|
stream.addCounterPair(counterPair)
|
||||||
NewTcpReader(
|
|
||||||
make(chan api.TcpReaderDataMsg),
|
|
||||||
&api.ReadProgress{},
|
|
||||||
fmt.Sprintf("%s %s", net, transport),
|
|
||||||
&api.TcpID{
|
|
||||||
SrcIP: srcIp,
|
|
||||||
DstIP: dstIp,
|
|
||||||
SrcPort: srcPort,
|
|
||||||
DstPort: dstPort,
|
|
||||||
},
|
|
||||||
time.Time{},
|
|
||||||
stream,
|
|
||||||
true,
|
|
||||||
props.isOutgoing,
|
|
||||||
extension,
|
|
||||||
factory.emitter,
|
|
||||||
counterPair,
|
|
||||||
reqResMatcher,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
stream.addServer(
|
|
||||||
NewTcpReader(
|
|
||||||
make(chan api.TcpReaderDataMsg),
|
|
||||||
&api.ReadProgress{},
|
|
||||||
fmt.Sprintf("%s %s", net, transport),
|
|
||||||
&api.TcpID{
|
|
||||||
SrcIP: net.Dst().String(),
|
|
||||||
DstIP: net.Src().String(),
|
|
||||||
SrcPort: transport.Dst().String(),
|
|
||||||
DstPort: transport.Src().String(),
|
|
||||||
},
|
|
||||||
time.Time{},
|
|
||||||
stream,
|
|
||||||
false,
|
|
||||||
props.isOutgoing,
|
|
||||||
extension,
|
|
||||||
factory.emitter,
|
|
||||||
counterPair,
|
|
||||||
reqResMatcher,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
factory.streamsMap.Store(stream.getId(), stream)
|
reqResMatcher := extension.Dissector.NewResponseRequestMatcher()
|
||||||
|
stream.addReqResMatcher(reqResMatcher)
|
||||||
factory.wg.Add(2)
|
|
||||||
go stream.getClient(i).run(filteringOptions, &factory.wg)
|
|
||||||
go stream.getServer(i).run(filteringOptions, &factory.wg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream.client = NewTcpReader(
|
||||||
|
fmt.Sprintf("%s %s", net, transport),
|
||||||
|
&api.TcpID{
|
||||||
|
SrcIP: srcIp,
|
||||||
|
DstIP: dstIp,
|
||||||
|
SrcPort: srcPort,
|
||||||
|
DstPort: dstPort,
|
||||||
|
},
|
||||||
|
stream,
|
||||||
|
true,
|
||||||
|
props.isOutgoing,
|
||||||
|
factory.emitter,
|
||||||
|
)
|
||||||
|
|
||||||
|
stream.server = NewTcpReader(
|
||||||
|
fmt.Sprintf("%s %s", net, transport),
|
||||||
|
&api.TcpID{
|
||||||
|
SrcIP: net.Dst().String(),
|
||||||
|
DstIP: net.Src().String(),
|
||||||
|
SrcPort: transport.Dst().String(),
|
||||||
|
DstPort: transport.Src().String(),
|
||||||
|
},
|
||||||
|
stream,
|
||||||
|
false,
|
||||||
|
props.isOutgoing,
|
||||||
|
factory.emitter,
|
||||||
|
)
|
||||||
|
|
||||||
|
factory.streamsMap.Store(stream.getId(), stream)
|
||||||
|
|
||||||
|
factory.wg.Add(2)
|
||||||
|
go stream.client.run(filteringOptions, &factory.wg)
|
||||||
|
go stream.server.run(filteringOptions, &factory.wg)
|
||||||
}
|
}
|
||||||
return reassemblyStream
|
return reassemblyStream
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ func (streamMap *tcpStreamMap) Range(f func(key, value interface{}) bool) {
|
|||||||
|
|
||||||
func (streamMap *tcpStreamMap) Store(key, value interface{}) {
|
func (streamMap *tcpStreamMap) Store(key, value interface{}) {
|
||||||
streamMap.streams.Store(key, value)
|
streamMap.streams.Store(key, value)
|
||||||
|
diagnose.AppStats.IncLiveTcpStreams()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (streamMap *tcpStreamMap) Delete(key interface{}) {
|
func (streamMap *tcpStreamMap) Delete(key interface{}) {
|
||||||
streamMap.streams.Delete(key)
|
streamMap.streams.Delete(key)
|
||||||
|
diagnose.AppStats.DecLiveTcpStreams()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (streamMap *tcpStreamMap) NextId() int64 {
|
func (streamMap *tcpStreamMap) NextId() int64 {
|
||||||
@@ -57,7 +59,7 @@ func (streamMap *tcpStreamMap) CloseTimedoutTcpStreamChannels() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if stream.protoIdentifier.Protocol == nil {
|
if stream.protocol == nil {
|
||||||
if !stream.isClosed && time.Now().After(stream.createdAt.Add(tcpStreamChannelTimeoutMs)) {
|
if !stream.isClosed && time.Now().After(stream.createdAt.Add(tcpStreamChannelTimeoutMs)) {
|
||||||
stream.close()
|
stream.close()
|
||||||
diagnose.AppStats.IncDroppedTcpStreams()
|
diagnose.AppStats.IncDroppedTcpStreams()
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ struct fd_info {
|
|||||||
BPF_HASH(pids_map, __u32, __u32);
|
BPF_HASH(pids_map, __u32, __u32);
|
||||||
BPF_LRU_HASH(ssl_write_context, __u64, struct ssl_info);
|
BPF_LRU_HASH(ssl_write_context, __u64, struct ssl_info);
|
||||||
BPF_LRU_HASH(ssl_read_context, __u64, struct ssl_info);
|
BPF_LRU_HASH(ssl_read_context, __u64, struct ssl_info);
|
||||||
BPF_HASH(file_descriptor_to_ipv4, __u64, struct fd_info);
|
BPF_LRU_HASH(file_descriptor_to_ipv4, __u64, struct fd_info);
|
||||||
BPF_PERF_OUTPUT(chunks_buffer);
|
BPF_PERF_OUTPUT(chunks_buffer);
|
||||||
BPF_PERF_OUTPUT(log_buffer);
|
BPF_PERF_OUTPUT(log_buffer);
|
||||||
|
|
||||||
|
|||||||
@@ -188,8 +188,7 @@ func (p *tlsPoller) startNewTlsReader(chunk *tlsChunk, address *addressPair, key
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream := &tlsStream{
|
stream := &tlsStream{
|
||||||
reader: reader,
|
reader: reader,
|
||||||
protoIdentifier: &api.ProtoIdentifier{},
|
|
||||||
}
|
}
|
||||||
streamsMap.Store(streamsMap.NextId(), stream)
|
streamsMap.Store(streamsMap.NextId(), stream)
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,3 @@ func (r *tlsReader) GetEmitter() api.Emitter {
|
|||||||
func (r *tlsReader) GetIsClosed() bool {
|
func (r *tlsReader) GetIsClosed() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *tlsReader) GetExtension() *api.Extension {
|
|
||||||
return r.extension
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,20 +3,16 @@ package tlstapper
|
|||||||
import "github.com/up9inc/mizu/tap/api"
|
import "github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
type tlsStream struct {
|
type tlsStream struct {
|
||||||
reader *tlsReader
|
reader *tlsReader
|
||||||
protoIdentifier *api.ProtoIdentifier
|
protocol *api.Protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tlsStream) GetOrigin() api.Capture {
|
func (t *tlsStream) GetOrigin() api.Capture {
|
||||||
return api.Ebpf
|
return api.Ebpf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tlsStream) GetProtoIdentifier() *api.ProtoIdentifier {
|
|
||||||
return t.protoIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tlsStream) SetProtocol(protocol *api.Protocol) {
|
func (t *tlsStream) SetProtocol(protocol *api.Protocol) {
|
||||||
t.protoIdentifier.Protocol = protocol
|
t.protocol = protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tlsStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
func (t *tlsStream) GetReqResMatchers() []api.RequestResponseMatcher {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
12011
ui-common/package-lock.json
generated
12011
ui-common/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user