mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-05-31 21:43:10 +00:00
Compare commits
14 Commits
28.0-dev4
...
28.0-dev18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58a17897cf | ||
|
|
cf3106f636 | ||
|
|
a553a1b683 | ||
|
|
2a6bbd66e6 | ||
|
|
5a4baa05ca | ||
|
|
4ec9b9b475 | ||
|
|
1e2288b9a8 | ||
|
|
74f58a88bf | ||
|
|
69ee8752d0 | ||
|
|
27fa0afb72 | ||
|
|
c98c99e488 | ||
|
|
2d838d7699 | ||
|
|
d5bb036939 | ||
|
|
87ef469e25 |
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -58,6 +58,7 @@ jobs:
|
|||||||
up9inc/mizu
|
up9inc/mizu
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,${{ steps.versioning.outputs.version }}
|
type=raw,${{ steps.versioning.outputs.version }}
|
||||||
|
type=raw,value=latest,enable=${{ steps.condval.outputs.value == 'stable' }}
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=auto
|
latest=auto
|
||||||
prefix=
|
prefix=
|
||||||
@@ -143,6 +144,7 @@ jobs:
|
|||||||
${{ steps.base_image_step.outputs.image }}
|
${{ steps.base_image_step.outputs.image }}
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,${{ steps.versioning.outputs.version }}
|
type=raw,${{ steps.versioning.outputs.version }}
|
||||||
|
type=raw,value=latest,enable=${{ steps.condval.outputs.value == 'stable' }}
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=auto
|
latest=auto
|
||||||
prefix=
|
prefix=
|
||||||
@@ -205,6 +207,7 @@ jobs:
|
|||||||
up9inc/mizu
|
up9inc/mizu
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,${{ steps.versioning.outputs.version }}
|
type=raw,${{ steps.versioning.outputs.version }}
|
||||||
|
type=raw,value=latest,enable=${{ steps.condval.outputs.value == 'stable' }}
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
|
|||||||
@@ -78,8 +78,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.4.16/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
ADD https://github.com/up9inc/basenine/releases/download/v0.4.17/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.4.16/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
ADD https://github.com/up9inc/basenine/releases/download/v0.4.17/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
|
||||||
RUN chmod +x ./basenine_linux_${GOARCH}
|
RUN chmod +x ./basenine_linux_${GOARCH}
|
||||||
RUN mv ./basenine_linux_${GOARCH} ./basenine
|
RUN mv ./basenine_linux_${GOARCH} ./basenine
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
<img alt="GitHub Latest Release" src="https://img.shields.io/github/v/release/up9inc/mizu?logo=GitHub&style=flat-square">
|
<img alt="GitHub Latest Release" src="https://img.shields.io/github/v/release/up9inc/mizu?logo=GitHub&style=flat-square">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/up9inc/mizu">
|
<a href="https://hub.docker.com/r/up9inc/mizu">
|
||||||
<img alt="Docker pulls" src="https://img.shields.io/docker/pulls/up9inc/mizu?color=%23099cec">
|
<img alt="Docker pulls" src="https://img.shields.io/docker/pulls/up9inc/mizu?color=%23099cec&logo=Docker&style=flat-square">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/up9inc/mizu">
|
<a href="https://hub.docker.com/r/up9inc/mizu">
|
||||||
<img alt="Image size" src="https://img.shields.io/docker/image-size/up9inc/mizu/latest">
|
<img alt="Image size" src="https://img.shields.io/docker/image-size/up9inc/mizu/latest?logo=Docker&style=flat-square">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://join.slack.com/t/up9/shared_invite/zt-tfjnduli-QzlR8VV4Z1w3YnPIAJfhlQ">
|
<a href="https://join.slack.com/t/up9/shared_invite/zt-tfjnduli-QzlR8VV4Z1w3YnPIAJfhlQ">
|
||||||
<img alt="Slack" src="https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social">
|
<img alt="Slack" src="https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social">
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
"tests/IgnoredUserAgents.js",
|
"tests/IgnoredUserAgents.js",
|
||||||
"tests/UiTest.js",
|
"tests/UiTest.js",
|
||||||
"tests/Redis.js",
|
"tests/Redis.js",
|
||||||
"tests/Rabbit.js"
|
"tests/Rabbit.js",
|
||||||
|
"tests/serviceMapFunction.js"
|
||||||
],
|
],
|
||||||
|
|
||||||
"env": {
|
"env": {
|
||||||
@@ -26,6 +27,9 @@
|
|||||||
"minimumEntries": 25,
|
"minimumEntries": 25,
|
||||||
"greenFilterColor": "rgb(210, 250, 210)",
|
"greenFilterColor": "rgb(210, 250, 210)",
|
||||||
"redFilterColor": "rgb(250, 214, 220)",
|
"redFilterColor": "rgb(250, 214, 220)",
|
||||||
"bodyJsonClass": ".hljs"
|
"bodyJsonClass": ".hljs",
|
||||||
|
"mizuWidth": 1920,
|
||||||
|
"normalMizuHeight": 1080,
|
||||||
|
"hugeMizuHeight": 3500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export const valueTabs = {
|
|||||||
none: null
|
none: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxEntriesInDom = 13;
|
||||||
|
|
||||||
export function isValueExistsInElement(shouldInclude, content, domPathToContainer){
|
export function isValueExistsInElement(shouldInclude, content, domPathToContainer){
|
||||||
it(`should ${shouldInclude ? '' : 'not'} include '${content}'`, function () {
|
it(`should ${shouldInclude ? '' : 'not'} include '${content}'`, function () {
|
||||||
cy.get(domPathToContainer).then(htmlText => {
|
cy.get(domPathToContainer).then(htmlText => {
|
||||||
@@ -15,11 +17,11 @@ export function isValueExistsInElement(shouldInclude, content, domPathToContaine
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resizeToHugeMizu() {
|
export function resizeToHugeMizu() {
|
||||||
cy.viewport(1920, 3500);
|
cy.viewport(Cypress.env('mizuWidth'), Cypress.env('hugeMizuHeight'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resizeToNormalMizu() {
|
export function resizeToNormalMizu() {
|
||||||
cy.viewport(1920, 1080);
|
cy.viewport(Cypress.env('mizuWidth'), Cypress.env('normalMizuHeight'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function verifyMinimumEntries() {
|
export function verifyMinimumEntries() {
|
||||||
@@ -61,7 +63,7 @@ export function checkThatAllEntriesShown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function checkFilterByMethod(funcDict) {
|
export function checkFilterByMethod(funcDict) {
|
||||||
const {protocol, method, summary} = funcDict;
|
const {protocol, method, summary, hugeMizu} = funcDict;
|
||||||
const summaryDict = getSummeryDict(summary);
|
const summaryDict = getSummeryDict(summary);
|
||||||
const methodDict = getMethodDict(method);
|
const methodDict = getMethodDict(method);
|
||||||
const protocolDict = getProtocolDict(protocol.name, protocol.text);
|
const protocolDict = getProtocolDict(protocol.name, protocol.text);
|
||||||
@@ -82,20 +84,24 @@ export function checkFilterByMethod(funcDict) {
|
|||||||
const listElmWithIdAttr = Object.values(elements);
|
const listElmWithIdAttr = Object.values(elements);
|
||||||
let doneCheckOnFirst = false;
|
let doneCheckOnFirst = false;
|
||||||
|
|
||||||
listElmWithIdAttr.forEach(entry => {
|
cy.get('#entries-length').invoke('text').then(len => {
|
||||||
if (entry?.id && entry.id.match(RegExp(/entry-(\d{2}|\d{1})$/gm))) {
|
resizeIfNeeded(len);
|
||||||
const entryNum = getEntryNumById(entry.id);
|
listElmWithIdAttr.forEach(entry => {
|
||||||
|
if (entry?.id && entry.id.match(RegExp(/entry-(\d{2}|\d{1})$/gm))) {
|
||||||
|
const entryNum = getEntryNumById(entry.id);
|
||||||
|
|
||||||
leftTextCheck(entryNum, methodDict.pathLeft, methodDict.expectedText);
|
leftTextCheck(entryNum, methodDict.pathLeft, methodDict.expectedText);
|
||||||
leftTextCheck(entryNum, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
leftTextCheck(entryNum, protocolDict.pathLeft, protocolDict.expectedTextLeft);
|
||||||
if (summaryDict)
|
if (summaryDict)
|
||||||
leftTextCheck(entryNum, summaryDict.pathLeft, summaryDict.expectedText);
|
leftTextCheck(entryNum, summaryDict.pathLeft, summaryDict.expectedText);
|
||||||
|
|
||||||
if (!doneCheckOnFirst) {
|
if (!doneCheckOnFirst) {
|
||||||
deepCheck(funcDict, protocolDict, methodDict, entry);
|
deepCheck(funcDict, protocolDict, methodDict, entry);
|
||||||
doneCheckOnFirst = true;
|
doneCheckOnFirst = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
resizeIfNeeded(len);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -103,6 +109,13 @@ export function checkFilterByMethod(funcDict) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 entryNum = getEntryNumById(entry.id);
|
const entryNum = getEntryNumById(entry.id);
|
||||||
const {summary, value} = generalDict;
|
const {summary, value} = generalDict;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {checkFilterByMethod, valueTabs,} from "../testHelpers/TrafficHelper";
|
import {checkFilterByMethod, valueTabs,} from "../testHelpers/TrafficHelper";
|
||||||
|
|
||||||
|
|
||||||
it('opening mizu', function () {
|
it('opening mizu', function () {
|
||||||
cy.visit(Cypress.env('testUrl'));
|
cy.visit(Cypress.env('testUrl'));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ func TestRedis(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAmqp(t *testing.T) {
|
func TestAmqp(t *testing.T) {
|
||||||
|
t.Skip("Invalid test. Not stable")
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("ignored acceptance test")
|
t.Skip("ignored acceptance test")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ require (
|
|||||||
github.com/ory/kratos-client-go v0.8.2-alpha.1
|
github.com/ory/kratos-client-go v0.8.2-alpha.1
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220125035757-926e42208705
|
github.com/up9inc/basenine/client/go v0.0.0-20220220204122-0ef8cb24fab1
|
||||||
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
|
||||||
@@ -54,6 +54,7 @@ require (
|
|||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4 // indirect
|
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4 // indirect
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
||||||
github.com/chanced/dynamic v0.0.0-20211210164248-f8fadb1d735b // indirect
|
github.com/chanced/dynamic v0.0.0-20211210164248-f8fadb1d735b // indirect
|
||||||
|
github.com/cilium/ebpf v0.8.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
|
|||||||
10
agent/go.sum
10
agent/go.sum
@@ -137,6 +137,8 @@ github.com/chanced/openapi v0.0.7/go.mod h1:SxE2VMLPw+T7Vq8nwbVVhDF2PigvRF4n5Xyq
|
|||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/cilium/ebpf v0.8.0 h1:2V6KSg3FRADVU2BMIRemZ0hV+9OM+aAHhZDjQyjJTAs=
|
||||||
|
github.com/cilium/ebpf v0.8.0/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@@ -210,8 +212,9 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF
|
|||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
|
|
||||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||||
|
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
|
||||||
|
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||||
@@ -850,8 +853,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-20220125035757-926e42208705 h1:5LLhzv0cjb/F+dU0z3j8teVGjQInMYAocTyAZohKUwY=
|
github.com/up9inc/basenine/client/go v0.0.0-20220220204122-0ef8cb24fab1 h1:0XN8s3HtwUBr9hbWRAFulFMsu1f2cabfJbwpz/sOoLA=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220125035757-926e42208705/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220220204122-0ef8cb24fab1/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
||||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
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=
|
||||||
@@ -1158,6 +1161,7 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/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-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-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logLevel := determineLogLevel()
|
logLevel := determineLogLevel()
|
||||||
logger.InitLoggerStderrOnly(logLevel)
|
logger.InitLoggerStd(logLevel)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if err := config.LoadConfig(); err != nil {
|
if err := config.LoadConfig(); err != nil {
|
||||||
logger.Log.Fatalf("Error loading config file %v", err)
|
logger.Log.Fatalf("Error loading config file %v", err)
|
||||||
|
|||||||
@@ -140,7 +140,17 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
mizuEntry.Rules = rules
|
mizuEntry.Rules = rules
|
||||||
}
|
}
|
||||||
|
|
||||||
entryWSource := oas.EntryWithSource{Entry: *harEntry, Source: mizuEntry.Source.Name, Id: mizuEntry.Id}
|
entryWSource := oas.EntryWithSource{
|
||||||
|
Entry: *harEntry,
|
||||||
|
Source: mizuEntry.Source.Name,
|
||||||
|
Destination: mizuEntry.Destination.Name,
|
||||||
|
Id: mizuEntry.Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
if entryWSource.Destination == "" {
|
||||||
|
entryWSource.Destination = mizuEntry.Destination.IP + ":" + mizuEntry.Destination.Port
|
||||||
|
}
|
||||||
|
|
||||||
oas.GetOasGeneratorInstance().PushEntry(&entryWSource)
|
oas.GetOasGeneratorInstance().PushEntry(&entryWSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,20 +110,31 @@ func websocketHandler(w http.ResponseWriter, r *http.Request, eventHandlers Even
|
|||||||
logger.Log.Error(err)
|
logger.Log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
for {
|
for {
|
||||||
_, msg, err := ws.ReadMessage()
|
// params[0]: query
|
||||||
if err != nil {
|
// params[1]: enableFullEntries (empty: disable, non-empty: enable)
|
||||||
if _, ok := err.(*websocket.CloseError); ok {
|
params := make([][]byte, 2)
|
||||||
logger.Log.Debugf("Received websocket close message, socket id: %d", socketId)
|
for i := range params {
|
||||||
} else {
|
_, params[i], err = ws.ReadMessage()
|
||||||
logger.Log.Errorf("Error reading message, socket id: %d, error: %v", socketId, err)
|
if err != nil {
|
||||||
}
|
if _, ok := err.(*websocket.CloseError); ok {
|
||||||
|
logger.Log.Debugf("Received websocket close message, socket id: %d", socketId)
|
||||||
|
} else {
|
||||||
|
logger.Log.Errorf("Error reading message, socket id: %d, error: %v", socketId, err)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enableFullEntries := false
|
||||||
|
if len(params[1]) > 0 {
|
||||||
|
enableFullEntries = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isTapper && !isQuerySet {
|
if !isTapper && !isQuerySet {
|
||||||
query := string(msg)
|
query := string(params[0])
|
||||||
err = basenine.Validate(shared.BasenineHost, shared.BaseninePort, query)
|
err = basenine.Validate(shared.BasenineHost, shared.BaseninePort, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
toastBytes, _ := models.CreateWebsocketToastMessage(&models.ToastMessage{
|
toastBytes, _ := models.CreateWebsocketToastMessage(&models.ToastMessage{
|
||||||
@@ -150,10 +161,15 @@ func websocketHandler(w http.ResponseWriter, r *http.Request, eventHandlers Even
|
|||||||
var entry *tapApi.Entry
|
var entry *tapApi.Entry
|
||||||
err = json.Unmarshal(bytes, &entry)
|
err = json.Unmarshal(bytes, &entry)
|
||||||
|
|
||||||
base := tapApi.Summarize(entry)
|
var message []byte
|
||||||
|
if enableFullEntries {
|
||||||
|
message, _ = models.CreateFullEntryWebSocketMessage(entry)
|
||||||
|
} else {
|
||||||
|
base := tapApi.Summarize(entry)
|
||||||
|
message, _ = models.CreateBaseEntryWebSocketMessage(base)
|
||||||
|
}
|
||||||
|
|
||||||
baseEntryBytes, _ := models.CreateBaseEntryWebSocketMessage(base)
|
if err := SendToSocket(socketId, message); err != nil {
|
||||||
if err := SendToSocket(socketId, baseEntryBytes); err != nil {
|
|
||||||
logger.Log.Error(err)
|
logger.Log.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +201,7 @@ func websocketHandler(w http.ResponseWriter, r *http.Request, eventHandlers Even
|
|||||||
|
|
||||||
connection.Query(query, data, meta)
|
connection.Query(query, data, meta)
|
||||||
} else {
|
} else {
|
||||||
eventHandlers.WebSocketMessage(socketId, msg)
|
eventHandlers.WebSocketMessage(socketId, params[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,10 +60,6 @@ func LoadExtensions() {
|
|||||||
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
return Extensions[i].Protocol.Priority < Extensions[j].Protocol.Priority
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, extension := range Extensions {
|
|
||||||
logger.Log.Infof("Extension Properties: %+v", extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
controllers.InitExtensionsMap(ExtensionsMap)
|
controllers.InitExtensionsMap(ExtensionsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func PostTapConfig(c *gin.Context) {
|
|||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
if _, err := startMizuTapperSyncer(ctx, kubernetesProvider, tappedNamespaces, *podRegex, []string{}, tapApi.TrafficFilteringOptions{}, false); err != nil {
|
if _, err := startMizuTapperSyncer(ctx, kubernetesProvider, tappedNamespaces, *podRegex, []string{}, tapApi.TrafficFilteringOptions{}, false, false); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, err)
|
c.JSON(http.StatusInternalServerError, err)
|
||||||
cancel()
|
cancel()
|
||||||
return
|
return
|
||||||
@@ -100,7 +100,7 @@ func GetTapConfig(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, tapConfigToReturn)
|
c.JSON(http.StatusOK, tapConfigToReturn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, targetNamespaces []string, podFilterRegex regexp.Regexp, ignoredUserAgents []string, mizuApiFilteringOptions tapApi.TrafficFilteringOptions, serviceMesh bool) (*kubernetes.MizuTapperSyncer, error) {
|
func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, targetNamespaces []string, podFilterRegex regexp.Regexp, ignoredUserAgents []string, mizuApiFilteringOptions tapApi.TrafficFilteringOptions, serviceMesh bool, tls bool) (*kubernetes.MizuTapperSyncer, error) {
|
||||||
tapperSyncer, err := kubernetes.CreateAndStartMizuTapperSyncer(ctx, provider, kubernetes.TapperSyncerConfig{
|
tapperSyncer, err := kubernetes.CreateAndStartMizuTapperSyncer(ctx, provider, kubernetes.TapperSyncerConfig{
|
||||||
TargetNamespaces: targetNamespaces,
|
TargetNamespaces: targetNamespaces,
|
||||||
PodFilterRegex: podFilterRegex,
|
PodFilterRegex: podFilterRegex,
|
||||||
@@ -113,6 +113,7 @@ func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, t
|
|||||||
MizuApiFilteringOptions: mizuApiFilteringOptions,
|
MizuApiFilteringOptions: mizuApiFilteringOptions,
|
||||||
MizuServiceAccountExists: true, //assume service account exists since install mode will not function without it anyway
|
MizuServiceAccountExists: true, //assume service account exists since install mode will not function without it anyway
|
||||||
ServiceMesh: serviceMesh,
|
ServiceMesh: serviceMesh,
|
||||||
|
Tls: tls,
|
||||||
}, time.Now())
|
}, time.Now())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ type WebSocketEntryMessage struct {
|
|||||||
Data *tapApi.BaseEntry `json:"data,omitempty"`
|
Data *tapApi.BaseEntry `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WebSocketFullEntryMessage struct {
|
||||||
|
*shared.WebSocketMessageMetadata
|
||||||
|
Data *tapApi.Entry `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type WebSocketTappedEntryMessage struct {
|
type WebSocketTappedEntryMessage struct {
|
||||||
*shared.WebSocketMessageMetadata
|
*shared.WebSocketMessageMetadata
|
||||||
Data *tapApi.OutputChannelItem
|
Data *tapApi.OutputChannelItem
|
||||||
@@ -88,6 +93,16 @@ func CreateBaseEntryWebSocketMessage(base *tapApi.BaseEntry) ([]byte, error) {
|
|||||||
return json.Marshal(message)
|
return json.Marshal(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateFullEntryWebSocketMessage(entry *tapApi.Entry) ([]byte, error) {
|
||||||
|
message := &WebSocketFullEntryMessage{
|
||||||
|
WebSocketMessageMetadata: &shared.WebSocketMessageMetadata{
|
||||||
|
MessageType: shared.WebSocketMessageTypeFullEntry,
|
||||||
|
},
|
||||||
|
Data: entry,
|
||||||
|
}
|
||||||
|
return json.Marshal(message)
|
||||||
|
}
|
||||||
|
|
||||||
func CreateWebsocketTappedEntryMessage(base *tapApi.OutputChannelItem) ([]byte, error) {
|
func CreateWebsocketTappedEntryMessage(base *tapApi.OutputChannelItem) ([]byte, error) {
|
||||||
message := &WebSocketTappedEntryMessage{
|
message := &WebSocketTappedEntryMessage{
|
||||||
WebSocketMessageMetadata: &shared.WebSocketMessageMetadata{
|
WebSocketMessageMetadata: &shared.WebSocketMessageMetadata{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -139,7 +140,12 @@ func feedEntry(entry *har.Entry, source string, isSync bool, file string) {
|
|||||||
logger.Log.Debugf("Interesting: %s", entry.Request.URL)
|
logger.Log.Debugf("Interesting: %s", entry.Request.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
ews := EntryWithSource{Entry: *entry, Source: source, Id: uint(0)}
|
u, err := url.Parse(entry.Request.URL)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Errorf("Failed to parse entry URL: %v, err: %v", entry.Request.URL, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ews := EntryWithSource{Entry: *entry, Source: source, Destination: u.Host, Id: uint(0)}
|
||||||
if isSync {
|
if isSync {
|
||||||
GetOasGeneratorInstance().entriesChan <- ews // blocking variant, right?
|
GetOasGeneratorInstance().entriesChan <- ews // blocking variant, right?
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ func (g *oasGenerator) runGeneretor() {
|
|||||||
logger.Log.Errorf("Failed to parse entry URL: %v, err: %v", entry.Request.URL, err)
|
logger.Log.Errorf("Failed to parse entry URL: %v, err: %v", entry.Request.URL, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
val, found := g.ServiceSpecs.Load(u.Host)
|
val, found := g.ServiceSpecs.Load(entryWithSource.Destination)
|
||||||
var gen *SpecGen
|
var gen *SpecGen
|
||||||
if !found {
|
if !found {
|
||||||
gen = NewGen(u.Scheme + "://" + u.Host)
|
gen = NewGen(u.Scheme + "://" + entryWithSource.Destination)
|
||||||
g.ServiceSpecs.Store(u.Host, gen)
|
g.ServiceSpecs.Store(entryWithSource.Destination, gen)
|
||||||
} else {
|
} else {
|
||||||
gen = val.(*SpecGen)
|
gen = val.(*SpecGen)
|
||||||
}
|
}
|
||||||
@@ -105,9 +105,10 @@ func newOasGenerator() *oasGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EntryWithSource struct {
|
type EntryWithSource struct {
|
||||||
Source string
|
Source string
|
||||||
Entry har.Entry
|
Destination string
|
||||||
Id uint
|
Entry har.Entry
|
||||||
|
Id uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type oasGenerator struct {
|
type oasGenerator struct {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func outputSpec(label string, spec *openapi.OpenAPI, t *testing.T) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEntries(t *testing.T) {
|
func TestEntries(t *testing.T) {
|
||||||
logger.InitLoggerStderrOnly(logging.INFO)
|
logger.InitLoggerStd(logging.INFO)
|
||||||
files, err := getFiles("./test_artifacts/")
|
files, err := getFiles("./test_artifacts/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
|
|||||||
30
cli/Makefile
30
cli/Makefile
@@ -1,3 +1,9 @@
|
|||||||
|
SHELL=/bin/bash
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
.ONESHELL:
|
||||||
|
|
||||||
SUFFIX=$(GOOS)_$(GOARCH)
|
SUFFIX=$(GOOS)_$(GOARCH)
|
||||||
COMMIT_HASH=$(shell git rev-parse HEAD)
|
COMMIT_HASH=$(shell git rev-parse HEAD)
|
||||||
GIT_BRANCH=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
|
GIT_BRANCH=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
|
||||||
@@ -5,9 +11,6 @@ GIT_VERSION=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
|
|||||||
BUILD_TIMESTAMP=$(shell date +%s)
|
BUILD_TIMESTAMP=$(shell date +%s)
|
||||||
export VER?=0.0
|
export VER?=0.0
|
||||||
|
|
||||||
.PHONY: help
|
|
||||||
.DEFAULT_GOAL := help
|
|
||||||
|
|
||||||
help: ## This help.
|
help: ## This help.
|
||||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
@@ -16,15 +19,20 @@ install:
|
|||||||
|
|
||||||
build-debug: ## Build mizu CLI for debug
|
build-debug: ## Build mizu CLI for debug
|
||||||
export GCLFAGS='-gcflags="all=-N -l"'
|
export GCLFAGS='-gcflags="all=-N -l"'
|
||||||
${MAKE} build
|
${MAKE} build-base
|
||||||
|
|
||||||
build: ## Build mizu CLI binary (select platform via GOOS / GOARCH env variables).
|
build:
|
||||||
go build ${GCLFAGS} -ldflags="-X 'github.com/up9inc/mizu/cli/mizu.GitCommitHash=$(COMMIT_HASH)' \
|
export LDFLAGS_EXT='-s -w'
|
||||||
-X 'github.com/up9inc/mizu/cli/mizu.Branch=$(GIT_BRANCH)' \
|
${MAKE} build-base
|
||||||
-X 'github.com/up9inc/mizu/cli/mizu.BuildTimestamp=$(BUILD_TIMESTAMP)' \
|
|
||||||
-X 'github.com/up9inc/mizu/cli/mizu.Platform=$(SUFFIX)' \
|
build-base: ## Build mizu CLI binary (select platform via GOOS / GOARCH env variables).
|
||||||
-X 'github.com/up9inc/mizu/cli/mizu.Ver=$(VER)'" \
|
go build ${GCLFAGS} -ldflags="${LDFLAGS_EXT} \
|
||||||
-o bin/mizu_$(SUFFIX) mizu.go
|
-X 'github.com/up9inc/mizu/cli/mizu.GitCommitHash=$(COMMIT_HASH)' \
|
||||||
|
-X 'github.com/up9inc/mizu/cli/mizu.Branch=$(GIT_BRANCH)' \
|
||||||
|
-X 'github.com/up9inc/mizu/cli/mizu.BuildTimestamp=$(BUILD_TIMESTAMP)' \
|
||||||
|
-X 'github.com/up9inc/mizu/cli/mizu.Platform=$(SUFFIX)' \
|
||||||
|
-X 'github.com/up9inc/mizu/cli/mizu.Ver=$(VER)'" \
|
||||||
|
-o bin/mizu_$(SUFFIX) mizu.go
|
||||||
(cd bin && shasum -a 256 mizu_${SUFFIX} > mizu_${SUFFIX}.sha256)
|
(cd bin && shasum -a 256 mizu_${SUFFIX} > mizu_${SUFFIX}.sha256)
|
||||||
|
|
||||||
build-all: ## Build for all supported platforms.
|
build-all: ## Build for all supported platforms.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ curl -Lo mizu https://github.com/up9inc/mizu/releases/download/_VER_/mizu_darwin
|
|||||||
|
|
||||||
**Mac** (AArch64/Apple M1 silicon)
|
**Mac** (AArch64/Apple M1 silicon)
|
||||||
```
|
```
|
||||||
curl -Lo mizu https://github.com/up9inc/mizu/releases/download/_VER_/mizu_darwin_arm64 && chmod 755 mizu
|
rm -f mizu && curl -Lo mizu https://github.com/up9inc/mizu/releases/download/_VER_/mizu_darwin_arm64 && chmod 755 mizu
|
||||||
```
|
```
|
||||||
|
|
||||||
**Linux** (x86-64)
|
**Linux** (x86-64)
|
||||||
|
|||||||
@@ -120,4 +120,5 @@ func init() {
|
|||||||
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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ func startTapperSyncer(ctx context.Context, cancel context.CancelFunc, provider
|
|||||||
MizuApiFilteringOptions: mizuApiFilteringOptions,
|
MizuApiFilteringOptions: mizuApiFilteringOptions,
|
||||||
MizuServiceAccountExists: state.mizuServiceAccountExists,
|
MizuServiceAccountExists: state.mizuServiceAccountExists,
|
||||||
ServiceMesh: config.Config.Tap.ServiceMesh,
|
ServiceMesh: config.Config.Tap.ServiceMesh,
|
||||||
|
Tls: config.Config.Tap.Tls,
|
||||||
}, startTime)
|
}, startTime)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const (
|
|||||||
EnforcePolicyFile = "traffic-validation-file"
|
EnforcePolicyFile = "traffic-validation-file"
|
||||||
ContractFile = "contract"
|
ContractFile = "contract"
|
||||||
ServiceMeshName = "service-mesh"
|
ServiceMeshName = "service-mesh"
|
||||||
|
TlsName = "tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TapConfig struct {
|
type TapConfig struct {
|
||||||
@@ -45,6 +46,7 @@ type TapConfig struct {
|
|||||||
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *TapConfig) PodRegex() *regexp.Regexp {
|
func (config *TapConfig) PodRegex() *regexp.Regexp {
|
||||||
|
|||||||
@@ -80,327 +80,9 @@ Notes:
|
|||||||
|
|
||||||
## List of permissions
|
## List of permissions
|
||||||
|
|
||||||
We broke down this list into few categories:
|
The permissions that are required to run Mizu depend on the configuration.
|
||||||
|
By default Mizu requires cluster-wide permissions.
|
||||||
|
If these are not available to the user, it is possible to run Mizu in namespace-restricted mode which has a reduced set of requirements.
|
||||||
|
This is done by by setting the `mizu-resources-namespace` config option. See [configuration](CONFIGURATION.md) for instructions.
|
||||||
|
|
||||||
- Required - what is needed for `mizu` to run properly on your k8s cluster
|
The different requirements are listed in [the example roles dir](../examples/roles)
|
||||||
- Optional - permissions needed for proper name resolving for service & pod IPs
|
|
||||||
- addition required for policy validation
|
|
||||||
|
|
||||||
### Required permissions
|
|
||||||
|
|
||||||
Mizu needs following permissions on your Kubernetes cluster to run properly
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
resources:
|
|
||||||
- daemonsets
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- patch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services/proxy
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Permissions required running with install command or (optional) for service / pod name resolving
|
|
||||||
|
|
||||||
Mandatory permissions for running with install command.
|
|
||||||
|
|
||||||
Optional for service/pod name resolving in non install standalone
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
resources:
|
|
||||||
- daemonsets
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- patch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services/proxy
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- serviceaccounts
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- clusterroles
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- clusterrolebindings
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- roles
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- rolebindings
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- endpoints
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Permissions for Policy rules validation feature (opt)
|
|
||||||
|
|
||||||
Optionally, in order to use the policy rules validation feature, Mizu requires the following additional permissions:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
```
|
|
||||||
|
|
||||||
- - -
|
|
||||||
|
|
||||||
#### Namespace-Restricted mode
|
|
||||||
|
|
||||||
Alternatively, in order to restrict Mizu to one namespace only (by setting `agent.namespace` in the config file), Mizu needs the following permissions in that namespace:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
resources:
|
|
||||||
- daemonsets
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- patch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services/proxy
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Name resolving in Namespace-Restricted mode (opt)
|
|
||||||
|
|
||||||
To restrict Mizu to one namespace while also resolving IPs, Mizu needs the following permissions in that namespace:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
resources:
|
|
||||||
- daemonsets
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- patch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- services/proxy
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- serviceaccounts
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- roles
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- rbac.authorization.k8s.io
|
|
||||||
resources:
|
|
||||||
- rolebindings
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- services
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
- apps
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- endpoints
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in all namespaces.
|
|
||||||
kind: ClusterRole
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-clusterrole
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch", "delete"]
|
|
||||||
- apiGroups: [ "apps" ]
|
|
||||||
resources: [ "deployments" ]
|
|
||||||
verbs: [ "get", "create", "delete" ]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["daemonsets"]
|
|
||||||
verbs: ["get", "create", "patch", "delete", "list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["namespaces"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
verbs: ["get"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["serviceaccounts"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["clusterroles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["clusterrolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["roles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["rolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["", "apps", "extensions"]
|
|
||||||
resources: ["endpoints"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-clusterrolebindings
|
|
||||||
subjects:
|
|
||||||
- kind: User
|
|
||||||
name: user1
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: mizu-runner-clusterrole
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# This example shows permissions that enrich the logs with additional info
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-runner-debug-clusterrole
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["events.k8s.io"]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-runner-debug-clusterrolebindings
|
||||||
|
subjects:
|
||||||
|
- kind: User
|
||||||
|
name: user1
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: mizu-runner-debug-clusterrole
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# This example shows permissions that are required for Mizu to resolve IPs to service names
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-resolver-clusterrole
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["serviceaccounts"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["clusterroles"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["clusterrolebindings"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["endpoints"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-resolver-clusterrolebindings
|
||||||
|
subjects:
|
||||||
|
- kind: User
|
||||||
|
name: user1
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: mizu-resolver-clusterrole
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in all namespaces with IP resolution disabled.
|
# This example shows the permissions that are required in order to run the `mizu tap` command
|
||||||
# (Traffic will be recorded, but Mizu will not translate IP addresses to names)
|
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
@@ -7,25 +6,22 @@ metadata:
|
|||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods"]
|
resources: ["pods"]
|
||||||
verbs: ["list", "watch", "create", "delete"]
|
verbs: ["list", "watch", "create"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services"]
|
||||||
verbs: ["create", "delete"]
|
verbs: ["get", "create"]
|
||||||
- apiGroups: ["apps"]
|
- apiGroups: ["apps"]
|
||||||
resources: ["daemonsets"]
|
resources: ["daemonsets"]
|
||||||
verbs: ["create", "patch", "delete"]
|
verbs: ["create", "patch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["namespaces"]
|
resources: ["namespaces"]
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
verbs: ["list", "watch", "create", "delete"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services/proxy"]
|
resources: ["services/proxy"]
|
||||||
verbs: ["get"]
|
verbs: ["get", "create"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["configmaps"]
|
resources: ["configmaps"]
|
||||||
verbs: ["get", "create", "delete"]
|
verbs: ["create"]
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
---
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in all namespaces.
|
|
||||||
kind: ClusterRole
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-clusterrole
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["daemonsets"]
|
|
||||||
verbs: ["create", "patch", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["namespaces"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
verbs: ["get"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["serviceaccounts"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["clusterroles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["clusterrolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["roles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["rolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["", "apps", "extensions"]
|
|
||||||
resources: ["endpoints"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-clusterrolebindings
|
|
||||||
subjects:
|
|
||||||
- kind: User
|
|
||||||
name: user1
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: mizu-runner-clusterrole
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in a single namespace.
|
|
||||||
kind: Role
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-role
|
|
||||||
namespace: user1
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch", "delete"]
|
|
||||||
- apiGroups: [ "apps" ]
|
|
||||||
resources: [ "deployments" ]
|
|
||||||
verbs: [ "get", "create", "delete" ]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["daemonsets"]
|
|
||||||
verbs: ["get", "create", "patch", "delete", "list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
verbs: ["get"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["serviceaccounts"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["roles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["rolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["apps", "extensions", ""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["", "apps", "extensions"]
|
|
||||||
resources: ["endpoints"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
|
||||||
kind: RoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-rolebindings
|
|
||||||
namespace: user1
|
|
||||||
subjects:
|
|
||||||
- kind: User
|
|
||||||
name: user1
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
roleRef:
|
|
||||||
kind: Role
|
|
||||||
name: mizu-runner-role
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
27
examples/roles/permissions-ns-debug-optional.yaml
Normal file
27
examples/roles/permissions-ns-debug-optional.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This example shows permissions that enrich the logs with additional info in namespace-restricted mode
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-runner-debug-role
|
||||||
|
namespace: user1
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["events.k8s.io"]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get"]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-runner-debug-rolebindings
|
||||||
|
namespace: user1
|
||||||
|
subjects:
|
||||||
|
- kind: User
|
||||||
|
name: user1
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: mizu-runner-debug-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
39
examples/roles/permissions-ns-ip-resolution-optional.yaml
Normal file
39
examples/roles/permissions-ns-ip-resolution-optional.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# This example shows permissions that are required for Mizu to resolve IPs to service names in namespace-restricted mode
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-resolver-role
|
||||||
|
namespace: user1
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["serviceaccounts"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["roles"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["rolebindings"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["", "apps", "extensions"]
|
||||||
|
resources: ["endpoints"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mizu-resolver-rolebindings
|
||||||
|
namespace: user1
|
||||||
|
subjects:
|
||||||
|
- kind: User
|
||||||
|
name: user1
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: mizu-resolver-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in a single namespace with IP resolution disabled.
|
# This example shows the permissions that are required in order to run the `mizu tap` command in namespace-restricted mode
|
||||||
kind: Role
|
kind: Role
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
@@ -7,22 +7,19 @@ metadata:
|
|||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods"]
|
resources: ["pods"]
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
verbs: ["list", "watch", "create"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services"]
|
||||||
verbs: ["get", "create", "delete"]
|
verbs: ["get", "create", "delete"]
|
||||||
- apiGroups: ["apps"]
|
- apiGroups: ["apps"]
|
||||||
resources: ["daemonsets"]
|
resources: ["daemonsets"]
|
||||||
verbs: ["get", "create", "patch", "delete"]
|
verbs: ["create", "patch", "delete"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services/proxy"]
|
resources: ["services/proxy"]
|
||||||
verbs: ["get"]
|
verbs: ["get", "create", "delete"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["configmaps"]
|
resources: ["configmaps"]
|
||||||
verbs: ["get", "create", "delete"]
|
verbs: ["create", "delete"]
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
---
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in a single namespace.
|
|
||||||
kind: Role
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-role
|
|
||||||
namespace: user1
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["daemonsets"]
|
|
||||||
verbs: ["get", "create", "patch", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
verbs: ["get"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["configmaps"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["serviceaccounts"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["roles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["rolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["", "apps", "extensions"]
|
|
||||||
resources: ["endpoints"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
|
||||||
kind: RoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-rolebindings
|
|
||||||
namespace: user1
|
|
||||||
subjects:
|
|
||||||
- kind: User
|
|
||||||
name: user1
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
roleRef:
|
|
||||||
kind: Role
|
|
||||||
name: mizu-runner-role
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# This example shows the roles required for a user to be able to use Mizu in a single namespace.
|
|
||||||
kind: Role
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-role
|
|
||||||
namespace: user1
|
|
||||||
rules:
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch", "create", "delete"]
|
|
||||||
- apiGroups: ["apps"]
|
|
||||||
resources: ["daemonsets"]
|
|
||||||
verbs: ["get", "create", "patch", "delete"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["services/proxy"]
|
|
||||||
verbs: ["get"]
|
|
||||||
- apiGroups: [ "" ]
|
|
||||||
resources: [ "configmaps" ]
|
|
||||||
verbs: [ "get", "create", "delete" ]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["serviceaccounts"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["roles"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
|
||||||
resources: ["rolebindings"]
|
|
||||||
verbs: ["get", "create", "delete"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["apps", "extensions"]
|
|
||||||
resources: ["services"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["", "apps", "extensions"]
|
|
||||||
resources: ["endpoints"]
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
- apiGroups: ["events.k8s.io"]
|
|
||||||
resources: ["events"]
|
|
||||||
verbs: ["list", "watch"]
|
|
||||||
---
|
|
||||||
kind: RoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: mizu-runner-rolebindings
|
|
||||||
namespace: user1
|
|
||||||
subjects:
|
|
||||||
- kind: User
|
|
||||||
name: user1
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
roleRef:
|
|
||||||
kind: Role
|
|
||||||
name: mizu-runner-role
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
@@ -46,6 +46,7 @@ type TapperSyncerConfig struct {
|
|||||||
MizuApiFilteringOptions api.TrafficFilteringOptions
|
MizuApiFilteringOptions api.TrafficFilteringOptions
|
||||||
MizuServiceAccountExists bool
|
MizuServiceAccountExists bool
|
||||||
ServiceMesh bool
|
ServiceMesh bool
|
||||||
|
Tls bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateAndStartMizuTapperSyncer(ctx context.Context, kubernetesProvider *Provider, config TapperSyncerConfig, startTime time.Time) (*MizuTapperSyncer, error) {
|
func CreateAndStartMizuTapperSyncer(ctx context.Context, kubernetesProvider *Provider, config TapperSyncerConfig, startTime time.Time) (*MizuTapperSyncer, error) {
|
||||||
@@ -324,6 +325,7 @@ func (tapperSyncer *MizuTapperSyncer) updateMizuTappers() error {
|
|||||||
tapperSyncer.config.MizuApiFilteringOptions,
|
tapperSyncer.config.MizuApiFilteringOptions,
|
||||||
tapperSyncer.config.LogLevel,
|
tapperSyncer.config.LogLevel,
|
||||||
tapperSyncer.config.ServiceMesh,
|
tapperSyncer.config.ServiceMesh,
|
||||||
|
tapperSyncer.config.Tls,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ const (
|
|||||||
fieldManagerName = "mizu-manager"
|
fieldManagerName = "mizu-manager"
|
||||||
procfsVolumeName = "proc"
|
procfsVolumeName = "proc"
|
||||||
procfsMountPath = "/hostproc"
|
procfsMountPath = "/hostproc"
|
||||||
|
sysfsVolumeName = "sys"
|
||||||
|
sysfsMountPath = "/sys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewProvider(kubeConfigPath string) (*Provider, error) {
|
func NewProvider(kubeConfigPath string) (*Provider, error) {
|
||||||
@@ -795,7 +797,7 @@ func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespace string, daemonSetName string, podImage string, tapperPodName string, apiServerPodIp string, nodeToTappedPodMap map[string][]core.Pod, serviceAccountName string, resources shared.Resources, imagePullPolicy core.PullPolicy, mizuApiFilteringOptions api.TrafficFilteringOptions, logLevel logging.Level, serviceMesh bool) error {
|
func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespace string, daemonSetName string, podImage string, tapperPodName string, apiServerPodIp string, nodeToTappedPodMap map[string][]core.Pod, serviceAccountName string, resources shared.Resources, imagePullPolicy core.PullPolicy, mizuApiFilteringOptions api.TrafficFilteringOptions, logLevel logging.Level, serviceMesh bool, tls bool) error {
|
||||||
logger.Log.Debugf("Applying %d tapper daemon sets, ns: %s, daemonSetName: %s, podImage: %s, tapperPodName: %s", len(nodeToTappedPodMap), namespace, daemonSetName, podImage, tapperPodName)
|
logger.Log.Debugf("Applying %d tapper daemon sets, ns: %s, daemonSetName: %s, podImage: %s, tapperPodName: %s", len(nodeToTappedPodMap), namespace, daemonSetName, podImage, tapperPodName)
|
||||||
|
|
||||||
if len(nodeToTappedPodMap) == 0 {
|
if len(nodeToTappedPodMap) == 0 {
|
||||||
@@ -821,7 +823,15 @@ func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespac
|
|||||||
}
|
}
|
||||||
|
|
||||||
if serviceMesh {
|
if serviceMesh {
|
||||||
mizuCmd = append(mizuCmd, "--procfs", procfsMountPath, "--servicemesh")
|
mizuCmd = append(mizuCmd, "--servicemesh")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tls {
|
||||||
|
mizuCmd = append(mizuCmd, "--tls")
|
||||||
|
}
|
||||||
|
|
||||||
|
if serviceMesh || tls {
|
||||||
|
mizuCmd = append(mizuCmd, "--procfs", procfsMountPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
agentContainer := applyconfcore.Container()
|
agentContainer := applyconfcore.Container()
|
||||||
@@ -829,12 +839,21 @@ func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespac
|
|||||||
agentContainer.WithImage(podImage)
|
agentContainer.WithImage(podImage)
|
||||||
agentContainer.WithImagePullPolicy(imagePullPolicy)
|
agentContainer.WithImagePullPolicy(imagePullPolicy)
|
||||||
|
|
||||||
caps := applyconfcore.Capabilities().WithDrop("ALL").WithAdd("NET_RAW").WithAdd("NET_ADMIN")
|
caps := applyconfcore.Capabilities().WithDrop("ALL")
|
||||||
|
|
||||||
if serviceMesh {
|
caps = caps.WithAdd("NET_RAW").WithAdd("NET_ADMIN") // to listen to traffic using libpcap
|
||||||
caps = caps.WithAdd("SYS_ADMIN") // for reading /proc/PID/net/ns
|
|
||||||
caps = caps.WithAdd("SYS_PTRACE") // for setting netns to other process
|
if serviceMesh || tls {
|
||||||
caps = caps.WithAdd("DAC_OVERRIDE") // for reading /proc/PID/environ
|
caps = caps.WithAdd("SYS_ADMIN") // to read /proc/PID/net/ns + to install eBPF programs (kernel < 5.8)
|
||||||
|
caps = caps.WithAdd("SYS_PTRACE") // to set netns to other process + to open libssl.so of other process
|
||||||
|
|
||||||
|
if serviceMesh {
|
||||||
|
caps = caps.WithAdd("DAC_OVERRIDE") // to read /proc/PID/environ
|
||||||
|
}
|
||||||
|
|
||||||
|
if tls {
|
||||||
|
caps = caps.WithAdd("SYS_RESOURCE") // to change rlimits for eBPF
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
agentContainer.WithSecurityContext(applyconfcore.SecurityContext().WithCapabilities(caps))
|
agentContainer.WithSecurityContext(applyconfcore.SecurityContext().WithCapabilities(caps))
|
||||||
@@ -910,8 +929,15 @@ func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespac
|
|||||||
//
|
//
|
||||||
procfsVolume := applyconfcore.Volume()
|
procfsVolume := applyconfcore.Volume()
|
||||||
procfsVolume.WithName(procfsVolumeName).WithHostPath(applyconfcore.HostPathVolumeSource().WithPath("/proc"))
|
procfsVolume.WithName(procfsVolumeName).WithHostPath(applyconfcore.HostPathVolumeSource().WithPath("/proc"))
|
||||||
volumeMount := applyconfcore.VolumeMount().WithName(procfsVolumeName).WithMountPath(procfsMountPath).WithReadOnly(true)
|
procfsVolumeMount := applyconfcore.VolumeMount().WithName(procfsVolumeName).WithMountPath(procfsMountPath).WithReadOnly(true)
|
||||||
agentContainer.WithVolumeMounts(volumeMount)
|
agentContainer.WithVolumeMounts(procfsVolumeMount)
|
||||||
|
|
||||||
|
// We need access to /sys in order to install certain eBPF tracepoints
|
||||||
|
//
|
||||||
|
sysfsVolume := applyconfcore.Volume()
|
||||||
|
sysfsVolume.WithName(sysfsVolumeName).WithHostPath(applyconfcore.HostPathVolumeSource().WithPath("/sys"))
|
||||||
|
sysfsVolumeMount := applyconfcore.VolumeMount().WithName(sysfsVolumeName).WithMountPath(sysfsMountPath).WithReadOnly(true)
|
||||||
|
agentContainer.WithVolumeMounts(sysfsVolumeMount)
|
||||||
|
|
||||||
volumeName := ConfigMapName
|
volumeName := ConfigMapName
|
||||||
configMapVolume := applyconfcore.VolumeApplyConfiguration{
|
configMapVolume := applyconfcore.VolumeApplyConfiguration{
|
||||||
@@ -941,7 +967,7 @@ func (provider *Provider) ApplyMizuTapperDaemonSet(ctx context.Context, namespac
|
|||||||
podSpec.WithContainers(agentContainer)
|
podSpec.WithContainers(agentContainer)
|
||||||
podSpec.WithAffinity(affinity)
|
podSpec.WithAffinity(affinity)
|
||||||
podSpec.WithTolerations(noExecuteToleration, noScheduleToleration)
|
podSpec.WithTolerations(noExecuteToleration, noScheduleToleration)
|
||||||
podSpec.WithVolumes(&configMapVolume, procfsVolume)
|
podSpec.WithVolumes(&configMapVolume, procfsVolume, sysfsVolume)
|
||||||
|
|
||||||
podTemplate := applyconfcore.PodTemplateSpec()
|
podTemplate := applyconfcore.PodTemplateSpec()
|
||||||
podTemplate.WithLabels(map[string]string{
|
podTemplate.WithLabels(map[string]string{
|
||||||
|
|||||||
@@ -30,11 +30,24 @@ func getMinimizedPod(fullPod core.Pod) core.Pod {
|
|||||||
Name: fullPod.Name,
|
Name: fullPod.Name,
|
||||||
},
|
},
|
||||||
Status: v1.PodStatus{
|
Status: v1.PodStatus{
|
||||||
PodIP: fullPod.Status.PodIP,
|
PodIP: fullPod.Status.PodIP,
|
||||||
|
ContainerStatuses: getMinimizedContainerStatuses(fullPod),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMinimizedContainerStatuses(fullPod core.Pod) []v1.ContainerStatus {
|
||||||
|
result := make([]v1.ContainerStatus, len(fullPod.Status.ContainerStatuses))
|
||||||
|
|
||||||
|
for i, container := range fullPod.Status.ContainerStatuses {
|
||||||
|
result[i] = v1.ContainerStatus{
|
||||||
|
ContainerID: container.ContainerID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func excludeMizuPods(pods []core.Pod) []core.Pod {
|
func excludeMizuPods(pods []core.Pod) []core.Pod {
|
||||||
mizuPrefixRegex := regexp.MustCompile("^" + MizuResourcesPrefix)
|
mizuPrefixRegex := regexp.MustCompile("^" + MizuResourcesPrefix)
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,21 @@ func InitLogger(logPath string) {
|
|||||||
logging.SetBackend(backend1Leveled, backend2Formatter)
|
logging.SetBackend(backend1Leveled, backend2Formatter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitLoggerStderrOnly(level logging.Level) {
|
func InitLoggerStd(level logging.Level) {
|
||||||
backend := logging.NewLogBackend(os.Stderr, "", 0)
|
var backends []logging.Backend
|
||||||
backendFormatter := logging.NewBackendFormatter(backend, format)
|
|
||||||
|
|
||||||
logging.SetBackend(backendFormatter)
|
stderrBackend := logging.NewLogBackend(os.Stderr, "", 0)
|
||||||
logging.SetLevel(level, "")
|
stderrFormater := logging.NewBackendFormatter(stderrBackend, format)
|
||||||
|
stderrLeveled := logging.AddModuleLevel(stderrFormater)
|
||||||
|
stderrLeveled.SetLevel(logging.ERROR, "")
|
||||||
|
backends = append(backends, stderrLeveled)
|
||||||
|
|
||||||
|
if level >= logging.WARNING {
|
||||||
|
stdoutBackend := logging.NewLogBackend(os.Stdout, "", 0)
|
||||||
|
stdoutFormater := logging.NewBackendFormatter(stdoutBackend, format)
|
||||||
|
stdoutLeveled := logging.AddModuleLevel(stdoutFormater)
|
||||||
|
stdoutLeveled.SetLevel(level, "")
|
||||||
|
backends = append(backends, stdoutLeveled)
|
||||||
|
}
|
||||||
|
logging.SetBackend(backends...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type WebSocketMessageType string
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
WebSocketMessageTypeEntry WebSocketMessageType = "entry"
|
WebSocketMessageTypeEntry WebSocketMessageType = "entry"
|
||||||
|
WebSocketMessageTypeFullEntry WebSocketMessageType = "fullEntry"
|
||||||
WebSocketMessageTypeTappedEntry WebSocketMessageType = "tappedEntry"
|
WebSocketMessageTypeTappedEntry WebSocketMessageType = "tappedEntry"
|
||||||
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
WebSocketMessageTypeUpdateStatus WebSocketMessageType = "status"
|
||||||
WebSocketMessageTypeAnalyzeStatus WebSocketMessageType = "analyzeStatus"
|
WebSocketMessageTypeAnalyzeStatus WebSocketMessageType = "analyzeStatus"
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ var protocol api.Protocol = api.Protocol{
|
|||||||
Priority: 1,
|
Priority: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.Println("Initializing AMQP extension...")
|
|
||||||
}
|
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
|
|||||||
@@ -76,10 +76,6 @@ const (
|
|||||||
TypeHttpResponse
|
TypeHttpResponse
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.Println("Initializing HTTP extension...")
|
|
||||||
}
|
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ var _protocol api.Protocol = api.Protocol{
|
|||||||
Priority: 2,
|
Priority: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.Println("Initializing Kafka extension...")
|
|
||||||
}
|
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
|
|||||||
@@ -24,10 +24,6 @@ var protocol api.Protocol = api.Protocol{
|
|||||||
Priority: 3,
|
Priority: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.Println("Initializing Redis extension...")
|
|
||||||
}
|
|
||||||
|
|
||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4
|
github.com/bradleyfalzon/tlsx v0.0.0-20170624122154-28fd0e59bac4
|
||||||
|
github.com/cilium/ebpf v0.8.0
|
||||||
|
github.com/go-errors/errors v1.4.2
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
|
|||||||
10
tap/go.sum
10
tap/go.sum
@@ -102,6 +102,8 @@ github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1
|
|||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/cilium/ebpf v0.8.0 h1:2V6KSg3FRADVU2BMIRemZ0hV+9OM+aAHhZDjQyjJTAs=
|
||||||
|
github.com/cilium/ebpf v0.8.0/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@@ -161,6 +163,8 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF
|
|||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
|
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
|
||||||
|
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||||
@@ -169,6 +173,7 @@ github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
|
|||||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@@ -366,6 +371,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
|||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -481,6 +488,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
|
|||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@@ -788,6 +797,7 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/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-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-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
"github.com/up9inc/mizu/tap/diagnose"
|
"github.com/up9inc/mizu/tap/diagnose"
|
||||||
"github.com/up9inc/mizu/tap/source"
|
"github.com/up9inc/mizu/tap/source"
|
||||||
|
"github.com/up9inc/mizu/tap/tlstapper"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ var promisc = flag.Bool("promisc", true, "Set promiscuous mode")
|
|||||||
var staleTimeoutSeconds = flag.Int("staletimout", 120, "Max time in seconds to keep connections which don't transmit data")
|
var staleTimeoutSeconds = flag.Int("staletimout", 120, "Max time in seconds to keep connections which don't transmit data")
|
||||||
var pids = flag.String("pids", "", "A comma separated list of PIDs to capture their network namespaces")
|
var pids = flag.String("pids", "", "A comma separated list of PIDs to capture their network namespaces")
|
||||||
var servicemesh = flag.Bool("servicemesh", false, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
var servicemesh = flag.Bool("servicemesh", false, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
||||||
|
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")
|
||||||
|
|
||||||
@@ -95,6 +97,15 @@ func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem,
|
|||||||
tapTargets = opts.FilterAuthorities
|
tapTargets = opts.FilterAuthorities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *tls {
|
||||||
|
for _, e := range extensions {
|
||||||
|
if e.Protocol.Name == "http" {
|
||||||
|
startTlsTapper(e, outputItems, options)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if GetMemoryProfilingEnabled() {
|
if GetMemoryProfilingEnabled() {
|
||||||
diagnose.StartMemoryProfiler(os.Getenv(MemoryProfilingDumpPath), os.Getenv(MemoryProfilingTimeIntervalSeconds))
|
diagnose.StartMemoryProfiler(os.Getenv(MemoryProfilingDumpPath), os.Getenv(MemoryProfilingTimeIntervalSeconds))
|
||||||
}
|
}
|
||||||
@@ -232,3 +243,35 @@ func startPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem)
|
|||||||
diagnose.TapErrors.PrintSummary()
|
diagnose.TapErrors.PrintSummary()
|
||||||
logger.Log.Infof("AppStats: %v", diagnose.AppStats)
|
logger.Log.Infof("AppStats: %v", diagnose.AppStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
||||||
|
tls := tlstapper.TlsTapper{}
|
||||||
|
tlsPerfBufferSize := os.Getpagesize() * 100
|
||||||
|
|
||||||
|
if err := tls.Init(tlsPerfBufferSize); err != nil {
|
||||||
|
tlstapper.LogError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// A quick way to instrument libssl.so without PID filtering - used for debuging and troubleshooting
|
||||||
|
//
|
||||||
|
if os.Getenv("MIZU_GLOBAL_SSL_LIBRARY") != "" {
|
||||||
|
if err := tls.GlobalTap(os.Getenv("MIZU_GLOBAL_SSL_LIBRARY")); err != nil {
|
||||||
|
tlstapper.LogError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tlstapper.UpdateTapTargets(&tls, &tapTargets, *procfs); err != nil {
|
||||||
|
tlstapper.LogError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var emitter api.Emitter = &api.Emitting{
|
||||||
|
AppStats: &diagnose.AppStats,
|
||||||
|
OutputChannel: outputItems,
|
||||||
|
}
|
||||||
|
|
||||||
|
poller := tlstapper.NewTlsPoller(&tls, extension)
|
||||||
|
go poller.Poll(extension, emitter, options)
|
||||||
|
}
|
||||||
|
|||||||
5
tap/tlstapper/bpf-builder/Dockerfile
Normal file
5
tap/tlstapper/bpf-builder/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
FROM alpine:3
|
||||||
|
|
||||||
|
RUN apk --no-cache update && apk --no-cache add clang llvm libbpf-dev go linux-headers
|
||||||
|
|
||||||
|
WORKDIR /mizu
|
||||||
16
tap/tlstapper/bpf-builder/README.md
Normal file
16
tap/tlstapper/bpf-builder/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
# Bpf builder
|
||||||
|
|
||||||
|
Currently we push the ebpf `*.o` files to source control, the motivation for it is to avoid the need for everyone to compile it in their PC.
|
||||||
|
|
||||||
|
This directory helps those who do want to build the .o files, it also serve as a documentation for the process of compiling the ebpf code.
|
||||||
|
|
||||||
|
## How to run ebpf-builder
|
||||||
|
|
||||||
|
From you shell, go to this directory and run `./build.sh`
|
||||||
|
|
||||||
|
Once the docker finished successfully, make sure to commit the four relevant files.
|
||||||
|
> tlstapper_bpfeb.go
|
||||||
|
> tlstapper_bpfel.go
|
||||||
|
> tlstapper_bpfeb.o
|
||||||
|
> tlstapper_bpfel.o
|
||||||
17
tap/tlstapper/bpf-builder/build.sh
Executable file
17
tap/tlstapper/bpf-builder/build.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
MIZU_HOME=$(realpath ../../../)
|
||||||
|
|
||||||
|
docker build -t mizu-ebpf-builder . || exit 1
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--name mizu-ebpf-builder \
|
||||||
|
-v $MIZU_HOME:/mizu \
|
||||||
|
-it mizu-ebpf-builder \
|
||||||
|
sh -c "
|
||||||
|
go generate tap/tlstapper/tls_tapper.go
|
||||||
|
chown $(id -u):$(id -g) tap/tlstapper/tlstapper_bpfeb.go
|
||||||
|
chown $(id -u):$(id -g) tap/tlstapper/tlstapper_bpfeb.o
|
||||||
|
chown $(id -u):$(id -g) tap/tlstapper/tlstapper_bpfel.go
|
||||||
|
chown $(id -u):$(id -g) tap/tlstapper/tlstapper_bpfel.o
|
||||||
|
" || exit 1
|
||||||
215
tap/tlstapper/bpf/fd_to_address_tracepoints.c
Normal file
215
tap/tlstapper/bpf/fd_to_address_tracepoints.c
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "include/headers.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
#include "include/maps.h"
|
||||||
|
#include "include/pids.h"
|
||||||
|
|
||||||
|
struct accept_info {
|
||||||
|
__u64* sockaddr;
|
||||||
|
__u32* addrlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
BPF_HASH(accept_syscall_context, __u64, struct accept_info);
|
||||||
|
|
||||||
|
struct sys_enter_accept4_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 fd;
|
||||||
|
__u64* sockaddr;
|
||||||
|
__u32* addrlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_enter_accept4")
|
||||||
|
void sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct accept_info info = {};
|
||||||
|
|
||||||
|
info.sockaddr = ctx->sockaddr;
|
||||||
|
info.addrlen = ctx->addrlen;
|
||||||
|
|
||||||
|
long err = bpf_map_update_elem(&accept_syscall_context, &id, &info, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting accept info (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sys_exit_accept4_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_exit_accept4")
|
||||||
|
void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->ret < 0) {
|
||||||
|
bpf_map_delete_elem(&accept_syscall_context, &id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct accept_info *infoPtr = bpf_map_lookup_elem(&accept_syscall_context, &id);
|
||||||
|
|
||||||
|
if (infoPtr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct accept_info info;
|
||||||
|
long err = bpf_probe_read(&info, sizeof(struct accept_info), infoPtr);
|
||||||
|
|
||||||
|
bpf_map_delete_elem(&accept_syscall_context, &id);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading accept info from accept syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__u32 addrlen;
|
||||||
|
bpf_probe_read(&addrlen, sizeof(__u32), info.addrlen);
|
||||||
|
|
||||||
|
if (addrlen != 16) {
|
||||||
|
// Currently only ipv4 is supported linux-src/include/linux/inet.h
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fd_info fdinfo = {
|
||||||
|
.flags = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
|
||||||
|
|
||||||
|
__u32 pid = id >> 32;
|
||||||
|
__u32 fd = (__u32) ctx->ret;
|
||||||
|
|
||||||
|
__u64 key = (__u64) pid << 32 | fd;
|
||||||
|
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting fd to address mapping from accept (key: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), key, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct connect_info {
|
||||||
|
__u64 fd;
|
||||||
|
__u64* sockaddr;
|
||||||
|
__u32 addrlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
BPF_HASH(connect_syscall_info, __u64, struct connect_info);
|
||||||
|
|
||||||
|
struct sys_enter_connect_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 fd;
|
||||||
|
__u64* sockaddr;
|
||||||
|
__u32 addrlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_enter_connect")
|
||||||
|
void sys_enter_connect(struct sys_enter_connect_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct connect_info info = {};
|
||||||
|
|
||||||
|
info.sockaddr = ctx->sockaddr;
|
||||||
|
info.addrlen = ctx->addrlen;
|
||||||
|
info.fd = ctx->fd;
|
||||||
|
|
||||||
|
long err = bpf_map_update_elem(&connect_syscall_info, &id, &info, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting connect info (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sys_exit_connect_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_exit_connect")
|
||||||
|
void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commented because of async connect which set errno to EINPROGRESS
|
||||||
|
//
|
||||||
|
// if (ctx->ret != 0) {
|
||||||
|
// bpf_map_delete_elem(&accept_syscall_context, &id);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
struct connect_info *infoPtr = bpf_map_lookup_elem(&connect_syscall_info, &id);
|
||||||
|
|
||||||
|
if (infoPtr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct connect_info info;
|
||||||
|
long err = bpf_probe_read(&info, sizeof(struct connect_info), infoPtr);
|
||||||
|
|
||||||
|
bpf_map_delete_elem(&connect_syscall_info, &id);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading connect info from connect syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.addrlen != 16) {
|
||||||
|
// Currently only ipv4 is supported linux-src/include/linux/inet.h
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fd_info fdinfo = {
|
||||||
|
.flags = FLAGS_IS_CLIENT_BIT
|
||||||
|
};
|
||||||
|
|
||||||
|
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
|
||||||
|
|
||||||
|
__u32 pid = id >> 32;
|
||||||
|
__u32 fd = (__u32) info.fd;
|
||||||
|
|
||||||
|
__u64 key = (__u64) pid << 32 | fd;
|
||||||
|
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting fd to address mapping from connect (key: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), key, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
tap/tlstapper/bpf/fd_tracepoints.c
Normal file
96
tap/tlstapper/bpf/fd_tracepoints.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "include/headers.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
#include "include/maps.h"
|
||||||
|
#include "include/pids.h"
|
||||||
|
|
||||||
|
struct sys_enter_read_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 fd;
|
||||||
|
__u64* buf;
|
||||||
|
__u64 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_enter_read")
|
||||||
|
void sys_enter_read(struct sys_enter_read_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info *infoPtr = bpf_map_lookup_elem(&ssl_read_context, &id);
|
||||||
|
|
||||||
|
if (infoPtr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info info;
|
||||||
|
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading read info from read syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.fd = ctx->fd;
|
||||||
|
|
||||||
|
err = bpf_map_update_elem(&ssl_read_context, &id, &info, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting file descriptor from read syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sys_enter_write_ctx {
|
||||||
|
__u64 __unused_syscall_header;
|
||||||
|
__u32 __unused_syscall_nr;
|
||||||
|
|
||||||
|
__u64 fd;
|
||||||
|
__u64* buf;
|
||||||
|
__u64 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("tracepoint/syscalls/sys_enter_write")
|
||||||
|
void sys_enter_write(struct sys_enter_write_ctx *ctx) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info *infoPtr = bpf_map_lookup_elem(&ssl_write_context, &id);
|
||||||
|
|
||||||
|
if (infoPtr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info info;
|
||||||
|
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading write context from write syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.fd = ctx->fd;
|
||||||
|
|
||||||
|
err = bpf_map_update_elem(&ssl_write_context, &id, &info, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting file descriptor from write syscall (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
tap/tlstapper/bpf/include/headers.h
Normal file
16
tap/tlstapper/bpf/include/headers.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HEADERS__
|
||||||
|
#define __HEADERS__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <bpf/bpf_helpers.h>
|
||||||
|
#include "bpf/bpf_tracing.h"
|
||||||
|
|
||||||
|
#endif /* __HEADERS__ */
|
||||||
63
tap/tlstapper/bpf/include/maps.h
Normal file
63
tap/tlstapper/bpf/include/maps.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MAPS__
|
||||||
|
#define __MAPS__
|
||||||
|
|
||||||
|
#define FLAGS_IS_CLIENT_BIT (1 << 0)
|
||||||
|
#define FLAGS_IS_READ_BIT (1 << 1)
|
||||||
|
|
||||||
|
// The same struct can be found in Chunk.go
|
||||||
|
//
|
||||||
|
// Be careful when editing, alignment and padding should be exactly the same in go/c.
|
||||||
|
//
|
||||||
|
struct tlsChunk {
|
||||||
|
__u32 pid;
|
||||||
|
__u32 tgid;
|
||||||
|
__u32 len;
|
||||||
|
__u32 recorded;
|
||||||
|
__u32 fd;
|
||||||
|
__u32 flags;
|
||||||
|
__u8 address[16];
|
||||||
|
__u8 data[4096]; // Must be N^2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssl_info {
|
||||||
|
void* buffer;
|
||||||
|
__u32 fd;
|
||||||
|
|
||||||
|
// for ssl_write and ssl_read must be zero
|
||||||
|
// for ssl_write_ex and ssl_read_ex save the *written/*readbytes pointer.
|
||||||
|
//
|
||||||
|
size_t *count_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fd_info {
|
||||||
|
__u8 ipv4_addr[16]; // struct sockaddr (linux-src/include/linux/socket.h)
|
||||||
|
__u8 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BPF_MAP(_name, _type, _key_type, _value_type, _max_entries) \
|
||||||
|
struct bpf_map_def SEC("maps") _name = { \
|
||||||
|
.type = _type, \
|
||||||
|
.key_size = sizeof(_key_type), \
|
||||||
|
.value_size = sizeof(_value_type), \
|
||||||
|
.max_entries = _max_entries, \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BPF_HASH(_name, _key_type, _value_type) \
|
||||||
|
BPF_MAP(_name, BPF_MAP_TYPE_HASH, _key_type, _value_type, 4096)
|
||||||
|
|
||||||
|
#define BPF_PERF_OUTPUT(_name) \
|
||||||
|
BPF_MAP(_name, BPF_MAP_TYPE_PERF_EVENT_ARRAY, int, __u32, 1024)
|
||||||
|
|
||||||
|
BPF_HASH(pids_map, __u32, __u32);
|
||||||
|
BPF_HASH(ssl_write_context, __u64, struct ssl_info);
|
||||||
|
BPF_HASH(ssl_read_context, __u64, struct ssl_info);
|
||||||
|
BPF_HASH(file_descriptor_to_ipv4, __u64, struct fd_info);
|
||||||
|
BPF_PERF_OUTPUT(chunks_buffer);
|
||||||
|
|
||||||
|
#endif /* __MAPS__ */
|
||||||
23
tap/tlstapper/bpf/include/pids.h
Normal file
23
tap/tlstapper/bpf/include/pids.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PIDS__
|
||||||
|
#define __PIDS__
|
||||||
|
|
||||||
|
int should_tap(__u32 pid) {
|
||||||
|
__u32* shouldTap = bpf_map_lookup_elem(&pids_map, &pid);
|
||||||
|
|
||||||
|
if (shouldTap != NULL && *shouldTap == 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__u32 globalPid = 0;
|
||||||
|
__u32* shouldTapGlobally = bpf_map_lookup_elem(&pids_map, &globalPid);
|
||||||
|
|
||||||
|
return shouldTapGlobally != NULL && *shouldTapGlobally == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __PIDS__ */
|
||||||
12
tap/tlstapper/bpf/include/util.h
Normal file
12
tap/tlstapper/bpf/include/util.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTIL__
|
||||||
|
#define __UTIL__
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
|
||||||
|
#endif /* __UTIL__ */
|
||||||
198
tap/tlstapper/bpf/openssl_uprobes.c
Normal file
198
tap/tlstapper/bpf/openssl_uprobes.c
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "include/headers.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
#include "include/maps.h"
|
||||||
|
#include "include/pids.h"
|
||||||
|
|
||||||
|
// Heap-like area for eBPF programs - stack size limited to 512 bytes, we must use maps for bigger (chunk) objects.
|
||||||
|
//
|
||||||
|
struct {
|
||||||
|
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
||||||
|
__uint(max_entries, 1);
|
||||||
|
__type(key, int);
|
||||||
|
__type(value, struct tlsChunk);
|
||||||
|
} heap SEC(".maps");
|
||||||
|
|
||||||
|
static __always_inline int ssl_uprobe(void* ssl, void* buffer, int num, struct bpf_map_def* map_fd, size_t *count_ptr) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info info = {};
|
||||||
|
|
||||||
|
info.fd = -1;
|
||||||
|
info.count_ptr = count_ptr;
|
||||||
|
info.buffer = buffer;
|
||||||
|
|
||||||
|
long err = bpf_map_update_elem(map_fd, &id, &info, BPF_ANY);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error putting ssl context (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline int ssl_uretprobe(struct pt_regs *ctx, struct bpf_map_def* map_fd, __u32 flags) {
|
||||||
|
__u64 id = bpf_get_current_pid_tgid();
|
||||||
|
|
||||||
|
if (!should_tap(id >> 32)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info *infoPtr = bpf_map_lookup_elem(map_fd, &id);
|
||||||
|
|
||||||
|
if (infoPtr == 0) {
|
||||||
|
char msg[] = "Error getting ssl context info (id: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_info info;
|
||||||
|
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||||
|
|
||||||
|
bpf_map_delete_elem(map_fd, &id);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading ssl context (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.fd == -1) {
|
||||||
|
char msg[] = "File descriptor is missing from ssl info (id: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countBytes = PT_REGS_RC(ctx);
|
||||||
|
|
||||||
|
if (info.count_ptr != 0) {
|
||||||
|
// ssl_read_ex and ssl_write_ex return 1 for success
|
||||||
|
//
|
||||||
|
if (countBytes != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tempCount;
|
||||||
|
long err = bpf_probe_read(&tempCount, sizeof(size_t), (void*) info.count_ptr);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading bytes count of _ex (id: %ld) (err: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
countBytes = tempCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (countBytes <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tlsChunk* c;
|
||||||
|
int zero = 0;
|
||||||
|
|
||||||
|
// If other thread, running on the same CPU get to this point at the same time like us
|
||||||
|
// the data will be corrupted - protection may be added in the future
|
||||||
|
//
|
||||||
|
c = bpf_map_lookup_elem(&heap, &zero);
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
char msg[] = "Unable to allocate chunk (id: %ld)";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t recorded = MIN(countBytes, sizeof(c->data));
|
||||||
|
|
||||||
|
c->flags = flags;
|
||||||
|
c->pid = id >> 32;
|
||||||
|
c->tgid = id;
|
||||||
|
c->len = countBytes;
|
||||||
|
c->recorded = recorded;
|
||||||
|
c->fd = info.fd;
|
||||||
|
|
||||||
|
// This ugly trick is for the ebpf verifier happiness
|
||||||
|
//
|
||||||
|
if (recorded == sizeof(c->data)) {
|
||||||
|
err = bpf_probe_read(c->data, sizeof(c->data), info.buffer);
|
||||||
|
} else {
|
||||||
|
recorded &= sizeof(c->data) - 1; // Buffer must be N^2
|
||||||
|
err = bpf_probe_read(c->data, recorded, info.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading from ssl buffer %ld - %ld";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__u32 pid = id >> 32;
|
||||||
|
__u32 fd = info.fd;
|
||||||
|
__u64 key = (__u64) pid << 32 | fd;
|
||||||
|
|
||||||
|
struct fd_info *fdinfo = bpf_map_lookup_elem(&file_descriptor_to_ipv4, &key);
|
||||||
|
|
||||||
|
if (fdinfo != 0) {
|
||||||
|
err = bpf_probe_read(c->address, sizeof(c->address), fdinfo->ipv4_addr);
|
||||||
|
c->flags |= (fdinfo->flags & FLAGS_IS_CLIENT_BIT);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
char msg[] = "Error reading from fd address %ld - %ld";
|
||||||
|
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf_perf_event_output(ctx, &chunks_buffer, BPF_F_CURRENT_CPU, c, sizeof(struct tlsChunk));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uprobe/ssl_write")
|
||||||
|
int BPF_KPROBE(ssl_write, void* ssl, void* buffer, int num) {
|
||||||
|
return ssl_uprobe(ssl, buffer, num, &ssl_write_context, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uretprobe/ssl_write")
|
||||||
|
int BPF_KPROBE(ssl_ret_write) {
|
||||||
|
return ssl_uretprobe(ctx, &ssl_write_context, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uprobe/ssl_read")
|
||||||
|
int BPF_KPROBE(ssl_read, void* ssl, void* buffer, int num) {
|
||||||
|
return ssl_uprobe(ssl, buffer, num, &ssl_read_context, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uretprobe/ssl_read")
|
||||||
|
int BPF_KPROBE(ssl_ret_read) {
|
||||||
|
return ssl_uretprobe(ctx, &ssl_read_context, FLAGS_IS_READ_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uprobe/ssl_write_ex")
|
||||||
|
int BPF_KPROBE(ssl_write_ex, void* ssl, void* buffer, size_t num, size_t *written) {
|
||||||
|
return ssl_uprobe(ssl, buffer, num, &ssl_write_context, written);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uretprobe/ssl_write_ex")
|
||||||
|
int BPF_KPROBE(ssl_ret_write_ex) {
|
||||||
|
return ssl_uretprobe(ctx, &ssl_write_context, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uprobe/ssl_read_ex")
|
||||||
|
int BPF_KPROBE(ssl_read_ex, void* ssl, void* buffer, size_t num, size_t *readbytes) {
|
||||||
|
return ssl_uprobe(ssl, buffer, num, &ssl_read_context, readbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("uretprobe/ssl_read_ex")
|
||||||
|
int BPF_KPROBE(ssl_ret_read_ex) {
|
||||||
|
return ssl_uretprobe(ctx, &ssl_read_context, FLAGS_IS_READ_BIT);
|
||||||
|
}
|
||||||
18
tap/tlstapper/bpf/tls_tapper.c
Normal file
18
tap/tlstapper/bpf/tls_tapper.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Note: This file is licenced differently from the rest of the project
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
Copyright (C) UP9 Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "include/headers.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
#include "include/maps.h"
|
||||||
|
#include "include/pids.h"
|
||||||
|
|
||||||
|
// To avoid multiple .o files
|
||||||
|
//
|
||||||
|
#include "openssl_uprobes.c"
|
||||||
|
#include "fd_tracepoints.c"
|
||||||
|
#include "fd_to_address_tracepoints.c"
|
||||||
|
|
||||||
|
char _license[] SEC("license") = "GPL";
|
||||||
70
tap/tlstapper/chunk.go
Normal file
70
tap/tlstapper/chunk.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const FLAGS_IS_CLIENT_BIT int32 = (1 << 0)
|
||||||
|
const FLAGS_IS_READ_BIT int32 = (1 << 1)
|
||||||
|
|
||||||
|
// The same struct can be found in maps.h
|
||||||
|
//
|
||||||
|
// Be careful when editing, alignment and padding should be exactly the same in go/c.
|
||||||
|
//
|
||||||
|
type tlsChunk struct {
|
||||||
|
Pid int32
|
||||||
|
Tgid int32
|
||||||
|
Len int32
|
||||||
|
Recorded int32
|
||||||
|
Fd int32
|
||||||
|
Flags int32
|
||||||
|
Address [16]byte
|
||||||
|
Data [4096]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) getAddress() (net.IP, uint16, error) {
|
||||||
|
address := bytes.NewReader(c.Address[:])
|
||||||
|
var family uint16
|
||||||
|
var port uint16
|
||||||
|
var ip32 uint32
|
||||||
|
|
||||||
|
if err := binary.Read(address, binary.BigEndian, &family); err != nil {
|
||||||
|
return nil, 0, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(address, binary.BigEndian, &port); err != nil {
|
||||||
|
return nil, 0, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(address, binary.BigEndian, &ip32); err != nil {
|
||||||
|
return nil, 0, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := net.IP{uint8(ip32 >> 24), uint8(ip32 >> 16), uint8(ip32 >> 8), uint8(ip32)}
|
||||||
|
|
||||||
|
return ip, port, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) isClient() bool {
|
||||||
|
return c.Flags&FLAGS_IS_CLIENT_BIT != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) isServer() bool {
|
||||||
|
return !c.isClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) isRead() bool {
|
||||||
|
return c.Flags&FLAGS_IS_READ_BIT != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) isWrite() bool {
|
||||||
|
return !c.isRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tlsChunk) getRecordedData() []byte {
|
||||||
|
return c.Data[:c.Recorded]
|
||||||
|
}
|
||||||
63
tap/tlstapper/ssllib_finder.go
Normal file
63
tap/tlstapper/ssllib_finder.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func findSsllib(procfs string, pid uint32) (string, error) {
|
||||||
|
binary, err := os.Readlink(fmt.Sprintf("%s/%d/exe", procfs, pid))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Log.Debugf("Binary file for %v = %v", pid, binary)
|
||||||
|
|
||||||
|
if strings.HasSuffix(binary, "/node") {
|
||||||
|
return findLibraryByPid(procfs, pid, binary)
|
||||||
|
} else {
|
||||||
|
return findLibraryByPid(procfs, pid, "libssl.so")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findLibraryByPid(procfs string, pid uint32, libraryName string) (string, error) {
|
||||||
|
file, err := os.Open(fmt.Sprintf("%v/%v/maps", procfs, pid))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
parts := strings.Fields(scanner.Text())
|
||||||
|
|
||||||
|
if len(parts) <= 5 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
filepath := parts[5]
|
||||||
|
|
||||||
|
if !strings.Contains(filepath, libraryName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath := fmt.Sprintf("%v/%v/root/%v", procfs, pid, filepath)
|
||||||
|
|
||||||
|
if _, err := os.Stat(fullpath); os.IsNotExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullpath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.Errorf("%s not found for PID %d", libraryName, pid)
|
||||||
|
}
|
||||||
153
tap/tlstapper/ssllib_hooks.go
Normal file
153
tap/tlstapper/ssllib_hooks.go
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cilium/ebpf/link"
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sslHooks struct {
|
||||||
|
sslWriteProbe link.Link
|
||||||
|
sslWriteRetProbe link.Link
|
||||||
|
sslReadProbe link.Link
|
||||||
|
sslReadRetProbe link.Link
|
||||||
|
sslWriteExProbe link.Link
|
||||||
|
sslWriteExRetProbe link.Link
|
||||||
|
sslReadExProbe link.Link
|
||||||
|
sslReadExRetProbe link.Link
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sslHooks) installUprobes(bpfObjects *tlsTapperObjects, sslLibraryPath string) error {
|
||||||
|
sslLibrary, err := link.OpenExecutable(sslLibraryPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
sslOffsets, err := getSslOffsets(sslLibraryPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.installSslHooks(bpfObjects, sslLibrary, sslOffsets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sslHooks) installSslHooks(bpfObjects *tlsTapperObjects, sslLibrary *link.Executable, offsets sslOffsets) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
s.sslWriteProbe, err = sslLibrary.Uprobe("SSL_write", bpfObjects.SslWrite, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslWriteOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sslWriteRetProbe, err = sslLibrary.Uretprobe("SSL_write", bpfObjects.SslRetWrite, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslWriteOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sslReadProbe, err = sslLibrary.Uprobe("SSL_read", bpfObjects.SslRead, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslReadOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sslReadRetProbe, err = sslLibrary.Uretprobe("SSL_read", bpfObjects.SslRetRead, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslReadOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if offsets.SslWriteExOffset != 0 {
|
||||||
|
s.sslWriteExProbe, err = sslLibrary.Uprobe("SSL_write_ex", bpfObjects.SslWriteEx, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslWriteExOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sslWriteExRetProbe, err = sslLibrary.Uretprobe("SSL_write_ex", bpfObjects.SslRetWriteEx, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslWriteExOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if offsets.SslReadExOffset != 0 {
|
||||||
|
s.sslReadExProbe, err = sslLibrary.Uprobe("SSL_read_ex", bpfObjects.SslReadEx, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslReadExOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sslReadExRetProbe, err = sslLibrary.Uretprobe("SSL_read_ex", bpfObjects.SslRetReadEx, &link.UprobeOptions{
|
||||||
|
Offset: offsets.SslReadExOffset,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sslHooks) close() []error {
|
||||||
|
errors := make([]error, 0)
|
||||||
|
|
||||||
|
if err := s.sslWriteProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sslWriteRetProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sslReadProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sslReadRetProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.sslWriteExProbe != nil {
|
||||||
|
if err := s.sslWriteExProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.sslWriteExRetProbe != nil {
|
||||||
|
if err := s.sslWriteExRetProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.sslReadExProbe != nil {
|
||||||
|
if err := s.sslReadExProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.sslReadExRetProbe != nil {
|
||||||
|
if err := s.sslReadExRetProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors
|
||||||
|
}
|
||||||
113
tap/tlstapper/ssllib_offsets.go
Normal file
113
tap/tlstapper/ssllib_offsets.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sslOffsets struct {
|
||||||
|
SslWriteOffset uint64
|
||||||
|
SslReadOffset uint64
|
||||||
|
SslWriteExOffset uint64
|
||||||
|
SslReadExOffset uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSslOffsets(sslLibraryPath string) (sslOffsets, error) {
|
||||||
|
sslElf, err := elf.Open(sslLibraryPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return sslOffsets{}, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer sslElf.Close()
|
||||||
|
|
||||||
|
base, err := findBaseAddress(sslElf, sslLibraryPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return sslOffsets{}, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
offsets, err := findSslOffsets(sslElf, base)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return sslOffsets{}, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Log.Debugf("Found TLS offsets (base: 0x%X) (write: 0x%X) (read: 0x%X)", base, offsets.SslWriteOffset, offsets.SslReadOffset)
|
||||||
|
return offsets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findBaseAddress(sslElf *elf.File, sslLibraryPath string) (uint64, error) {
|
||||||
|
for _, prog := range sslElf.Progs {
|
||||||
|
if prog.Type == elf.PT_LOAD {
|
||||||
|
return prog.Paddr, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, errors.New(fmt.Sprintf("Program header not found in %v", sslLibraryPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
func findSslOffsets(sslElf *elf.File, base uint64) (sslOffsets, error) {
|
||||||
|
symbolsMap := make(map[string]elf.Symbol)
|
||||||
|
|
||||||
|
if err := buildSymbolsMap(sslElf.Symbols, symbolsMap); err != nil {
|
||||||
|
return sslOffsets{}, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := buildSymbolsMap(sslElf.DynamicSymbols, symbolsMap); err != nil {
|
||||||
|
return sslOffsets{}, errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sslWriteSymbol, sslReadSymbol, sslWriteExSymbol, sslReadExSymbol elf.Symbol
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
if sslWriteSymbol, ok = symbolsMap["SSL_write"]; !ok {
|
||||||
|
return sslOffsets{}, errors.New("SSL_write symbol not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if sslReadSymbol, ok = symbolsMap["SSL_read"]; !ok {
|
||||||
|
return sslOffsets{}, errors.New("SSL_read symbol not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sslWriteExOffset, sslReadExOffset uint64
|
||||||
|
|
||||||
|
if sslWriteExSymbol, ok = symbolsMap["SSL_write_ex"]; !ok {
|
||||||
|
sslWriteExOffset = 0 // libssl.so.1.0 doesn't have the _ex functions
|
||||||
|
} else {
|
||||||
|
sslWriteExOffset = sslWriteExSymbol.Value - base
|
||||||
|
}
|
||||||
|
|
||||||
|
if sslReadExSymbol, ok = symbolsMap["SSL_read_ex"]; !ok {
|
||||||
|
sslReadExOffset = 0 // libssl.so.1.0 doesn't have the _ex functions
|
||||||
|
} else {
|
||||||
|
sslReadExOffset = sslReadExSymbol.Value - base
|
||||||
|
}
|
||||||
|
|
||||||
|
return sslOffsets{
|
||||||
|
SslWriteOffset: sslWriteSymbol.Value - base,
|
||||||
|
SslReadOffset: sslReadSymbol.Value - base,
|
||||||
|
SslWriteExOffset: sslWriteExOffset,
|
||||||
|
SslReadExOffset: sslReadExOffset,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSymbolsMap(sectionGetter func() ([]elf.Symbol, error), symbols map[string]elf.Symbol) error {
|
||||||
|
syms, err := sectionGetter()
|
||||||
|
|
||||||
|
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, sym := range syms {
|
||||||
|
if elf.ST_TYPE(sym.Info) != elf.STT_FUNC {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols[sym.Name] = sym
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
87
tap/tlstapper/syscall_hooks.go
Normal file
87
tap/tlstapper/syscall_hooks.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cilium/ebpf/link"
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type syscallHooks struct {
|
||||||
|
sysEnterRead link.Link
|
||||||
|
sysEnterWrite link.Link
|
||||||
|
sysEnterAccept4 link.Link
|
||||||
|
sysExitAccept4 link.Link
|
||||||
|
sysEnterConnect link.Link
|
||||||
|
sysExitConnect link.Link
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syscallHooks) installSyscallHooks(bpfObjects *tlsTapperObjects) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
s.sysEnterRead, err = link.Tracepoint("syscalls", "sys_enter_read", bpfObjects.SysEnterRead)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sysEnterWrite, err = link.Tracepoint("syscalls", "sys_enter_write", bpfObjects.SysEnterWrite)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sysEnterAccept4, err = link.Tracepoint("syscalls", "sys_enter_accept4", bpfObjects.SysEnterAccept4)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sysExitAccept4, err = link.Tracepoint("syscalls", "sys_exit_accept4", bpfObjects.SysExitAccept4)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sysEnterConnect, err = link.Tracepoint("syscalls", "sys_enter_connect", bpfObjects.SysEnterConnect)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sysExitConnect, err = link.Tracepoint("syscalls", "sys_exit_connect", bpfObjects.SysExitConnect)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syscallHooks) close() []error {
|
||||||
|
errors := make([]error, 0)
|
||||||
|
|
||||||
|
if err := s.sysEnterRead.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sysEnterWrite.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sysEnterAccept4.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sysExitAccept4.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sysEnterConnect.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sysExitConnect.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors
|
||||||
|
}
|
||||||
162
tap/tlstapper/tls_poller.go
Normal file
162
tap/tlstapper/tls_poller.go
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"encoding/hex"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
const UNKNOWN_PORT uint16 = 80
|
||||||
|
const UNKNOWN_HOST string = "127.0.0.1"
|
||||||
|
|
||||||
|
type tlsPoller struct {
|
||||||
|
tls *TlsTapper
|
||||||
|
readers map[string]*tlsReader
|
||||||
|
closedReaders chan string
|
||||||
|
reqResMatcher api.RequestResponseMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTlsPoller(tls *TlsTapper, extension *api.Extension) *tlsPoller {
|
||||||
|
return &tlsPoller{
|
||||||
|
tls: tls,
|
||||||
|
readers: make(map[string]*tlsReader),
|
||||||
|
closedReaders: make(chan string, 100),
|
||||||
|
reqResMatcher: extension.Dissector.NewResponseRequestMatcher(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) Poll(extension *api.Extension,
|
||||||
|
emitter api.Emitter, options *api.TrafficFilteringOptions) {
|
||||||
|
|
||||||
|
chunks := make(chan *tlsChunk)
|
||||||
|
|
||||||
|
go p.tls.pollPerf(chunks)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case chunk, ok := <-chunks:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.handleTlsChunk(chunk, extension, emitter, options); err != nil {
|
||||||
|
LogError(err)
|
||||||
|
}
|
||||||
|
case key := <-p.closedReaders:
|
||||||
|
delete(p.readers, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) handleTlsChunk(chunk *tlsChunk, extension *api.Extension,
|
||||||
|
emitter api.Emitter, options *api.TrafficFilteringOptions) error {
|
||||||
|
ip, port, err := chunk.getAddress()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
key := buildTlsKey(chunk, ip, port)
|
||||||
|
reader, exists := p.readers[key]
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
reader = p.startNewTlsReader(chunk, ip, port, key, extension, emitter, options)
|
||||||
|
p.readers[key] = reader
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.chunks <- chunk
|
||||||
|
|
||||||
|
if os.Getenv("MIZU_VERBOSE_TLS_TAPPER") == "true" {
|
||||||
|
logTls(chunk, ip, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) startNewTlsReader(chunk *tlsChunk, ip net.IP, port uint16, key string, extension *api.Extension,
|
||||||
|
emitter api.Emitter, options *api.TrafficFilteringOptions) *tlsReader {
|
||||||
|
|
||||||
|
reader := &tlsReader{
|
||||||
|
key: key,
|
||||||
|
chunks: make(chan *tlsChunk, 1),
|
||||||
|
doneHandler: func(r *tlsReader) {
|
||||||
|
p.closeReader(key, r)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
isRequest := (chunk.isClient() && chunk.isWrite()) || (chunk.isServer() && chunk.isRead())
|
||||||
|
tcpid := buildTcpId(isRequest, ip, port)
|
||||||
|
|
||||||
|
go dissect(extension, reader, isRequest, &tcpid, emitter, options, p.reqResMatcher)
|
||||||
|
return reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func dissect(extension *api.Extension, reader *tlsReader, isRequest bool, tcpid *api.TcpID,
|
||||||
|
emitter api.Emitter, options *api.TrafficFilteringOptions, reqResMatcher api.RequestResponseMatcher) {
|
||||||
|
b := bufio.NewReader(reader)
|
||||||
|
|
||||||
|
err := extension.Dissector.Dissect(b, isRequest, tcpid, &api.CounterPair{},
|
||||||
|
&api.SuperTimer{}, &api.SuperIdentifier{}, emitter, options, reqResMatcher)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Warningf("Error dissecting TLS %v - %v", tcpid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsPoller) closeReader(key string, r *tlsReader) {
|
||||||
|
close(r.chunks)
|
||||||
|
p.closedReaders <- key
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildTlsKey(chunk *tlsChunk, ip net.IP, port uint16) string {
|
||||||
|
return fmt.Sprintf("%v:%v-%v:%v", chunk.isClient(), chunk.isRead(), ip, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildTcpId(isRequest bool, ip net.IP, port uint16) api.TcpID {
|
||||||
|
if isRequest {
|
||||||
|
return api.TcpID{
|
||||||
|
SrcIP: UNKNOWN_HOST,
|
||||||
|
DstIP: ip.String(),
|
||||||
|
SrcPort: strconv.Itoa(int(UNKNOWN_PORT)),
|
||||||
|
DstPort: strconv.FormatInt(int64(port), 10),
|
||||||
|
Ident: "",
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return api.TcpID{
|
||||||
|
SrcIP: ip.String(),
|
||||||
|
DstIP: UNKNOWN_HOST,
|
||||||
|
SrcPort: strconv.FormatInt(int64(port), 10),
|
||||||
|
DstPort: strconv.Itoa(int(UNKNOWN_PORT)),
|
||||||
|
Ident: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func logTls(chunk *tlsChunk, ip net.IP, port uint16) {
|
||||||
|
var flagsStr string
|
||||||
|
|
||||||
|
if chunk.isClient() {
|
||||||
|
flagsStr = "C"
|
||||||
|
} else {
|
||||||
|
flagsStr = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
if chunk.isRead() {
|
||||||
|
flagsStr += "R"
|
||||||
|
} else {
|
||||||
|
flagsStr += "W"
|
||||||
|
}
|
||||||
|
|
||||||
|
str := strings.ReplaceAll(strings.ReplaceAll(string(chunk.Data[0:chunk.Recorded]), "\n", " "), "\r", "")
|
||||||
|
|
||||||
|
logger.Log.Infof("PID: %v (tid: %v) (fd: %v) (client: %v) (addr: %v:%v) (recorded %v out of %v) - %v - %v",
|
||||||
|
chunk.Pid, chunk.Tgid, chunk.Fd, flagsStr, ip, port, chunk.Recorded, chunk.Len, str, hex.EncodeToString(chunk.Data[0:chunk.Recorded]))
|
||||||
|
}
|
||||||
143
tap/tlstapper/tls_process_discoverer.go
Normal file
143
tap/tlstapper/tls_process_discoverer.go
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var numberRegex = regexp.MustCompile("[0-9]+")
|
||||||
|
|
||||||
|
func UpdateTapTargets(tls *TlsTapper, pods *[]v1.Pod, procfs string) error {
|
||||||
|
containerIds := buildContainerIdsMap(pods)
|
||||||
|
containerPids, err := findContainerPids(procfs, containerIds)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pid := range containerPids {
|
||||||
|
if err := tls.AddPid(procfs, pid); err != nil {
|
||||||
|
LogError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findContainerPids(procfs string, containerIds map[string]bool) ([]uint32, error) {
|
||||||
|
result := make([]uint32, 0)
|
||||||
|
|
||||||
|
pids, err := ioutil.ReadDir(procfs)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Log.Infof("Starting tls auto discoverer %v %v - scanning %v potential pids",
|
||||||
|
procfs, containerIds, len(pids))
|
||||||
|
|
||||||
|
for _, pid := range pids {
|
||||||
|
if !pid.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !numberRegex.MatchString(pid.Name()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroup, err := getProcessCgroup(procfs, pid.Name())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := containerIds[cgroup]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pidNumber, err := strconv.Atoi(pid.Name())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, uint32(pidNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildContainerIdsMap(pods *[]v1.Pod) map[string]bool {
|
||||||
|
result := make(map[string]bool)
|
||||||
|
|
||||||
|
for _, pod := range *pods {
|
||||||
|
for _, container := range pod.Status.ContainerStatuses {
|
||||||
|
url, err := url.Parse(container.ContainerID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Warningf("Expecting URL like container ID %v", container.ContainerID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result[url.Host] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProcessCgroup(procfs string, pid string) (string, error) {
|
||||||
|
filePath := fmt.Sprintf("%s/%s/cgroup", procfs, pid)
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadFile(filePath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Warningf("Error reading cgroup file %s - %v", filePath, err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(bytes), "\n")
|
||||||
|
cgrouppath := extractCgroup(lines)
|
||||||
|
|
||||||
|
if cgrouppath == "" {
|
||||||
|
return "", errors.Errorf("Cgroup path not found for %s, %s", pid, lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeCgroup(cgrouppath), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractCgroup(lines []string) string {
|
||||||
|
if len(lines) == 1 {
|
||||||
|
parts := strings.Split(lines[0], ":")
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
} else {
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(line, ":pids:") {
|
||||||
|
parts := strings.Split(line, ":")
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeCgroup(cgrouppath string) string {
|
||||||
|
basename := strings.TrimSpace(path.Base(cgrouppath))
|
||||||
|
|
||||||
|
if strings.Contains(basename, ".") {
|
||||||
|
return strings.TrimSuffix(basename, filepath.Ext(basename))
|
||||||
|
} else {
|
||||||
|
return basename
|
||||||
|
}
|
||||||
|
}
|
||||||
41
tap/tlstapper/tls_reader.go
Normal file
41
tap/tlstapper/tls_reader.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tlsReader struct {
|
||||||
|
key string
|
||||||
|
chunks chan *tlsChunk
|
||||||
|
data []byte
|
||||||
|
doneHandler func(r *tlsReader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *tlsReader) Read(p []byte) (int, error) {
|
||||||
|
var chunk *tlsChunk
|
||||||
|
|
||||||
|
for len(r.data) == 0 {
|
||||||
|
var ok bool
|
||||||
|
select {
|
||||||
|
case chunk, ok = <-r.chunks:
|
||||||
|
if !ok {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
r.data = chunk.getRecordedData()
|
||||||
|
case <-time.After(time.Second * 3):
|
||||||
|
r.doneHandler(r)
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r.data) > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l := copy(p, r.data)
|
||||||
|
r.data = r.data[l:]
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
177
tap/tlstapper/tls_tapper.go
Normal file
177
tap/tlstapper/tls_tapper.go
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/perf"
|
||||||
|
"github.com/cilium/ebpf/rlimit"
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go tlsTapper bpf/tls_tapper.c -- -O2 -g -D__TARGET_ARCH_x86
|
||||||
|
|
||||||
|
type TlsTapper struct {
|
||||||
|
bpfObjects tlsTapperObjects
|
||||||
|
syscallHooks syscallHooks
|
||||||
|
sslHooksStructs []sslHooks
|
||||||
|
reader *perf.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) Init(bufferSize int) error {
|
||||||
|
logger.Log.Infof("Initializing tls tapper (bufferSize: %v)", bufferSize)
|
||||||
|
|
||||||
|
if err := setupRLimit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.bpfObjects = tlsTapperObjects{}
|
||||||
|
|
||||||
|
if err := loadTlsTapperObjects(&t.bpfObjects, nil); err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.syscallHooks = syscallHooks{}
|
||||||
|
|
||||||
|
if err := t.syscallHooks.installSyscallHooks(&t.bpfObjects); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.sslHooksStructs = make([]sslHooks, 0)
|
||||||
|
|
||||||
|
return t.initChunksReader(bufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) pollPerf(chunks chan<- *tlsChunk) {
|
||||||
|
logger.Log.Infof("Start polling for tls events")
|
||||||
|
|
||||||
|
for {
|
||||||
|
record, err := t.reader.Read()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
close(chunks)
|
||||||
|
|
||||||
|
if errors.Is(err, perf.ErrClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LogError(errors.Errorf("Error reading chunks from tls perf, aborting TLS! %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.LostSamples != 0 {
|
||||||
|
logger.Log.Infof("Buffer is full, dropped %d chunks", record.LostSamples)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.NewReader(record.RawSample)
|
||||||
|
|
||||||
|
var chunk tlsChunk
|
||||||
|
|
||||||
|
if err := binary.Read(buffer, binary.LittleEndian, &chunk); err != nil {
|
||||||
|
LogError(errors.Errorf("Error parsing chunk %v", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks <- &chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) GlobalTap(sslLibrary string) error {
|
||||||
|
return t.tapPid(0, sslLibrary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) AddPid(procfs string, pid uint32) error {
|
||||||
|
sslLibrary, err := findSsllib(procfs, pid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Infof("PID skipped no libssl.so found (pid: %d) %v", pid, err)
|
||||||
|
return nil // hide the error on purpose, its OK for a process to not use libssl.so
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.tapPid(pid, sslLibrary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) RemovePid(pid uint32) error {
|
||||||
|
logger.Log.Infof("Removing PID (pid: %v)", pid)
|
||||||
|
|
||||||
|
pids := t.bpfObjects.tlsTapperMaps.PidsMap
|
||||||
|
|
||||||
|
if err := pids.Delete(pid); err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) Close() []error {
|
||||||
|
errors := make([]error, 0)
|
||||||
|
|
||||||
|
if err := t.bpfObjects.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
errors = append(errors, t.syscallHooks.close()...)
|
||||||
|
|
||||||
|
for _, sslHooks := range t.sslHooksStructs {
|
||||||
|
errors = append(errors, sslHooks.close()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.reader.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRLimit() error {
|
||||||
|
err := rlimit.RemoveMemlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) initChunksReader(bufferSize int) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
t.reader, err = perf.NewReader(t.bpfObjects.ChunksBuffer, bufferSize)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) tapPid(pid uint32, sslLibrary string) error {
|
||||||
|
logger.Log.Infof("Tapping TLS (pid: %v) (sslLibrary: %v)", pid, sslLibrary)
|
||||||
|
|
||||||
|
newSsl := sslHooks{}
|
||||||
|
|
||||||
|
if err := newSsl.installUprobes(&t.bpfObjects, sslLibrary); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.sslHooksStructs = append(t.sslHooksStructs, newSsl)
|
||||||
|
|
||||||
|
pids := t.bpfObjects.tlsTapperMaps.PidsMap
|
||||||
|
|
||||||
|
if err := pids.Put(pid, uint32(1)); err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogError(err error) {
|
||||||
|
var e *errors.Error
|
||||||
|
if errors.As(err, &e) {
|
||||||
|
logger.Log.Errorf("Error: %v", e.ErrorStack())
|
||||||
|
} else {
|
||||||
|
logger.Log.Errorf("Error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
179
tap/tlstapper/tlstapper_bpfeb.go
Normal file
179
tap/tlstapper/tlstapper_bpfeb.go
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
// Code generated by bpf2go; DO NOT EDIT.
|
||||||
|
//go:build arm64be || armbe || mips || mips64 || mips64p32 || ppc64 || s390 || s390x || sparc || sparc64
|
||||||
|
// +build arm64be armbe mips mips64 mips64p32 ppc64 s390 s390x sparc sparc64
|
||||||
|
|
||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
// loadTlsTapper returns the embedded CollectionSpec for tlsTapper.
|
||||||
|
func loadTlsTapper() (*ebpf.CollectionSpec, error) {
|
||||||
|
reader := bytes.NewReader(_TlsTapperBytes)
|
||||||
|
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't load tlsTapper: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadTlsTapperObjects loads tlsTapper and converts it into a struct.
|
||||||
|
//
|
||||||
|
// The following types are suitable as obj argument:
|
||||||
|
//
|
||||||
|
// *tlsTapperObjects
|
||||||
|
// *tlsTapperPrograms
|
||||||
|
// *tlsTapperMaps
|
||||||
|
//
|
||||||
|
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||||
|
func loadTlsTapperObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||||
|
spec, err := loadTlsTapper()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.LoadAndAssign(obj, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperSpecs contains maps and programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperSpecs struct {
|
||||||
|
tlsTapperProgramSpecs
|
||||||
|
tlsTapperMapSpecs
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperSpecs contains programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperProgramSpecs struct {
|
||||||
|
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
||||||
|
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
||||||
|
SslRetRead *ebpf.ProgramSpec `ebpf:"ssl_ret_read"`
|
||||||
|
SslRetReadEx *ebpf.ProgramSpec `ebpf:"ssl_ret_read_ex"`
|
||||||
|
SslRetWrite *ebpf.ProgramSpec `ebpf:"ssl_ret_write"`
|
||||||
|
SslRetWriteEx *ebpf.ProgramSpec `ebpf:"ssl_ret_write_ex"`
|
||||||
|
SslWrite *ebpf.ProgramSpec `ebpf:"ssl_write"`
|
||||||
|
SslWriteEx *ebpf.ProgramSpec `ebpf:"ssl_write_ex"`
|
||||||
|
SysEnterAccept4 *ebpf.ProgramSpec `ebpf:"sys_enter_accept4"`
|
||||||
|
SysEnterConnect *ebpf.ProgramSpec `ebpf:"sys_enter_connect"`
|
||||||
|
SysEnterRead *ebpf.ProgramSpec `ebpf:"sys_enter_read"`
|
||||||
|
SysEnterWrite *ebpf.ProgramSpec `ebpf:"sys_enter_write"`
|
||||||
|
SysExitAccept4 *ebpf.ProgramSpec `ebpf:"sys_exit_accept4"`
|
||||||
|
SysExitConnect *ebpf.ProgramSpec `ebpf:"sys_exit_connect"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperMapSpecs contains maps before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperMapSpecs struct {
|
||||||
|
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||||
|
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||||
|
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||||
|
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||||
|
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||||
|
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||||
|
SslReadContext *ebpf.MapSpec `ebpf:"ssl_read_context"`
|
||||||
|
SslWriteContext *ebpf.MapSpec `ebpf:"ssl_write_context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperObjects struct {
|
||||||
|
tlsTapperPrograms
|
||||||
|
tlsTapperMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *tlsTapperObjects) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
&o.tlsTapperPrograms,
|
||||||
|
&o.tlsTapperMaps,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperMaps contains all maps after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperMaps struct {
|
||||||
|
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||||
|
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||||
|
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||||
|
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||||
|
Heap *ebpf.Map `ebpf:"heap"`
|
||||||
|
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||||
|
SslReadContext *ebpf.Map `ebpf:"ssl_read_context"`
|
||||||
|
SslWriteContext *ebpf.Map `ebpf:"ssl_write_context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *tlsTapperMaps) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
m.AcceptSyscallContext,
|
||||||
|
m.ChunksBuffer,
|
||||||
|
m.ConnectSyscallInfo,
|
||||||
|
m.FileDescriptorToIpv4,
|
||||||
|
m.Heap,
|
||||||
|
m.PidsMap,
|
||||||
|
m.SslReadContext,
|
||||||
|
m.SslWriteContext,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperPrograms contains all programs after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperPrograms struct {
|
||||||
|
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
||||||
|
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
||||||
|
SslRetRead *ebpf.Program `ebpf:"ssl_ret_read"`
|
||||||
|
SslRetReadEx *ebpf.Program `ebpf:"ssl_ret_read_ex"`
|
||||||
|
SslRetWrite *ebpf.Program `ebpf:"ssl_ret_write"`
|
||||||
|
SslRetWriteEx *ebpf.Program `ebpf:"ssl_ret_write_ex"`
|
||||||
|
SslWrite *ebpf.Program `ebpf:"ssl_write"`
|
||||||
|
SslWriteEx *ebpf.Program `ebpf:"ssl_write_ex"`
|
||||||
|
SysEnterAccept4 *ebpf.Program `ebpf:"sys_enter_accept4"`
|
||||||
|
SysEnterConnect *ebpf.Program `ebpf:"sys_enter_connect"`
|
||||||
|
SysEnterRead *ebpf.Program `ebpf:"sys_enter_read"`
|
||||||
|
SysEnterWrite *ebpf.Program `ebpf:"sys_enter_write"`
|
||||||
|
SysExitAccept4 *ebpf.Program `ebpf:"sys_exit_accept4"`
|
||||||
|
SysExitConnect *ebpf.Program `ebpf:"sys_exit_connect"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsTapperPrograms) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
p.SslRead,
|
||||||
|
p.SslReadEx,
|
||||||
|
p.SslRetRead,
|
||||||
|
p.SslRetReadEx,
|
||||||
|
p.SslRetWrite,
|
||||||
|
p.SslRetWriteEx,
|
||||||
|
p.SslWrite,
|
||||||
|
p.SslWriteEx,
|
||||||
|
p.SysEnterAccept4,
|
||||||
|
p.SysEnterConnect,
|
||||||
|
p.SysEnterRead,
|
||||||
|
p.SysEnterWrite,
|
||||||
|
p.SysExitAccept4,
|
||||||
|
p.SysExitConnect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _TlsTapperClose(closers ...io.Closer) error {
|
||||||
|
for _, closer := range closers {
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not access this directly.
|
||||||
|
//go:embed tlstapper_bpfeb.o
|
||||||
|
var _TlsTapperBytes []byte
|
||||||
BIN
tap/tlstapper/tlstapper_bpfeb.o
Normal file
BIN
tap/tlstapper/tlstapper_bpfeb.o
Normal file
Binary file not shown.
179
tap/tlstapper/tlstapper_bpfel.go
Normal file
179
tap/tlstapper/tlstapper_bpfel.go
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
// Code generated by bpf2go; DO NOT EDIT.
|
||||||
|
//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64
|
||||||
|
// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64
|
||||||
|
|
||||||
|
package tlstapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
// loadTlsTapper returns the embedded CollectionSpec for tlsTapper.
|
||||||
|
func loadTlsTapper() (*ebpf.CollectionSpec, error) {
|
||||||
|
reader := bytes.NewReader(_TlsTapperBytes)
|
||||||
|
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't load tlsTapper: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadTlsTapperObjects loads tlsTapper and converts it into a struct.
|
||||||
|
//
|
||||||
|
// The following types are suitable as obj argument:
|
||||||
|
//
|
||||||
|
// *tlsTapperObjects
|
||||||
|
// *tlsTapperPrograms
|
||||||
|
// *tlsTapperMaps
|
||||||
|
//
|
||||||
|
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||||
|
func loadTlsTapperObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||||
|
spec, err := loadTlsTapper()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.LoadAndAssign(obj, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperSpecs contains maps and programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperSpecs struct {
|
||||||
|
tlsTapperProgramSpecs
|
||||||
|
tlsTapperMapSpecs
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperSpecs contains programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperProgramSpecs struct {
|
||||||
|
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
||||||
|
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
||||||
|
SslRetRead *ebpf.ProgramSpec `ebpf:"ssl_ret_read"`
|
||||||
|
SslRetReadEx *ebpf.ProgramSpec `ebpf:"ssl_ret_read_ex"`
|
||||||
|
SslRetWrite *ebpf.ProgramSpec `ebpf:"ssl_ret_write"`
|
||||||
|
SslRetWriteEx *ebpf.ProgramSpec `ebpf:"ssl_ret_write_ex"`
|
||||||
|
SslWrite *ebpf.ProgramSpec `ebpf:"ssl_write"`
|
||||||
|
SslWriteEx *ebpf.ProgramSpec `ebpf:"ssl_write_ex"`
|
||||||
|
SysEnterAccept4 *ebpf.ProgramSpec `ebpf:"sys_enter_accept4"`
|
||||||
|
SysEnterConnect *ebpf.ProgramSpec `ebpf:"sys_enter_connect"`
|
||||||
|
SysEnterRead *ebpf.ProgramSpec `ebpf:"sys_enter_read"`
|
||||||
|
SysEnterWrite *ebpf.ProgramSpec `ebpf:"sys_enter_write"`
|
||||||
|
SysExitAccept4 *ebpf.ProgramSpec `ebpf:"sys_exit_accept4"`
|
||||||
|
SysExitConnect *ebpf.ProgramSpec `ebpf:"sys_exit_connect"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperMapSpecs contains maps before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type tlsTapperMapSpecs struct {
|
||||||
|
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||||
|
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||||
|
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||||
|
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||||
|
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||||
|
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||||
|
SslReadContext *ebpf.MapSpec `ebpf:"ssl_read_context"`
|
||||||
|
SslWriteContext *ebpf.MapSpec `ebpf:"ssl_write_context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperObjects struct {
|
||||||
|
tlsTapperPrograms
|
||||||
|
tlsTapperMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *tlsTapperObjects) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
&o.tlsTapperPrograms,
|
||||||
|
&o.tlsTapperMaps,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperMaps contains all maps after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperMaps struct {
|
||||||
|
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||||
|
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||||
|
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||||
|
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||||
|
Heap *ebpf.Map `ebpf:"heap"`
|
||||||
|
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||||
|
SslReadContext *ebpf.Map `ebpf:"ssl_read_context"`
|
||||||
|
SslWriteContext *ebpf.Map `ebpf:"ssl_write_context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *tlsTapperMaps) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
m.AcceptSyscallContext,
|
||||||
|
m.ChunksBuffer,
|
||||||
|
m.ConnectSyscallInfo,
|
||||||
|
m.FileDescriptorToIpv4,
|
||||||
|
m.Heap,
|
||||||
|
m.PidsMap,
|
||||||
|
m.SslReadContext,
|
||||||
|
m.SslWriteContext,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tlsTapperPrograms contains all programs after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type tlsTapperPrograms struct {
|
||||||
|
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
||||||
|
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
||||||
|
SslRetRead *ebpf.Program `ebpf:"ssl_ret_read"`
|
||||||
|
SslRetReadEx *ebpf.Program `ebpf:"ssl_ret_read_ex"`
|
||||||
|
SslRetWrite *ebpf.Program `ebpf:"ssl_ret_write"`
|
||||||
|
SslRetWriteEx *ebpf.Program `ebpf:"ssl_ret_write_ex"`
|
||||||
|
SslWrite *ebpf.Program `ebpf:"ssl_write"`
|
||||||
|
SslWriteEx *ebpf.Program `ebpf:"ssl_write_ex"`
|
||||||
|
SysEnterAccept4 *ebpf.Program `ebpf:"sys_enter_accept4"`
|
||||||
|
SysEnterConnect *ebpf.Program `ebpf:"sys_enter_connect"`
|
||||||
|
SysEnterRead *ebpf.Program `ebpf:"sys_enter_read"`
|
||||||
|
SysEnterWrite *ebpf.Program `ebpf:"sys_enter_write"`
|
||||||
|
SysExitAccept4 *ebpf.Program `ebpf:"sys_exit_accept4"`
|
||||||
|
SysExitConnect *ebpf.Program `ebpf:"sys_exit_connect"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *tlsTapperPrograms) Close() error {
|
||||||
|
return _TlsTapperClose(
|
||||||
|
p.SslRead,
|
||||||
|
p.SslReadEx,
|
||||||
|
p.SslRetRead,
|
||||||
|
p.SslRetReadEx,
|
||||||
|
p.SslRetWrite,
|
||||||
|
p.SslRetWriteEx,
|
||||||
|
p.SslWrite,
|
||||||
|
p.SslWriteEx,
|
||||||
|
p.SysEnterAccept4,
|
||||||
|
p.SysEnterConnect,
|
||||||
|
p.SysEnterRead,
|
||||||
|
p.SysEnterWrite,
|
||||||
|
p.SysExitAccept4,
|
||||||
|
p.SysExitConnect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _TlsTapperClose(closers ...io.Closer) error {
|
||||||
|
for _, closer := range closers {
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not access this directly.
|
||||||
|
//go:embed tlstapper_bpfel.o
|
||||||
|
var _TlsTapperBytes []byte
|
||||||
BIN
tap/tlstapper/tlstapper_bpfel.o
Normal file
BIN
tap/tlstapper/tlstapper_bpfel.o
Normal file
Binary file not shown.
@@ -122,6 +122,7 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus}) => {
|
|||||||
ws.current.onopen = () => {
|
ws.current.onopen = () => {
|
||||||
setWsConnection(WsConnectionStatus.Connected);
|
setWsConnection(WsConnectionStatus.Connected);
|
||||||
ws.current.send(query);
|
ws.current.send(query);
|
||||||
|
ws.current.send("");
|
||||||
}
|
}
|
||||||
ws.current.onclose = () => {
|
ws.current.onclose = () => {
|
||||||
setWsConnection(WsConnectionStatus.Closed);
|
setWsConnection(WsConnectionStatus.Closed);
|
||||||
|
|||||||
Reference in New Issue
Block a user