mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-07 20:20:55 +00:00
Compare commits
316 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a322fc58a | ||
|
|
53c3dabcbf | ||
|
|
6b6915c7ee | ||
|
|
e819759c2d | ||
|
|
b39c5dd5d3 | ||
|
|
0f402789f1 | ||
|
|
d4fade3599 | ||
|
|
054c4a9e8b | ||
|
|
35c1a88724 | ||
|
|
fe3f93c91b | ||
|
|
24aa4db0bc | ||
|
|
ef44257942 | ||
|
|
0b58558f70 | ||
|
|
cdd306b890 | ||
|
|
3cc9ff8616 | ||
|
|
247498492a | ||
|
|
867c7058a0 | ||
|
|
f1021f61b6 | ||
|
|
9162c4fb64 | ||
|
|
e7fc7b791a | ||
|
|
9914183d7d | ||
|
|
c0751ad4cb | ||
|
|
0aca81fbcb | ||
|
|
24dccab3e4 | ||
|
|
db607aff16 | ||
|
|
ec1728ef91 | ||
|
|
93de6e8934 | ||
|
|
5998d00e6a | ||
|
|
afafb2c625 | ||
|
|
b125860d06 | ||
|
|
68aabf262f | ||
|
|
d279b7272d | ||
|
|
d15e1cca54 | ||
|
|
d8761e1e31 | ||
|
|
a9d2cb5ac2 | ||
|
|
ddcf973e35 | ||
|
|
b6d1804326 | ||
|
|
6dc12af55b | ||
|
|
d78b0b987a | ||
|
|
9889787833 | ||
|
|
8fe0544175 | ||
|
|
09afa1983a | ||
|
|
669b5cb1f2 | ||
|
|
25e0949761 | ||
|
|
fa07f973c0 | ||
|
|
c38bdcd977 | ||
|
|
51a4165304 | ||
|
|
c8cd1f57c4 | ||
|
|
dfde87140a | ||
|
|
64b6368e63 | ||
|
|
6af2d11878 | ||
|
|
2b552b5847 | ||
|
|
72ec983b24 | ||
|
|
2f899a943c | ||
|
|
12f6b04a49 | ||
|
|
f010f349a1 | ||
|
|
26e23dc94f | ||
|
|
6785f024e4 | ||
|
|
92dab2e2f7 | ||
|
|
4da51c40b9 | ||
|
|
18d051af28 | ||
|
|
cef012d1f3 | ||
|
|
4802cca646 | ||
|
|
4117d008a9 | ||
|
|
91e3546196 | ||
|
|
4db2a80675 | ||
|
|
bfa3efd23a | ||
|
|
c48187a02e | ||
|
|
f6d7510a14 | ||
|
|
f9e0c36d5f | ||
|
|
a8dd332ff8 | ||
|
|
8e5df14f49 | ||
|
|
6307871584 | ||
|
|
7e77a76334 | ||
|
|
f2b7df7e02 | ||
|
|
b0af52ba9c | ||
|
|
ddc1dc3d71 | ||
|
|
d99bfea0db | ||
|
|
bed9d06c59 | ||
|
|
aaeb3ca1eb | ||
|
|
7df35e04a8 | ||
|
|
a5be1a8eaa | ||
|
|
8ba3e603a4 | ||
|
|
db51e6dbc2 | ||
|
|
77878e97f5 | ||
|
|
36767eda27 | ||
|
|
6c01078f97 | ||
|
|
6c06307d68 | ||
|
|
2223cad038 | ||
|
|
c1fc4447ef | ||
|
|
ea3eecfa04 | ||
|
|
51968f2aae | ||
|
|
15f7a3559a | ||
|
|
cc9627c884 | ||
|
|
d3f2cdbf0e | ||
|
|
28bfbf4186 | ||
|
|
d3c21a07bb | ||
|
|
510d5e5ed8 | ||
|
|
1070d17e20 | ||
|
|
6b8beb50ad | ||
|
|
68877b254b | ||
|
|
dd91087157 | ||
|
|
cf3ce0180b | ||
|
|
b4dc321829 | ||
|
|
7e893a5b52 | ||
|
|
33dabe8bbf | ||
|
|
ddf354f34e | ||
|
|
88f8998df3 | ||
|
|
fc0f6a8452 | ||
|
|
cc9dbbef2e | ||
|
|
696fed8345 | ||
|
|
c03de2222d | ||
|
|
a028211f0a | ||
|
|
c94a399bc3 | ||
|
|
788bcd4846 | ||
|
|
e2ef9eff05 | ||
|
|
7ce18ecaa9 | ||
|
|
7737bdf4fc | ||
|
|
bed59e12ea | ||
|
|
19723debb2 | ||
|
|
d82df9d670 | ||
|
|
d295cecfc2 | ||
|
|
9c291bbf47 | ||
|
|
cb0e89934d | ||
|
|
820fb64f8d | ||
|
|
62d4c3a86e | ||
|
|
2757b7419f | ||
|
|
3b5cd6c77b | ||
|
|
7e56d45c6b | ||
|
|
0e2bca9729 | ||
|
|
b1a40df069 | ||
|
|
773cf371f3 | ||
|
|
1527f43396 | ||
|
|
c9a2b9eb44 | ||
|
|
2b92bb74c7 | ||
|
|
fb08481909 | ||
|
|
e215870b9d | ||
|
|
426c6450ba | ||
|
|
a3383ee6cc | ||
|
|
bdff836040 | ||
|
|
9f8ecc8e4e | ||
|
|
9cdf1aa68b | ||
|
|
78481d4bcc | ||
|
|
706a2fc9b5 | ||
|
|
1064305934 | ||
|
|
9f1586ab50 | ||
|
|
6d79598c5d | ||
|
|
22bdbda718 | ||
|
|
23e2493890 | ||
|
|
a7905bc1ba | ||
|
|
4831b44dfa | ||
|
|
6817fd70ab | ||
|
|
3803bad6a4 | ||
|
|
d0b621070c | ||
|
|
6add6fb1ec | ||
|
|
e1106e25c4 | ||
|
|
48adf86b25 | ||
|
|
2ea5dc0df0 | ||
|
|
bb0172b151 | ||
|
|
ef7c80df05 | ||
|
|
5bd44b57f4 | ||
|
|
41dacbff1a | ||
|
|
d94ce4dce3 | ||
|
|
65ab0ca668 | ||
|
|
9bc3ea5ffc | ||
|
|
2d17d1a83d | ||
|
|
78c89cc5b4 | ||
|
|
b5c9a31380 | ||
|
|
3dfff2b7a5 | ||
|
|
583a5b97ee | ||
|
|
64aae06fe5 | ||
|
|
1ccaa03fb2 | ||
|
|
3222212367 | ||
|
|
c5681871e4 | ||
|
|
1ac3ba0a6d | ||
|
|
d3520765eb | ||
|
|
fa1e7bcf01 | ||
|
|
bf182b6330 | ||
|
|
f59f84af02 | ||
|
|
cae5a92a13 | ||
|
|
7afb1d8b9b | ||
|
|
f628192216 | ||
|
|
b1feb4e33f | ||
|
|
94dff24aed | ||
|
|
d00d2eafa7 | ||
|
|
63eb39b451 | ||
|
|
149a8b7efe | ||
|
|
247fbc1291 | ||
|
|
0e74238e56 | ||
|
|
05ecef557f | ||
|
|
63325ec890 | ||
|
|
579cb47ecf | ||
|
|
7ed4088b4b | ||
|
|
f95db49317 | ||
|
|
749b19512e | ||
|
|
746eff1e23 | ||
|
|
b7a8d9a41a | ||
|
|
995fb96f24 | ||
|
|
5d4557d1dd | ||
|
|
78c1c02fe6 | ||
|
|
742a56272b | ||
|
|
b7b3603e57 | ||
|
|
54c5da2fcb | ||
|
|
a5efb6b625 | ||
|
|
7dcb2d23a0 | ||
|
|
f4ff4d4dd6 | ||
|
|
dd5761f112 | ||
|
|
854836056d | ||
|
|
090368295c | ||
|
|
67038e324b | ||
|
|
a5fb7e0474 | ||
|
|
1a0625d37c | ||
|
|
7ec1f595a1 | ||
|
|
3998485944 | ||
|
|
e5de984acd | ||
|
|
18d6345e80 | ||
|
|
661e17ace9 | ||
|
|
cc78b291af | ||
|
|
7c8adee7a8 | ||
|
|
461ad1921e | ||
|
|
5ca90d70ff | ||
|
|
65bda4e844 | ||
|
|
c533bcd38c | ||
|
|
1d17f83931 | ||
|
|
b9c3704bae | ||
|
|
08602c75e0 | ||
|
|
46799f6665 | ||
|
|
250a878407 | ||
|
|
b32f5f9e12 | ||
|
|
5325f94f2b | ||
|
|
fc3bf69348 | ||
|
|
7f41c348e6 | ||
|
|
eb69ebf008 | ||
|
|
9f889a7a36 | ||
|
|
909cc8de15 | ||
|
|
a0313e9e5a | ||
|
|
3aed354ab8 | ||
|
|
7fe9ecbca4 | ||
|
|
9e6af8c0bc | ||
|
|
2c8f2e903f | ||
|
|
ca451e08f6 | ||
|
|
45bfebc956 | ||
|
|
acaa29f8eb | ||
|
|
470ab3d7ed | ||
|
|
a259361a96 | ||
|
|
0350bcdd61 | ||
|
|
cddc7d25fd | ||
|
|
635a9d3256 | ||
|
|
2224d0e9f4 | ||
|
|
db01c4e9e3 | ||
|
|
0659d0fead | ||
|
|
988bb16260 | ||
|
|
b4e8573634 | ||
|
|
cfa12ea45e | ||
|
|
9a7c23f070 | ||
|
|
0f1f832ddd | ||
|
|
dfe5605032 | ||
|
|
4c2884c40f | ||
|
|
4fb179f623 | ||
|
|
796fc1453c | ||
|
|
0ef3e2d018 | ||
|
|
77a14410f4 | ||
|
|
f269a61842 | ||
|
|
51eddd3ae4 | ||
|
|
64b22daa2a | ||
|
|
3a2d34647e | ||
|
|
d8ee89225c | ||
|
|
f7ce141d0d | ||
|
|
3c25cec633 | ||
|
|
7b86d32174 | ||
|
|
aeda619104 | ||
|
|
98738cb5a6 | ||
|
|
bf3285cb8b | ||
|
|
5f9084e497 | ||
|
|
f2a384c8db | ||
|
|
207d89fa17 | ||
|
|
3b758d15a0 | ||
|
|
261e850a59 | ||
|
|
242a276c5f | ||
|
|
b9f9e860b6 | ||
|
|
1404c68a22 | ||
|
|
400c681369 | ||
|
|
a4761e3262 | ||
|
|
313d26670b | ||
|
|
16f1e116c0 | ||
|
|
2d625eccaa | ||
|
|
19443501da | ||
|
|
4ef91a2701 | ||
|
|
bc031be0fe | ||
|
|
f32a7d97ec | ||
|
|
aeda024986 | ||
|
|
98198b9733 | ||
|
|
0bf7c83b86 | ||
|
|
a8df589076 | ||
|
|
c07f1851b3 | ||
|
|
5c4c913a27 | ||
|
|
71111248bd | ||
|
|
5efb48f0c5 | ||
|
|
cc980dbaf8 | ||
|
|
1afe27e969 | ||
|
|
8df5e015c5 | ||
|
|
6b898077f1 | ||
|
|
e93cd978e8 | ||
|
|
bada6dae68 | ||
|
|
8814e08871 | ||
|
|
6b7a94a850 | ||
|
|
7b004e7a1f | ||
|
|
836b87d517 | ||
|
|
646da4810d | ||
|
|
a6d349a8fa | ||
|
|
9d58c662a8 | ||
|
|
e4a09be4e2 | ||
|
|
7208ed85d3 | ||
|
|
7a5bf83336 | ||
|
|
87b8a067c9 | ||
|
|
3fe765e072 |
@@ -1,16 +0,0 @@
|
||||
# Files
|
||||
.dockerignore
|
||||
.editorconfig
|
||||
.gitignore
|
||||
Dockerfile
|
||||
Makefile
|
||||
LICENSE
|
||||
**/*.md
|
||||
**/*_test.go
|
||||
*.out
|
||||
|
||||
# Folders
|
||||
.git/
|
||||
.github/
|
||||
build/
|
||||
**/node_modules/
|
||||
46
.github/static/kubeshark.rb.tmpl
vendored
Normal file
46
.github/static/kubeshark.rb.tmpl
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Kubeshark < Formula
|
||||
desc ""
|
||||
homepage "https://github.com/kubeshark/kubeshark"
|
||||
version "${CLEAN_VERSION}"
|
||||
|
||||
on_macos do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/kubeshark/kubeshark/releases/download/${FULL_VERSION}/kubeshark_darwin_arm64"
|
||||
sha256 "${DARWIN_ARM64_SHA256}"
|
||||
|
||||
def install
|
||||
bin.install "kubeshark_darwin_arm64" => "kubeshark"
|
||||
end
|
||||
end
|
||||
if Hardware::CPU.intel?
|
||||
url "https://github.com/kubeshark/kubeshark/releases/download/${FULL_VERSION}/kubeshark_darwin_amd64"
|
||||
sha256 "${DARWIN_AMD64_SHA256}"
|
||||
|
||||
def install
|
||||
bin.install "kubeshark_darwin_amd64" => "kubeshark"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on_linux do
|
||||
if Hardware::CPU.intel?
|
||||
url "https://github.com/kubeshark/kubeshark/releases/download/${FULL_VERSION}/kubeshark_linux_amd64"
|
||||
sha256 "${LINUX_AMD64_SHA256}"
|
||||
|
||||
def install
|
||||
bin.install "kubeshark_linux_amd64" => "kubeshark"
|
||||
end
|
||||
end
|
||||
if Hardware::CPU.arm? && Hardware::CPU.is_64_bit?
|
||||
url "https://github.com/kubeshark/kubeshark/releases/download/${FULL_VERSION}/kubeshark_linux_arm64"
|
||||
sha256 "${LINUX_ARM64_SHA256}"
|
||||
|
||||
def install
|
||||
bin.install "kubeshark_linux_arm64" => "kubeshark"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
3
.github/workflows/helm.yml
vendored
3
.github/workflows/helm.yml
vendored
@@ -1,7 +1,8 @@
|
||||
on:
|
||||
push:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- '*'
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
name: Release Helm Charts
|
||||
|
||||
|
||||
50
.github/workflows/release.yml
vendored
50
.github/workflows/release.yml
vendored
@@ -1,7 +1,8 @@
|
||||
on:
|
||||
push:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- '*'
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
name: Release
|
||||
|
||||
@@ -13,6 +14,8 @@ jobs:
|
||||
release:
|
||||
name: Build and publish a new release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.tag }}
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
@@ -46,44 +49,19 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: "bin/*"
|
||||
tag: ${{ steps.version.outputs.tag }}
|
||||
prerelease: true
|
||||
prerelease: false
|
||||
bodyFile: 'bin/README.md'
|
||||
|
||||
brew-tap:
|
||||
name: Create Homebrew formulae
|
||||
runs-on: ubuntu-latest
|
||||
brew:
|
||||
name: Publish a new Homebrew formulae
|
||||
needs: [release]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Bump core homebrew formula
|
||||
uses: mislav/bump-homebrew-formula-action@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Version
|
||||
id: version
|
||||
shell: bash
|
||||
run: |
|
||||
{
|
||||
echo "tag=${GITHUB_REF#refs/*/}"
|
||||
echo "build_timestamp=$(date +%s)"
|
||||
echo "branch=${GITHUB_REF#refs/heads/}"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Fetch all tags
|
||||
run: git fetch --force --tags
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: ${{ env.GITHUB_REF_NAME }}
|
||||
args: release --clean
|
||||
# A PR will be sent to github.com/Homebrew/homebrew-core to update this formula:
|
||||
formula-name: kubeshark
|
||||
push-to: kubeshark/homebrew-core
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.HOMEBREW_TOKEN }}
|
||||
VER: ${{ steps.version.outputs.tag }}
|
||||
BUILD_TIMESTAMP: ${{ steps.version.outputs.build_timestamp }}
|
||||
COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }}
|
||||
|
||||
115
Makefile
115
Makefile
@@ -9,7 +9,7 @@ COMMIT_HASH=$(shell git rev-parse HEAD)
|
||||
GIT_BRANCH=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
|
||||
GIT_VERSION=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
|
||||
BUILD_TIMESTAMP=$(shell date +%s)
|
||||
export VER?=0.0
|
||||
export VER?=0.0.0
|
||||
|
||||
help: ## Print this help message.
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
@@ -40,6 +40,21 @@ build-base: ## Build binary (select the platform via GOOS / GOARCH env variables
|
||||
-o bin/kubeshark_$(SUFFIX) kubeshark.go && \
|
||||
cd bin && shasum -a 256 kubeshark_${SUFFIX} > kubeshark_${SUFFIX}.sha256
|
||||
|
||||
build-brew: ## Build binary for brew/core CI
|
||||
go build ${GCLFAGS} -ldflags="${LDFLAGS_EXT} \
|
||||
-X 'github.com/kubeshark/kubeshark/misc.GitCommitHash=$(COMMIT_HASH)' \
|
||||
-X 'github.com/kubeshark/kubeshark/misc.Branch=$(GIT_BRANCH)' \
|
||||
-X 'github.com/kubeshark/kubeshark/misc.BuildTimestamp=$(BUILD_TIMESTAMP)' \
|
||||
-X 'github.com/kubeshark/kubeshark/misc.Platform=$(SUFFIX)' \
|
||||
-X 'github.com/kubeshark/kubeshark/misc.Ver=$(VER)'" \
|
||||
-o kubeshark kubeshark.go
|
||||
|
||||
build-windows-amd64:
|
||||
$(MAKE) build GOOS=windows GOARCH=amd64 && \
|
||||
mv ./bin/kubeshark_windows_amd64 ./bin/kubeshark.exe && \
|
||||
rm bin/kubeshark_windows_amd64.sha256 && \
|
||||
cd bin && shasum -a 256 kubeshark.exe > kubeshark.exe.sha256
|
||||
|
||||
build-all: ## Build for all supported platforms.
|
||||
export CGO_ENABLED=0
|
||||
echo "Compiling for every OS and Platform" && \
|
||||
@@ -48,8 +63,7 @@ build-all: ## Build for all supported platforms.
|
||||
$(MAKE) build GOOS=linux GOARCH=arm64 && \
|
||||
$(MAKE) build GOOS=darwin GOARCH=amd64 && \
|
||||
$(MAKE) build GOOS=darwin GOARCH=arm64 && \
|
||||
$(MAKE) build GOOS=windows GOARCH=amd64 && \
|
||||
mv ./bin/kubeshark_windows_amd64 ./bin/kubeshark.exe && \
|
||||
$(MAKE) build-windows-amd64 && \
|
||||
echo "---------" && \
|
||||
find ./bin -ls
|
||||
|
||||
@@ -68,3 +82,98 @@ kubectl-view-all-resources: ## This command outputs all Kubernetes resources usi
|
||||
|
||||
kubectl-view-kubeshark-resources: ## This command outputs all Kubernetes resources in "kubeshark" namespace using YAML format and pipes it to VS Code
|
||||
./kubectl.sh view-kubeshark-resources
|
||||
|
||||
generate-helm-values: ## Generate the Helm values from config.yaml
|
||||
./bin/kubeshark__ config > ./helm-chart/values.yaml && sed -i 's/^license:.*/license: ""/' helm-chart/values.yaml
|
||||
|
||||
generate-manifests: ## Generate the manifests from the Helm chart using default configuration
|
||||
helm template kubeshark -n default ./helm-chart > ./manifests/complete.yaml
|
||||
|
||||
logs-worker:
|
||||
export LOGS_POD_PREFIX=kubeshark-worker-
|
||||
export LOGS_FOLLOW=
|
||||
${MAKE} logs
|
||||
|
||||
logs-worker-follow:
|
||||
export LOGS_POD_PREFIX=kubeshark-worker-
|
||||
export LOGS_FOLLOW=--follow
|
||||
${MAKE} logs
|
||||
|
||||
logs-hub:
|
||||
export LOGS_POD_PREFIX=kubeshark-hub
|
||||
export LOGS_FOLLOW=
|
||||
${MAKE} logs
|
||||
|
||||
logs-hub-follow:
|
||||
export LOGS_POD_PREFIX=kubeshark-hub
|
||||
export LOGS_FOLLOW=--follow
|
||||
${MAKE} logs
|
||||
|
||||
logs-front:
|
||||
export LOGS_POD_PREFIX=kubeshark-front
|
||||
export LOGS_FOLLOW=
|
||||
${MAKE} logs
|
||||
|
||||
logs-front-follow:
|
||||
export LOGS_POD_PREFIX=kubeshark-front
|
||||
export LOGS_FOLLOW=--follow
|
||||
${MAKE} logs
|
||||
|
||||
logs:
|
||||
kubectl logs $$(kubectl get pods | awk '$$1 ~ /^$(LOGS_POD_PREFIX)/' | awk 'END {print $$1}') $(LOGS_FOLLOW)
|
||||
|
||||
ssh-node:
|
||||
kubectl ssh node $$(kubectl get nodes | awk 'END {print $$1}')
|
||||
|
||||
exec-worker:
|
||||
export EXEC_POD_PREFIX=kubeshark-worker-
|
||||
${MAKE} exec
|
||||
|
||||
exec-hub:
|
||||
export EXEC_POD_PREFIX=kubeshark-hub
|
||||
${MAKE} exec
|
||||
|
||||
exec-front:
|
||||
export EXEC_POD_PREFIX=kubeshark-front
|
||||
${MAKE} exec
|
||||
|
||||
exec:
|
||||
kubectl exec --stdin --tty $$(kubectl get pods | awk '$$1 ~ /^$(EXEC_POD_PREFIX)/' | awk 'END {print $$1}') -- /bin/sh
|
||||
|
||||
helm-install:
|
||||
cd helm-chart && helm install kubeshark . && cd ..
|
||||
|
||||
helm-install-canary:
|
||||
cd helm-chart && helm install kubeshark . --set tap.docker.tag=canary && cd ..
|
||||
|
||||
helm-install-dev:
|
||||
cd helm-chart && helm install kubeshark . --set tap.docker.tag=dev && cd ..
|
||||
|
||||
helm-install-debug:
|
||||
cd helm-chart && helm install kubeshark . --set tap.debug=true && cd ..
|
||||
|
||||
helm-install-debug-canary:
|
||||
cd helm-chart && helm install kubeshark . --set tap.debug=true --set tap.docker.tag=canary && cd ..
|
||||
|
||||
helm-install-debug-dev:
|
||||
cd helm-chart && helm install kubeshark . --set tap.debug=true --set tap.docker.tag=dev && cd ..
|
||||
|
||||
helm-uninstall:
|
||||
helm uninstall kubeshark
|
||||
|
||||
proxy:
|
||||
kubeshark proxy
|
||||
|
||||
port-forward-worker:
|
||||
kubectl port-forward $$(kubectl get pods | awk '$$1 ~ /^$(LOGS_POD_PREFIX)/' | awk 'END {print $$1}') $(LOGS_FOLLOW) 30001:30001
|
||||
|
||||
release:
|
||||
@cd ../worker && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
|
||||
@cd ../hub && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
|
||||
@cd ../front && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
|
||||
@cd ../kubeshark && sed -i 's/^version:.*/version: "$(VERSION)"/' helm-chart/Chart.yaml && make && make generate-helm-values && make generate-manifests
|
||||
@git add -A . && git commit -m ":bookmark: Bump the Helm chart version to $(VERSION)" && git push
|
||||
@git tag v$(VERSION) && git push origin --tags
|
||||
@cd helm-chart && cp -r . ../../kubeshark.github.io/charts/chart
|
||||
@cd ../../kubeshark.github.io/ && git add -A . && git commit -m ":sparkles: Update the Helm chart" && git push
|
||||
@cd ../kubeshark
|
||||
|
||||
27
README.md
27
README.md
@@ -3,14 +3,11 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/kubeshark/kubeshark/blob/main/LICENSE">
|
||||
<img alt="GitHub License" src="https://img.shields.io/github/license/kubeshark/kubeshark?logo=GitHub&style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/kubeshark/kubeshark/releases/latest">
|
||||
<img alt="GitHub Latest Release" src="https://img.shields.io/github/v/release/kubeshark/kubeshark?logo=GitHub&style=flat-square">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/r/kubeshark/worker">
|
||||
<img alt="Docker pulls" src="https://img.shields.io/docker/pulls/kubeshark/kubeshark?color=%23099cec&logo=Docker&style=flat-square">
|
||||
<img alt="Docker pulls" src="https://img.shields.io/docker/pulls/kubeshark/worker?color=%23099cec&logo=Docker&style=flat-square">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/r/kubeshark/worker">
|
||||
<img alt="Image size" src="https://img.shields.io/docker/image-size/kubeshark/kubeshark/latest?logo=Docker&style=flat-square">
|
||||
@@ -25,9 +22,8 @@
|
||||
|
||||
<p align="center">
|
||||
<b>
|
||||
<span>NEW: </span><a href="https://github.com/kubeshark/kubeshark/releases/tag/39.4">Version 39.4</a> is out, introducing
|
||||
<a href="https://docs.kubeshark.co/en/automation_scripting">Scripting</a>,
|
||||
<a href="https://docs.kubeshark.co/en/automation_hooks">L4/L7 hooks</a>, and so much more...
|
||||
Want to see Kubeshark in action, right now? Visit this
|
||||
<a href="https://demo.kubeshark.co/">live demo deploymenet</a> of Kubeshark.
|
||||
</b>
|
||||
</p>
|
||||
|
||||
@@ -53,18 +49,21 @@ Running any of the :point_up: above commands will open the [Web UI](https://docs
|
||||
|
||||
### Homebrew
|
||||
|
||||
[Homebrew](https://brew.sh/) :beer: users can add Kubeshark formulae with:
|
||||
|
||||
```shell
|
||||
brew tap kubeshark/kubeshark
|
||||
```
|
||||
|
||||
and install Kubeshark CLI with:
|
||||
[Homebrew](https://brew.sh/) :beer: users install Kubeshark CLI with:
|
||||
|
||||
```shell
|
||||
brew install kubeshark
|
||||
```
|
||||
|
||||
### Helm
|
||||
|
||||
Add the helm repository and install the chart:
|
||||
|
||||
```shell
|
||||
helm repo add kubeshark https://helm.kubeshark.co
|
||||
helm install kubeshark kubeshark/kubeshark
|
||||
```
|
||||
|
||||
## Building From Source
|
||||
|
||||
Clone this repository and run `make` command to build it. After the build is complete, the executable can be found at `./bin/kubeshark__`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Kubeshark release _VER_
|
||||
Kubeshark CHANGELOG is now part of [Kubeshark wiki](https://github.com/kubeshark/kubeshark/wiki/CHANGELOG)
|
||||
Release notes coming soon ..
|
||||
|
||||
## Download Kubeshark for your platform
|
||||
|
||||
|
||||
21
cmd/check.go
21
cmd/check.go
@@ -1,21 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var checkCmd = &cobra.Command{
|
||||
Use: "check",
|
||||
Short: fmt.Sprintf("Check the %s resources for potential problems", misc.Software),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runCheck()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(checkCmd)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/semver"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func KubernetesApi() (*kubernetes.Provider, *semver.SemVersion, bool) {
|
||||
log.Info().Str("procedure", "kubernetes-api").Msg("Checking:")
|
||||
|
||||
kubernetesProvider, err := kubernetes.NewProvider(config.Config.KubeConfigPath(), config.Config.Kube.Context)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Can't initialize the client!")
|
||||
return nil, nil, false
|
||||
}
|
||||
log.Info().Msg("Initialization of the client is passed.")
|
||||
|
||||
kubernetesVersion, err := kubernetesProvider.GetKubernetesVersion()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Can't query the Kubernetes API!")
|
||||
return nil, nil, false
|
||||
}
|
||||
log.Info().Msg("Querying the Kubernetes API is passed.")
|
||||
|
||||
return kubernetesProvider, kubernetesVersion, true
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/rs/zerolog/log"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
)
|
||||
|
||||
func KubernetesPermissions(ctx context.Context, kubernetesProvider *kubernetes.Provider) bool {
|
||||
log.Info().Str("procedure", "kubernetes-permissions").Msg("Checking:")
|
||||
return checkRulesPermissions(ctx, kubernetesProvider, kubernetesProvider.BuildClusterRole().Rules, "")
|
||||
}
|
||||
|
||||
func checkRulesPermissions(ctx context.Context, kubernetesProvider *kubernetes.Provider, rules []rbac.PolicyRule, namespace string) bool {
|
||||
permissionsExist := true
|
||||
|
||||
for _, rule := range rules {
|
||||
for _, group := range rule.APIGroups {
|
||||
for _, resource := range rule.Resources {
|
||||
for _, verb := range rule.Verbs {
|
||||
exist, err := kubernetesProvider.CanI(ctx, namespace, resource, verb, group)
|
||||
permissionsExist = checkPermissionExist(group, resource, verb, namespace, exist, err) && permissionsExist
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return permissionsExist
|
||||
}
|
||||
|
||||
func checkPermissionExist(group string, resource string, verb string, namespace string, exist bool, err error) bool {
|
||||
var groupAndNamespace string
|
||||
if group != "" && namespace != "" {
|
||||
groupAndNamespace = fmt.Sprintf("in api group '%v' and namespace '%v'", group, namespace)
|
||||
} else if group != "" {
|
||||
groupAndNamespace = fmt.Sprintf("in api group '%v'", group)
|
||||
} else if namespace != "" {
|
||||
groupAndNamespace = fmt.Sprintf("in namespace '%v'", namespace)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Str("verb", verb).
|
||||
Str("resource", resource).
|
||||
Str("group-and-namespace", groupAndNamespace).
|
||||
Err(err).
|
||||
Msg("While checking Kubernetes permissions!")
|
||||
return false
|
||||
} else if !exist {
|
||||
log.Error().Msg(fmt.Sprintf("Can't %v %v %v", verb, resource, groupAndNamespace))
|
||||
return false
|
||||
}
|
||||
|
||||
log.Info().Msg(fmt.Sprintf("Can %v %v %v", verb, resource, groupAndNamespace))
|
||||
return true
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func KubernetesResources(ctx context.Context, kubernetesProvider *kubernetes.Provider) bool {
|
||||
log.Info().Str("procedure", "k8s-components").Msg("Checking:")
|
||||
|
||||
exist, err := kubernetesProvider.DoesNamespaceExist(ctx, config.Config.Tap.SelfNamespace)
|
||||
allResourcesExist := checkResourceExist(config.Config.Tap.SelfNamespace, "namespace", exist, err)
|
||||
|
||||
exist, err = kubernetesProvider.DoesServiceAccountExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.ServiceAccountName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.ServiceAccountName, "service account", exist, err) && allResourcesExist
|
||||
|
||||
if config.Config.IsNsRestrictedMode() {
|
||||
exist, err = kubernetesProvider.DoesRoleExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.RoleName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.RoleName, "role", exist, err) && allResourcesExist
|
||||
|
||||
exist, err = kubernetesProvider.DoesRoleBindingExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.RoleBindingName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.RoleBindingName, "role binding", exist, err) && allResourcesExist
|
||||
} else {
|
||||
exist, err = kubernetesProvider.DoesClusterRoleExist(ctx, kubernetes.ClusterRoleName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.ClusterRoleName, "cluster role", exist, err) && allResourcesExist
|
||||
|
||||
exist, err = kubernetesProvider.DoesClusterRoleBindingExist(ctx, kubernetes.ClusterRoleBindingName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.ClusterRoleBindingName, "cluster role binding", exist, err) && allResourcesExist
|
||||
}
|
||||
|
||||
exist, err = kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.HubServiceName)
|
||||
allResourcesExist = checkResourceExist(kubernetes.HubServiceName, "service", exist, err) && allResourcesExist
|
||||
|
||||
allResourcesExist = checkPodResourcesExist(ctx, kubernetesProvider) && allResourcesExist
|
||||
|
||||
return allResourcesExist
|
||||
}
|
||||
|
||||
func checkPodResourcesExist(ctx context.Context, kubernetesProvider *kubernetes.Provider) bool {
|
||||
if pods, err := kubernetesProvider.ListPodsByAppLabel(ctx, config.Config.Tap.SelfNamespace, kubernetes.HubPodName); err != nil {
|
||||
log.Error().
|
||||
Str("name", kubernetes.HubPodName).
|
||||
Err(err).
|
||||
Msg("While checking if pod is running!")
|
||||
return false
|
||||
} else if len(pods) == 0 {
|
||||
log.Error().
|
||||
Str("name", kubernetes.HubPodName).
|
||||
Msg("Pod doesn't exist!")
|
||||
return false
|
||||
} else if !kubernetes.IsPodRunning(&pods[0]) {
|
||||
log.Error().
|
||||
Str("name", kubernetes.HubPodName).
|
||||
Msg("Pod is not running!")
|
||||
return false
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("name", kubernetes.HubPodName).
|
||||
Msg("Pod is running.")
|
||||
|
||||
if pods, err := kubernetesProvider.ListPodsByAppLabel(ctx, config.Config.Tap.SelfNamespace, kubernetes.WorkerPodName); err != nil {
|
||||
log.Error().
|
||||
Str("name", kubernetes.WorkerPodName).
|
||||
Err(err).
|
||||
Msg("While checking if pods are running!")
|
||||
return false
|
||||
} else {
|
||||
workers := 0
|
||||
notRunningWorkers := 0
|
||||
|
||||
for _, pod := range pods {
|
||||
workers += 1
|
||||
if !kubernetes.IsPodRunning(&pod) {
|
||||
notRunningWorkers += 1
|
||||
}
|
||||
}
|
||||
|
||||
if notRunningWorkers > 0 {
|
||||
log.Error().
|
||||
Str("name", kubernetes.WorkerPodName).
|
||||
Msg(fmt.Sprintf("%d/%d pods are not running!", notRunningWorkers, workers))
|
||||
return false
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("name", kubernetes.WorkerPodName).
|
||||
Msg(fmt.Sprintf("All %d pods are running.", workers))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func checkResourceExist(resourceName string, resourceType string, exist bool, err error) bool {
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Str("name", resourceName).
|
||||
Str("type", resourceType).
|
||||
Err(err).
|
||||
Msg("Checking if resource exists!")
|
||||
return false
|
||||
} else if !exist {
|
||||
log.Error().
|
||||
Str("name", resourceName).
|
||||
Str("type", resourceType).
|
||||
Msg("Resource doesn't exist!")
|
||||
return false
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("name", resourceName).
|
||||
Str("type", resourceType).
|
||||
Msg("Resource exist.")
|
||||
return true
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/semver"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func KubernetesVersion(kubernetesVersion *semver.SemVersion) bool {
|
||||
log.Info().Str("procedure", "kubernetes-version").Msg("Checking:")
|
||||
|
||||
if err := kubernetes.ValidateKubernetesVersion(kubernetesVersion); err != nil {
|
||||
log.Error().Str("k8s-version", string(*kubernetesVersion)).Err(err).Msg(fmt.Sprintf(utils.Red, "The cluster does not have the minimum required Kubernetes API version!"))
|
||||
return false
|
||||
}
|
||||
|
||||
log.Info().Str("k8s-version", string(*kubernetesVersion)).Msg("Minimum required Kubernetes API version is passed.")
|
||||
return true
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/internal/connect"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func ServerConnection(kubernetesProvider *kubernetes.Provider) bool {
|
||||
log.Info().Str("procedure", "server-connectivity").Msg("Checking:")
|
||||
|
||||
var connectedToHub, connectedToFront bool
|
||||
|
||||
if err := checkProxy(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port), "/echo", kubernetesProvider); err != nil {
|
||||
log.Error().Err(err).Msg("Couldn't connect to Hub using proxy!")
|
||||
} else {
|
||||
connectedToHub = true
|
||||
log.Info().Msg("Connected successfully to Hub using proxy.")
|
||||
}
|
||||
|
||||
if err := checkProxy(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Front.Port), "", kubernetesProvider); err != nil {
|
||||
log.Error().Err(err).Msg("Couldn't connect to Front using proxy!")
|
||||
} else {
|
||||
connectedToFront = true
|
||||
log.Info().Msg("Connected successfully to Front using proxy.")
|
||||
}
|
||||
|
||||
return connectedToHub && connectedToFront
|
||||
}
|
||||
|
||||
func checkProxy(serverUrl string, path string, kubernetesProvider *kubernetes.Provider) error {
|
||||
log.Info().Str("url", serverUrl).Msg("Connecting:")
|
||||
connector := connect.NewConnector(serverUrl, connect.DefaultRetries, connect.DefaultTimeout)
|
||||
if err := connector.TestConnection(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/kubeshark/kubeshark/cmd/check"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func runCheck() {
|
||||
log.Info().Msg(fmt.Sprintf("Checking the %s resources...", misc.Software))
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel() // cancel will be called when this function exits
|
||||
|
||||
kubernetesProvider, kubernetesVersion, checkPassed := check.KubernetesApi()
|
||||
|
||||
if checkPassed {
|
||||
checkPassed = check.KubernetesVersion(kubernetesVersion)
|
||||
}
|
||||
|
||||
if checkPassed {
|
||||
checkPassed = check.KubernetesPermissions(ctx, kubernetesProvider)
|
||||
}
|
||||
|
||||
if checkPassed {
|
||||
checkPassed = check.KubernetesResources(ctx, kubernetesProvider)
|
||||
}
|
||||
|
||||
if checkPassed {
|
||||
checkPassed = check.ServerConnection(kubernetesProvider)
|
||||
}
|
||||
|
||||
if checkPassed {
|
||||
log.Info().Msg(fmt.Sprintf(utils.Green, "All checks are passed."))
|
||||
} else {
|
||||
log.Error().
|
||||
Str("command1", fmt.Sprintf("%s %s", misc.Program, cleanCmd.Use)).
|
||||
Str("command2", fmt.Sprintf("%s %s", misc.Program, tapCmd.Use)).
|
||||
Msg(fmt.Sprintf(utils.Red, fmt.Sprintf("There are issues in your %s resources! Run these commands:", misc.Software)))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
15
cmd/clean.go
15
cmd/clean.go
@@ -4,7 +4,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/kubernetes/helm"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -14,7 +16,16 @@ var cleanCmd = &cobra.Command{
|
||||
Use: "clean",
|
||||
Short: fmt.Sprintf("Removes all %s resources", misc.Software),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
performCleanCommand()
|
||||
resp, err := helm.NewHelm(
|
||||
config.Config.Tap.Release.Repo,
|
||||
config.Config.Tap.Release.Name,
|
||||
config.Config.Tap.Release.Namespace,
|
||||
).Uninstall()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
} else {
|
||||
log.Info().Msgf("Uninstalled the Helm release: %s", resp.Release.Name)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -27,5 +38,5 @@ func init() {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
cleanCmd.Flags().StringP(configStructs.SelfNamespaceLabel, "s", defaultTapConfig.SelfNamespace, "Self-namespace of Kubeshark")
|
||||
cleanCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
)
|
||||
|
||||
func performCleanCommand() {
|
||||
kubernetesProvider, err := getKubernetesProviderForCli(false, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
finishSelfExecution(kubernetesProvider, config.Config.IsNsRestrictedMode(), config.Config.Tap.SelfNamespace, false)
|
||||
}
|
||||
@@ -14,12 +14,11 @@ import (
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/misc/fsUtils"
|
||||
"github.com/kubeshark/kubeshark/resources"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func startProxyReportErrorIfAny(kubernetesProvider *kubernetes.Provider, ctx context.Context, serviceName string, podName string, proxyPortLabel string, srcPort uint16, dstPort uint16, healthCheck string) {
|
||||
httpServer, err := kubernetes.StartProxy(kubernetesProvider, config.Config.Tap.Proxy.Host, srcPort, config.Config.Tap.SelfNamespace, serviceName)
|
||||
httpServer, err := kubernetes.StartProxy(kubernetesProvider, config.Config.Tap.Proxy.Host, srcPort, config.Config.Tap.Release.Namespace, serviceName)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Err(errormessage.FormatError(err)).
|
||||
@@ -27,7 +26,7 @@ func startProxyReportErrorIfAny(kubernetesProvider *kubernetes.Provider, ctx con
|
||||
return
|
||||
}
|
||||
|
||||
connector := connect.NewConnector(kubernetes.GetLocalhostOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector := connect.NewConnector(kubernetes.GetProxyOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
if err := connector.TestConnection(healthCheck); err != nil {
|
||||
log.Warn().
|
||||
Str("service", serviceName).
|
||||
@@ -39,7 +38,7 @@ func startProxyReportErrorIfAny(kubernetesProvider *kubernetes.Provider, ctx con
|
||||
}
|
||||
|
||||
podRegex, _ := regexp.Compile(podName)
|
||||
if _, err := kubernetes.NewPortForward(kubernetesProvider, config.Config.Tap.SelfNamespace, podRegex, srcPort, dstPort, ctx); err != nil {
|
||||
if _, err := kubernetes.NewPortForward(kubernetesProvider, config.Config.Tap.Release.Namespace, podRegex, srcPort, dstPort, ctx); err != nil {
|
||||
log.Error().
|
||||
Str("pod-regex", podRegex.String()).
|
||||
Err(errormessage.FormatError(err)).
|
||||
@@ -47,7 +46,7 @@ func startProxyReportErrorIfAny(kubernetesProvider *kubernetes.Provider, ctx con
|
||||
return
|
||||
}
|
||||
|
||||
connector = connect.NewConnector(kubernetes.GetLocalhostOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector = connect.NewConnector(kubernetes.GetProxyOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
if err := connector.TestConnection(healthCheck); err != nil {
|
||||
log.Error().
|
||||
Str("service", serviceName).
|
||||
@@ -100,13 +99,10 @@ func handleKubernetesProviderError(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func finishSelfExecution(kubernetesProvider *kubernetes.Provider, isNsRestrictedMode bool, selfNamespace string, withoutCleanup bool) {
|
||||
func finishSelfExecution(kubernetesProvider *kubernetes.Provider) {
|
||||
removalCtx, cancel := context.WithTimeout(context.Background(), cleanupTimeout)
|
||||
defer cancel()
|
||||
dumpLogsIfNeeded(removalCtx, kubernetesProvider)
|
||||
if !withoutCleanup {
|
||||
resources.CleanUpSelfResources(removalCtx, cancel, kubernetesProvider, isNsRestrictedMode, selfNamespace)
|
||||
}
|
||||
}
|
||||
|
||||
func dumpLogsIfNeeded(ctx context.Context, kubernetesProvider *kubernetes.Provider) {
|
||||
|
||||
@@ -17,21 +17,20 @@ var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: fmt.Sprintf("Generate %s config with default values", misc.Software),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
configWithDefaults, err := config.GetConfigWithDefaults()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed generating config with defaults.")
|
||||
return nil
|
||||
}
|
||||
|
||||
if config.Config.Config.Regenerate {
|
||||
if err := config.WriteConfig(configWithDefaults); err != nil {
|
||||
defaultConfig := config.CreateDefaultConfig()
|
||||
if err := defaults.Set(&defaultConfig); err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return nil
|
||||
}
|
||||
if err := config.WriteConfig(&defaultConfig); err != nil {
|
||||
log.Error().Err(err).Msg("Failed generating config with defaults.")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Info().Str("config-path", config.ConfigFilePath).Msg("Template file written to config path.")
|
||||
} else {
|
||||
template, err := utils.PrettyYaml(configWithDefaults)
|
||||
template, err := utils.PrettyYaml(config.Config)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed converting config with defaults to YAML.")
|
||||
return nil
|
||||
|
||||
@@ -36,12 +36,13 @@ func init() {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
consoleCmd.Flags().Uint16(configStructs.ProxyHubPortLabel, defaultTapConfig.Proxy.Hub.Port, "Provide a custom port for the Hub")
|
||||
consoleCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Hub")
|
||||
consoleCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the Kubeshark")
|
||||
consoleCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Kubeshark")
|
||||
consoleCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
func runConsole() {
|
||||
hubUrl := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)
|
||||
hubUrl := kubernetes.GetHubUrl()
|
||||
response, err := http.Get(fmt.Sprintf("%s/echo", hubUrl))
|
||||
if err != nil || response.StatusCode != 200 {
|
||||
log.Info().Msg(fmt.Sprintf(utils.Yellow, "Couldn't connect to Hub. Establishing proxy..."))
|
||||
@@ -51,14 +52,16 @@ func runConsole() {
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
|
||||
log.Info().Str("host", config.Config.Tap.Proxy.Host).Uint16("port", config.Config.Tap.Proxy.Hub.Port).Msg("Connecting to:")
|
||||
log.Info().Str("host", config.Config.Tap.Proxy.Host).Str("url", hubUrl).Msg("Connecting to:")
|
||||
u := url.URL{
|
||||
Scheme: "ws",
|
||||
Host: fmt.Sprintf("%s:%d", config.Config.Tap.Proxy.Host, config.Config.Tap.Proxy.Hub.Port),
|
||||
Host: fmt.Sprintf("%s:%d/api", config.Config.Tap.Proxy.Host, config.Config.Tap.Proxy.Front.Port),
|
||||
Path: "/scripts/logs",
|
||||
}
|
||||
headers := http.Header{}
|
||||
headers.Set("License-Key", config.Config.License)
|
||||
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), headers)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
|
||||
62
cmd/export.go
Normal file
62
cmd/export.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/internal/connect"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var exportCmd = &cobra.Command{
|
||||
Use: "export",
|
||||
Short: "Exports the captured traffic into a TAR file that contains PCAP files",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runExport()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(exportCmd)
|
||||
|
||||
defaultTapConfig := configStructs.TapConfig{}
|
||||
if err := defaults.Set(&defaultTapConfig); err != nil {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
exportCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the Kubeshark")
|
||||
exportCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Kubeshark")
|
||||
exportCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
func runExport() {
|
||||
hubUrl := kubernetes.GetHubUrl()
|
||||
response, err := http.Get(fmt.Sprintf("%s/echo", hubUrl))
|
||||
if err != nil || response.StatusCode != 200 {
|
||||
log.Info().Msg(fmt.Sprintf(utils.Yellow, "Couldn't connect to Hub. Establishing proxy..."))
|
||||
runProxy(false, true)
|
||||
}
|
||||
|
||||
dstPath, err := filepath.Abs(fmt.Sprintf("./%d.tar.gz", time.Now().Unix()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out, err := os.Create(dstPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
connector := connect.NewConnector(kubernetes.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector.PostPcapsMerge(out)
|
||||
}
|
||||
488
cmd/helmChart.go
488
cmd/helmChart.go
@@ -1,488 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/misc/fsUtils"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/ohler55/ojg/jp"
|
||||
"github.com/ohler55/ojg/oj"
|
||||
"github.com/otiai10/copy"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var helmChartCmd = &cobra.Command{
|
||||
Use: "helm-chart",
|
||||
Short: "Generate Helm chart of Kubeshark",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runHelmChart()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// Maintainer describes a Chart maintainer.
|
||||
type Maintainer struct {
|
||||
// Name is a user name or organization name
|
||||
Name string `json:"name,omitempty"`
|
||||
// Email is an optional email address to contact the named maintainer
|
||||
Email string `json:"email,omitempty"`
|
||||
// URL is an optional URL to an address for the named maintainer
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// Metadata for a Chart file. This models the structure of a Chart.yaml file.
|
||||
type Metadata struct {
|
||||
// The name of the chart. Required.
|
||||
Name string `json:"name,omitempty"`
|
||||
// The URL to a relevant project page, git repo, or contact person
|
||||
Home string `json:"home,omitempty"`
|
||||
// Source is the URL to the source code of this chart
|
||||
Sources []string `json:"sources,omitempty"`
|
||||
// A SemVer 2 conformant version string of the chart. Required.
|
||||
Version string `json:"version,omitempty"`
|
||||
// A one-sentence description of the chart
|
||||
Description string `json:"description,omitempty"`
|
||||
// A list of string keywords
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
// A list of name and URL/email address combinations for the maintainer(s)
|
||||
Maintainers []*Maintainer `json:"maintainers,omitempty"`
|
||||
// The URL to an icon file.
|
||||
Icon string `json:"icon,omitempty"`
|
||||
// The API Version of this chart. Required.
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
// The condition to check to enable chart
|
||||
Condition string `json:"condition,omitempty"`
|
||||
// The tags to check to enable chart
|
||||
Tags string `json:"tags,omitempty"`
|
||||
// The version of the application enclosed inside of this chart.
|
||||
AppVersion string `json:"appVersion,omitempty"`
|
||||
// Whether or not this chart is deprecated
|
||||
Deprecated bool `json:"deprecated,omitempty"`
|
||||
// Annotations are additional mappings uninterpreted by Helm,
|
||||
// made available for inspection by other applications.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
// KubeVersion is a SemVer constraint specifying the version of Kubernetes required.
|
||||
KubeVersion string `json:"kubeVersion,omitempty"`
|
||||
// Dependencies are a list of dependencies for a chart.
|
||||
Dependencies []*Dependency `json:"dependencies,omitempty"`
|
||||
// Specifies the chart type: application or library
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// Dependency describes a chart upon which another chart depends.
|
||||
//
|
||||
// Dependencies can be used to express developer intent, or to capture the state
|
||||
// of a chart.
|
||||
type Dependency struct {
|
||||
// Name is the name of the dependency.
|
||||
//
|
||||
// This must mach the name in the dependency's Chart.yaml.
|
||||
Name string `json:"name"`
|
||||
// Version is the version (range) of this chart.
|
||||
//
|
||||
// A lock file will always produce a single version, while a dependency
|
||||
// may contain a semantic version range.
|
||||
Version string `json:"version,omitempty"`
|
||||
// The URL to the repository.
|
||||
//
|
||||
// Appending `index.yaml` to this string should result in a URL that can be
|
||||
// used to fetch the repository index.
|
||||
Repository string `json:"repository"`
|
||||
// A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled )
|
||||
Condition string `json:"condition,omitempty"`
|
||||
// Tags can be used to group charts for enabling/disabling together
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
// Enabled bool determines if chart should be loaded
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
// ImportValues holds the mapping of source values to parent key to be imported. Each item can be a
|
||||
// string or pair of child/parent sublist items.
|
||||
ImportValues []interface{} `json:"import-values,omitempty"`
|
||||
// Alias usable alias to be used for the chart
|
||||
Alias string `json:"alias,omitempty"`
|
||||
}
|
||||
|
||||
var namespaceMappings = map[string]interface{}{
|
||||
"metadata.name": "{{ .Values.tap.selfnamespace }}",
|
||||
}
|
||||
var serviceAccountMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
}
|
||||
var clusterRoleMappings = serviceAccountMappings
|
||||
var clusterRoleBindingMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"subjects[0].namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
}
|
||||
var hubPodMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"spec.containers[0].env": []map[string]interface{}{
|
||||
{
|
||||
"name": "POD_REGEX",
|
||||
"value": "{{ .Values.tap.regex }}",
|
||||
},
|
||||
{
|
||||
"name": "NAMESPACES",
|
||||
"value": "{{ gt (len .Values.tap.namespaces) 0 | ternary (join \",\" .Values.tap.namespaces) \"\" }}",
|
||||
},
|
||||
{
|
||||
"name": "LICENSE",
|
||||
"value": "{{ .Values.license }}",
|
||||
},
|
||||
{
|
||||
"name": "SCRIPTING_ENV",
|
||||
"value": "{}",
|
||||
},
|
||||
{
|
||||
"name": "SCRIPTING_SCRIPTS",
|
||||
"value": "[]",
|
||||
},
|
||||
{
|
||||
"name": "AUTH_APPROVED_DOMAINS",
|
||||
"value": "{{ gt (len .Values.tap.ingress.auth.approvedDomains) 0 | ternary (join \",\" .Values.tap.ingress.auth.approvedDomains) \"\" }}",
|
||||
},
|
||||
},
|
||||
"spec.containers[0].image": "{{ .Values.tap.docker.registry }}/hub:{{ .Values.tap.docker.tag }}",
|
||||
"spec.containers[0].imagePullPolicy": "{{ .Values.tap.docker.imagepullpolicy }}",
|
||||
"spec.containers[0].resources.limits.cpu": "{{ .Values.tap.resources.hub.limits.cpu }}",
|
||||
"spec.containers[0].resources.limits.memory": "{{ .Values.tap.resources.hub.limits.memory }}",
|
||||
"spec.containers[0].resources.requests.cpu": "{{ .Values.tap.resources.hub.requests.cpu }}",
|
||||
"spec.containers[0].resources.requests.memory": "{{ .Values.tap.resources.hub.requests.memory }}",
|
||||
"spec.containers[0].command[0]": "{{ .Values.tap.debug | ternary \"./hub -debug\" \"./hub\" }}",
|
||||
}
|
||||
var hubServiceMappings = serviceAccountMappings
|
||||
var frontPodMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"spec.containers[0].image": "{{ .Values.tap.docker.registry }}/front:{{ .Values.tap.docker.tag }}",
|
||||
"spec.containers[0].imagePullPolicy": "{{ .Values.tap.docker.imagepullpolicy }}",
|
||||
"spec.containers[0].env": []map[string]interface{}{
|
||||
{
|
||||
"name": "REACT_APP_DEFAULT_FILTER",
|
||||
"value": " ",
|
||||
},
|
||||
{
|
||||
"name": "REACT_APP_HUB_HOST",
|
||||
"value": " ",
|
||||
},
|
||||
{
|
||||
"name": "REACT_APP_HUB_PORT",
|
||||
"value": "{{ .Values.tap.ingress.enabled | ternary \"80/api\" \"8898\" }}",
|
||||
},
|
||||
},
|
||||
}
|
||||
var frontServiceMappings = serviceAccountMappings
|
||||
var persistentVolumeMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"spec.resources.requests.storage": "{{ .Values.tap.storagelimit }}",
|
||||
"spec.storageClassName": "{{ .Values.tap.storageclass }}",
|
||||
}
|
||||
var workerDaemonSetMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"spec.template.spec.containers[0].image": "{{ .Values.tap.docker.registry }}/worker:{{ .Values.tap.docker.tag }}",
|
||||
"spec.template.spec.containers[0].imagePullPolicy": "{{ .Values.tap.docker.imagepullpolicy }}",
|
||||
"spec.template.spec.containers[0].resources.limits.cpu": "{{ .Values.tap.resources.worker.limits.cpu }}",
|
||||
"spec.template.spec.containers[0].resources.limits.memory": "{{ .Values.tap.resources.worker.limits.memory }}",
|
||||
"spec.template.spec.containers[0].resources.requests.cpu": "{{ .Values.tap.resources.worker.requests.cpu }}",
|
||||
"spec.template.spec.containers[0].resources.requests.memory": "{{ .Values.tap.resources.worker.requests.memory }}",
|
||||
"spec.template.spec.containers[0].command[0]": "{{ .Values.tap.debug | ternary \"./worker -debug\" \"./worker\" }}",
|
||||
"spec.template.spec.containers[0].command[4]": "{{ .Values.tap.proxy.worker.srvport }}",
|
||||
"spec.template.spec.containers[0].command[6]": "{{ .Values.tap.packetcapture }}",
|
||||
}
|
||||
var ingressClassMappings = serviceAccountMappings
|
||||
var ingressMappings = map[string]interface{}{
|
||||
"metadata.namespace": "{{ .Values.tap.selfnamespace }}",
|
||||
"metadata.annotations[\"certmanager.k8s.io/cluster-issuer\"]": "{{ .Values.tap.ingress.certManager }}",
|
||||
"spec.rules[0].host": "{{ .Values.tap.ingress.host }}",
|
||||
"spec.tls": "{{ .Values.tap.ingress.tls | toYaml }}",
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(helmChartCmd)
|
||||
}
|
||||
|
||||
func runHelmChart() {
|
||||
namespace,
|
||||
serviceAccount,
|
||||
clusterRole,
|
||||
clusterRoleBinding,
|
||||
hubPod,
|
||||
hubService,
|
||||
frontPod,
|
||||
frontService,
|
||||
persistentVolume,
|
||||
workerDaemonSet,
|
||||
ingressClass,
|
||||
ingress,
|
||||
err := generateManifests()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
err = dumpHelmChart(map[string]interface{}{
|
||||
"00-namespace.yaml": template(namespace, namespaceMappings),
|
||||
"01-service-account.yaml": template(serviceAccount, serviceAccountMappings),
|
||||
"02-cluster-role.yaml": template(clusterRole, clusterRoleMappings),
|
||||
"03-cluster-role-binding.yaml": template(clusterRoleBinding, clusterRoleBindingMappings),
|
||||
"04-hub-pod.yaml": template(hubPod, hubPodMappings),
|
||||
"05-hub-service.yaml": template(hubService, hubServiceMappings),
|
||||
"06-front-pod.yaml": template(frontPod, frontPodMappings),
|
||||
"07-front-service.yaml": template(frontService, frontServiceMappings),
|
||||
"08-persistent-volume-claim.yaml": template(persistentVolume, persistentVolumeMappings),
|
||||
"09-worker-daemon-set.yaml": template(workerDaemonSet, workerDaemonSetMappings),
|
||||
"10-ingress-class.yaml": template(ingressClass, ingressClassMappings),
|
||||
"11-ingress.yaml": template(ingress, ingressMappings),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func template(object interface{}, mappings map[string]interface{}) (template interface{}) {
|
||||
var err error
|
||||
var data []byte
|
||||
data, err = json.Marshal(object)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
var obj interface{}
|
||||
obj, err = oj.Parse(data)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
for path, value := range mappings {
|
||||
var x jp.Expr
|
||||
x, err = jp.ParseString(path)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
err = x.Set(obj, value)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
newJson := oj.JSON(obj)
|
||||
|
||||
err = json.Unmarshal([]byte(newJson), &template)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func handleHubPod(manifest string) string {
|
||||
lines := strings.Split(manifest, "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "hostPort:") {
|
||||
lines[i] = " hostPort: {{ .Values.tap.proxy.hub.srvport }}"
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func handleFrontPod(manifest string) string {
|
||||
lines := strings.Split(manifest, "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "hostPort:") {
|
||||
lines[i] = " hostPort: {{ .Values.tap.proxy.front.srvport }}"
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func handlePVCManifest(manifest string) string {
|
||||
return fmt.Sprintf("{{- if .Values.tap.persistentstorage }}\n%s{{- end }}\n", manifest)
|
||||
}
|
||||
|
||||
func handleDaemonSetManifest(manifest string) string {
|
||||
lines := strings.Split(manifest, "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.TrimSpace(line) == "- mountPath: /app/data" {
|
||||
lines[i] = fmt.Sprintf("{{- if .Values.tap.persistentstorage }}\n%s", line)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(line) == "name: kubeshark-persistent-volume" {
|
||||
lines[i] = fmt.Sprintf("%s\n{{- end }}", line)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(line) == "- name: kubeshark-persistent-volume" {
|
||||
lines[i] = fmt.Sprintf("{{- if .Values.tap.persistentstorage }}\n%s", line)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(line) == "claimName: kubeshark-persistent-volume-claim" {
|
||||
lines[i] = fmt.Sprintf("%s\n{{- end }}", line)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "- containerPort:") {
|
||||
lines[i] = " - containerPort: {{ .Values.tap.proxy.worker.srvport }}"
|
||||
}
|
||||
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "hostPort:") {
|
||||
lines[i] = " hostPort: {{ .Values.tap.proxy.worker.srvport }}"
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func handleIngressClass(manifest string) string {
|
||||
return fmt.Sprintf("{{- if .Values.tap.ingress.enabled }}\n%s{{- end }}\n", manifest)
|
||||
}
|
||||
|
||||
func handleIngress(manifest string) string {
|
||||
manifest = strings.Replace(manifest, "'{{ .Values.tap.ingress.tls | toYaml }}'", "{{ .Values.tap.ingress.tls | toYaml }}", 1)
|
||||
|
||||
return handleIngressClass(manifest)
|
||||
}
|
||||
|
||||
func dumpHelmChart(objects map[string]interface{}) error {
|
||||
folder := filepath.Join(".", "helm-chart")
|
||||
templatesFolder := filepath.Join(folder, "templates")
|
||||
|
||||
err := fsUtils.RemoveFilesByExtension(templatesFolder, "yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(templatesFolder, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sort by filenames
|
||||
filenames := make([]string, 0)
|
||||
for filename := range objects {
|
||||
filenames = append(filenames, filename)
|
||||
}
|
||||
sort.Strings(filenames)
|
||||
|
||||
// Generate templates
|
||||
for _, filename := range filenames {
|
||||
manifest, err := utils.PrettyYamlOmitEmpty(objects[filename])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if filename == "04-hub-pod.yaml" {
|
||||
manifest = handleHubPod(manifest)
|
||||
}
|
||||
|
||||
if filename == "06-front-pod.yaml" {
|
||||
manifest = handleFrontPod(manifest)
|
||||
}
|
||||
|
||||
if filename == "08-persistent-volume-claim.yaml" {
|
||||
manifest = handlePVCManifest(manifest)
|
||||
}
|
||||
|
||||
if filename == "09-worker-daemon-set.yaml" {
|
||||
manifest = handleDaemonSetManifest(manifest)
|
||||
}
|
||||
|
||||
if filename == "10-ingress-class.yaml" {
|
||||
manifest = handleIngressClass(manifest)
|
||||
}
|
||||
|
||||
if filename == "11-ingress.yaml" {
|
||||
manifest = handleIngress(manifest)
|
||||
}
|
||||
|
||||
path := filepath.Join(templatesFolder, filename)
|
||||
err = os.WriteFile(path, []byte(manifestHeader+manifest), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Msgf("Helm chart template generated: %s", path)
|
||||
}
|
||||
|
||||
// Copy LICENSE
|
||||
licenseSrcPath := filepath.Join(".", "LICENSE")
|
||||
licenseDstPath := filepath.Join(folder, "LICENSE")
|
||||
err = copy.Copy(licenseSrcPath, licenseDstPath)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("path", licenseSrcPath).Msg("Couldn't find the license:")
|
||||
} else {
|
||||
log.Info().Msgf("Helm chart license copied: %s", licenseDstPath)
|
||||
}
|
||||
|
||||
// Generate Chart.yaml
|
||||
chartMetadata := Metadata{
|
||||
APIVersion: "v2",
|
||||
Name: misc.Program,
|
||||
Description: misc.Description,
|
||||
Home: misc.Website,
|
||||
Sources: []string{"https://github.com/kubeshark/kubeshark/tree/master/helm-chart"},
|
||||
Keywords: []string{
|
||||
"kubeshark",
|
||||
"packet capture",
|
||||
"traffic capture",
|
||||
"traffic analyzer",
|
||||
"network sniffer",
|
||||
"observability",
|
||||
"devops",
|
||||
"microservice",
|
||||
"forensics",
|
||||
"api",
|
||||
},
|
||||
Maintainers: []*Maintainer{
|
||||
{
|
||||
Name: misc.Software,
|
||||
Email: misc.Email,
|
||||
URL: misc.Website,
|
||||
},
|
||||
},
|
||||
Version: misc.Ver,
|
||||
AppVersion: misc.Ver,
|
||||
KubeVersion: fmt.Sprintf(">= %s-0", kubernetes.MinKubernetesServerVersion),
|
||||
Type: "application",
|
||||
}
|
||||
|
||||
chart, err := utils.PrettyYamlOmitEmpty(chartMetadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := filepath.Join(folder, "Chart.yaml")
|
||||
err = os.WriteFile(path, []byte(chart), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Msgf("Helm chart Chart.yaml generated: %s", path)
|
||||
|
||||
// Generate values.yaml
|
||||
values, err := utils.PrettyYaml(config.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path = filepath.Join(folder, "values.yaml")
|
||||
err = os.WriteFile(path, []byte(values), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Msgf("Helm chart values.yaml generated: %s", path)
|
||||
|
||||
return nil
|
||||
}
|
||||
21
cmd/license.go
Normal file
21
cmd/license.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var licenseCmd = &cobra.Command{
|
||||
Use: "license",
|
||||
Short: "Print the license loaded string",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Println(config.Config.License)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(licenseCmd)
|
||||
}
|
||||
239
cmd/manifests.go
239
cmd/manifests.go
@@ -1,239 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/docker"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc/fsUtils"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
networking "k8s.io/api/networking/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
)
|
||||
|
||||
const manifestSeperator = "---"
|
||||
const manifestHeader = "# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!\n" + manifestSeperator + "\n"
|
||||
|
||||
var manifestsCmd = &cobra.Command{
|
||||
Use: "manifests",
|
||||
Short: "Generate Kubernetes manifests of Kubeshark",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runManifests()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(manifestsCmd)
|
||||
|
||||
defaultManifestsConfig := config.ManifestsConfig{}
|
||||
if err := defaults.Set(&defaultManifestsConfig); err != nil {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
manifestsCmd.Flags().Bool("dump", defaultManifestsConfig.Dump, "Enable the debug mode")
|
||||
}
|
||||
|
||||
func runManifests() {
|
||||
namespace,
|
||||
serviceAccount,
|
||||
clusterRole,
|
||||
clusterRoleBinding,
|
||||
hubPod,
|
||||
hubService,
|
||||
frontPod,
|
||||
frontService,
|
||||
persistentVolume,
|
||||
workerDaemonSet,
|
||||
ingressClass,
|
||||
ingress,
|
||||
err := generateManifests()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if config.Config.Manifests.Dump {
|
||||
err = dumpManifests(map[string]interface{}{
|
||||
"00-namespace.yaml": namespace,
|
||||
"01-service-account.yaml": serviceAccount,
|
||||
"02-cluster-role.yaml": clusterRole,
|
||||
"03-cluster-role-binding.yaml": clusterRoleBinding,
|
||||
"04-hub-pod.yaml": hubPod,
|
||||
"05-hub-service.yaml": hubService,
|
||||
"06-front-pod.yaml": frontPod,
|
||||
"07-front-service.yaml": frontService,
|
||||
"08-persistent-volume-claim.yaml": persistentVolume,
|
||||
"09-worker-daemon-set.yaml": workerDaemonSet,
|
||||
"10-ingress-class.yaml": ingressClass,
|
||||
"11-ingress.yaml": ingress,
|
||||
})
|
||||
} else {
|
||||
err = printManifests([]interface{}{
|
||||
namespace,
|
||||
serviceAccount,
|
||||
clusterRole,
|
||||
clusterRoleBinding,
|
||||
hubPod,
|
||||
hubService,
|
||||
frontPod,
|
||||
frontService,
|
||||
workerDaemonSet,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func generateManifests() (
|
||||
namespace *v1.Namespace,
|
||||
serviceAccount *v1.ServiceAccount,
|
||||
clusterRole *rbac.ClusterRole,
|
||||
clusterRoleBinding *rbac.ClusterRoleBinding,
|
||||
hubPod *v1.Pod,
|
||||
hubService *v1.Service,
|
||||
frontPod *v1.Pod,
|
||||
frontService *v1.Service,
|
||||
persistentVolumeClaim *v1.PersistentVolumeClaim,
|
||||
workerDaemonSet *kubernetes.DaemonSet,
|
||||
ingressClass *networking.IngressClass,
|
||||
ingress *networking.Ingress,
|
||||
err error,
|
||||
) {
|
||||
config.Config.License = ""
|
||||
persistentStorage := config.Config.Tap.PersistentStorage
|
||||
config.Config.Tap.PersistentStorage = true
|
||||
|
||||
var kubernetesProvider *kubernetes.Provider
|
||||
kubernetesProvider, err = getKubernetesProviderForCli(true, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
namespace = kubernetesProvider.BuildNamespace(config.Config.Tap.SelfNamespace)
|
||||
|
||||
serviceAccount = kubernetesProvider.BuildServiceAccount()
|
||||
|
||||
clusterRole = kubernetesProvider.BuildClusterRole()
|
||||
|
||||
clusterRoleBinding = kubernetesProvider.BuildClusterRoleBinding()
|
||||
|
||||
hubPod, err = kubernetesProvider.BuildHubPod(&kubernetes.PodOptions{
|
||||
Namespace: config.Config.Tap.SelfNamespace,
|
||||
PodName: kubernetes.HubPodName,
|
||||
PodImage: docker.GetHubImage(),
|
||||
ServiceAccountName: kubernetes.ServiceAccountName,
|
||||
Resources: config.Config.Tap.Resources.Hub,
|
||||
ImagePullPolicy: config.Config.ImagePullPolicy(),
|
||||
ImagePullSecrets: config.Config.ImagePullSecrets(),
|
||||
Debug: config.Config.Tap.Debug,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hubService = kubernetesProvider.BuildHubService(config.Config.Tap.SelfNamespace)
|
||||
|
||||
frontPod, err = kubernetesProvider.BuildFrontPod(&kubernetes.PodOptions{
|
||||
Namespace: config.Config.Tap.SelfNamespace,
|
||||
PodName: kubernetes.FrontPodName,
|
||||
PodImage: docker.GetHubImage(),
|
||||
ServiceAccountName: kubernetes.ServiceAccountName,
|
||||
Resources: config.Config.Tap.Resources.Hub,
|
||||
ImagePullPolicy: config.Config.ImagePullPolicy(),
|
||||
ImagePullSecrets: config.Config.ImagePullSecrets(),
|
||||
Debug: config.Config.Tap.Debug,
|
||||
}, config.Config.Tap.Proxy.Host, fmt.Sprintf("%d", config.Config.Tap.Proxy.Hub.Port))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
frontService = kubernetesProvider.BuildFrontService(config.Config.Tap.SelfNamespace)
|
||||
|
||||
persistentVolumeClaim, err = kubernetesProvider.BuildPersistentVolumeClaim()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
workerDaemonSet, err = kubernetesProvider.BuildWorkerDaemonSet(
|
||||
docker.GetWorkerImage(),
|
||||
kubernetes.WorkerDaemonSetName,
|
||||
kubernetes.ServiceAccountName,
|
||||
config.Config.Tap.Resources.Worker,
|
||||
config.Config.ImagePullPolicy(),
|
||||
config.Config.ImagePullSecrets(),
|
||||
config.Config.Tap.ServiceMesh,
|
||||
config.Config.Tap.Tls,
|
||||
config.Config.Tap.Debug,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ingressClass = kubernetesProvider.BuildIngressClass()
|
||||
ingress = kubernetesProvider.BuildIngress()
|
||||
|
||||
config.Config.Tap.PersistentStorage = persistentStorage
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func dumpManifests(objects map[string]interface{}) error {
|
||||
folder := filepath.Join(".", "manifests")
|
||||
|
||||
err := fsUtils.RemoveFilesByExtension(folder, "yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(folder, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sort by filenames
|
||||
filenames := make([]string, 0)
|
||||
for filename := range objects {
|
||||
filenames = append(filenames, filename)
|
||||
}
|
||||
sort.Strings(filenames)
|
||||
|
||||
for _, filename := range filenames {
|
||||
manifest, err := utils.PrettyYamlOmitEmpty(objects[filename])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := filepath.Join(folder, filename)
|
||||
err = os.WriteFile(path, []byte(manifestHeader+manifest), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Msgf("Manifest generated: %s", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printManifests(objects []interface{}) error {
|
||||
for _, object := range objects {
|
||||
manifest, err := utils.PrettyYamlOmitEmpty(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(manifestSeperator)
|
||||
fmt.Println(manifest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
33
cmd/pro.go
33
cmd/pro.go
@@ -2,7 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@@ -28,7 +28,7 @@ var proCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
const (
|
||||
PRO_URL = "https://console.kubeshark.co"
|
||||
PRO_URL = "https://console.kubeshark.co/cli"
|
||||
PRO_PORT = 5252
|
||||
)
|
||||
|
||||
@@ -40,19 +40,20 @@ func init() {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
proCmd.Flags().Uint16(configStructs.ProxyHubPortLabel, defaultTapConfig.Proxy.Hub.Port, "Provide a custom port for the Hub")
|
||||
proCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Hub")
|
||||
proCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the Kubeshark")
|
||||
proCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Kubeshark")
|
||||
proCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
func acquireLicense() {
|
||||
hubUrl := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)
|
||||
hubUrl := kubernetes.GetHubUrl()
|
||||
response, err := http.Get(fmt.Sprintf("%s/echo", hubUrl))
|
||||
if err != nil || response.StatusCode != 200 {
|
||||
log.Info().Msg(fmt.Sprintf(utils.Yellow, "Couldn't connect to Hub. Establishing proxy..."))
|
||||
runProxy(false, true)
|
||||
}
|
||||
|
||||
connector = connect.NewConnector(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector = connect.NewConnector(kubernetes.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
|
||||
log.Info().Str("url", PRO_URL).Msg("Opening in the browser:")
|
||||
utils.OpenBrowser(PRO_URL)
|
||||
@@ -69,9 +70,21 @@ func updateLicense(licenseKey string) {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
connector.PostLicenseSingle(config.Config.License)
|
||||
kubernetesProvider, err := getKubernetesProviderForCli(false, false)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
updated, err := kubernetes.SetSecret(kubernetesProvider, kubernetes.SECRET_LICENSE, config.Config.License)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
log.Info().Msg("Updated the license. Exiting.")
|
||||
if updated {
|
||||
log.Info().Msg("Updated the license, exiting...")
|
||||
} else {
|
||||
log.Info().Msg("Exiting...")
|
||||
}
|
||||
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
@@ -98,7 +111,7 @@ func runLicenseRecieverServer() {
|
||||
})
|
||||
|
||||
ginApp.POST("/", func(c *gin.Context) {
|
||||
data, err := ioutil.ReadAll(c.Request.Body)
|
||||
data, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
c.AbortWithStatus(http.StatusBadRequest)
|
||||
@@ -112,7 +125,7 @@ func runLicenseRecieverServer() {
|
||||
|
||||
go func() {
|
||||
if err := ginApp.Run(fmt.Sprintf(":%d", PRO_PORT)); err != nil {
|
||||
panic(err)
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ func init() {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
proxyCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the front-end proxy/port-forward")
|
||||
proxyCmd.Flags().Uint16(configStructs.ProxyHubPortLabel, defaultTapConfig.Proxy.Hub.Port, "Provide a custom port for the Hub proxy/port-forward")
|
||||
proxyCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the proxy/port-forward")
|
||||
proxyCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the proxy/port-forward")
|
||||
proxyCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func runProxy(block bool, noBrowser bool) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
exists, err := kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.FrontServiceName)
|
||||
exists, err := kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.Release.Namespace, kubernetes.FrontServiceName)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Str("service", kubernetes.FrontServiceName).
|
||||
@@ -42,7 +42,7 @@ func runProxy(block bool, noBrowser bool) {
|
||||
return
|
||||
}
|
||||
|
||||
exists, err = kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.SelfNamespace, kubernetes.HubServiceName)
|
||||
exists, err = kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.Release.Namespace, kubernetes.HubServiceName)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Str("service", kubernetes.HubServiceName).
|
||||
@@ -63,38 +63,8 @@ func runProxy(block bool, noBrowser bool) {
|
||||
|
||||
var establishedProxy bool
|
||||
|
||||
hubUrl := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)
|
||||
response, err := http.Get(fmt.Sprintf("%s/echo", hubUrl))
|
||||
if err == nil && response.StatusCode == 200 {
|
||||
log.Info().
|
||||
Str("service", kubernetes.HubServiceName).
|
||||
Int("port", int(config.Config.Tap.Proxy.Hub.Port)).
|
||||
Msg("Found a running service.")
|
||||
|
||||
okToOpen("Hub", hubUrl, true)
|
||||
} else {
|
||||
startProxyReportErrorIfAny(
|
||||
kubernetesProvider,
|
||||
ctx,
|
||||
kubernetes.HubServiceName,
|
||||
kubernetes.HubPodName,
|
||||
configStructs.ProxyHubPortLabel,
|
||||
config.Config.Tap.Proxy.Hub.Port,
|
||||
configStructs.ContainerPort,
|
||||
"/echo",
|
||||
)
|
||||
connector := connect.NewConnector(hubUrl, connect.DefaultRetries, connect.DefaultTimeout)
|
||||
if err := connector.TestConnection("/echo"); err != nil {
|
||||
log.Error().Msg(fmt.Sprintf(utils.Red, "Couldn't connect to Hub."))
|
||||
return
|
||||
}
|
||||
|
||||
establishedProxy = true
|
||||
okToOpen("Hub", hubUrl, true)
|
||||
}
|
||||
|
||||
frontUrl := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Front.Port)
|
||||
response, err = http.Get(fmt.Sprintf("%s/", frontUrl))
|
||||
frontUrl := kubernetes.GetProxyOnPort(config.Config.Tap.Proxy.Front.Port)
|
||||
response, err := http.Get(fmt.Sprintf("%s/", frontUrl))
|
||||
if err == nil && response.StatusCode == 200 {
|
||||
log.Info().
|
||||
Str("service", kubernetes.FrontServiceName).
|
||||
|
||||
@@ -34,8 +34,9 @@ func init() {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
|
||||
scriptsCmd.Flags().Uint16(configStructs.ProxyHubPortLabel, defaultTapConfig.Proxy.Hub.Port, "Provide a custom port for the Hub")
|
||||
scriptsCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Hub")
|
||||
scriptsCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the Kubeshark")
|
||||
scriptsCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the Kubeshark")
|
||||
scriptsCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
}
|
||||
|
||||
func runScripts() {
|
||||
@@ -44,14 +45,14 @@ func runScripts() {
|
||||
return
|
||||
}
|
||||
|
||||
hubUrl := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)
|
||||
hubUrl := kubernetes.GetHubUrl()
|
||||
response, err := http.Get(fmt.Sprintf("%s/echo", hubUrl))
|
||||
if err != nil || response.StatusCode != 200 {
|
||||
log.Info().Msg(fmt.Sprintf(utils.Yellow, "Couldn't connect to Hub. Establishing proxy..."))
|
||||
runProxy(false, true)
|
||||
}
|
||||
|
||||
connector = connect.NewConnector(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector = connect.NewConnector(kubernetes.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
|
||||
watchScripts(true)
|
||||
}
|
||||
|
||||
12
cmd/tap.go
12
cmd/tap.go
@@ -2,13 +2,11 @@ package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/errormessage"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -47,19 +45,19 @@ func init() {
|
||||
tapCmd.Flags().StringP(configStructs.DockerTagLabel, "t", defaultTapConfig.Docker.Tag, "The tag of the Docker images that are going to be pulled")
|
||||
tapCmd.Flags().String(configStructs.DockerImagePullPolicy, defaultTapConfig.Docker.ImagePullPolicy, "ImagePullPolicy for the Docker images")
|
||||
tapCmd.Flags().StringSlice(configStructs.DockerImagePullSecrets, defaultTapConfig.Docker.ImagePullSecrets, "ImagePullSecrets for the Docker images")
|
||||
tapCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the front-end proxy/port-forward")
|
||||
tapCmd.Flags().Uint16(configStructs.ProxyHubPortLabel, defaultTapConfig.Proxy.Hub.Port, "Provide a custom port for the Hub proxy/port-forward")
|
||||
tapCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the proxy/port-forward")
|
||||
tapCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the proxy/port-forward")
|
||||
tapCmd.Flags().StringSliceP(configStructs.NamespacesLabel, "n", defaultTapConfig.Namespaces, "Namespaces selector")
|
||||
tapCmd.Flags().StringP(configStructs.SelfNamespaceLabel, "s", defaultTapConfig.SelfNamespace, "Self-namespace of Kubeshark")
|
||||
tapCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark")
|
||||
tapCmd.Flags().Bool(configStructs.PersistentStorageLabel, defaultTapConfig.PersistentStorage, "Enable persistent storage (PersistentVolumeClaim)")
|
||||
tapCmd.Flags().Bool(configStructs.PersistentStorageStaticLabel, defaultTapConfig.PersistentStorageStatic, "Persistent storage static provision")
|
||||
tapCmd.Flags().String(configStructs.EfsFileSytemIdAndPathLabel, defaultTapConfig.EfsFileSytemIdAndPath, "EFS file system ID")
|
||||
tapCmd.Flags().String(configStructs.StorageLimitLabel, defaultTapConfig.StorageLimit, "Override the default storage limit (per node)")
|
||||
tapCmd.Flags().String(configStructs.StorageClassLabel, defaultTapConfig.StorageClass, "Override the default storage class of the PersistentVolumeClaim (per node)")
|
||||
tapCmd.Flags().Bool(configStructs.DryRunLabel, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
||||
tapCmd.Flags().StringP(configStructs.PcapLabel, "p", defaultTapConfig.Pcap, fmt.Sprintf("Capture from a PCAP snapshot of %s (.tar.gz) using your Docker Daemon instead of Kubernetes", misc.Software))
|
||||
tapCmd.Flags().Bool(configStructs.ServiceMeshLabel, defaultTapConfig.ServiceMesh, "Capture the encrypted traffic if the cluster is configured with a service mesh and with mTLS")
|
||||
tapCmd.Flags().Bool(configStructs.TlsLabel, defaultTapConfig.Tls, "Capture the traffic that's encrypted with OpenSSL or Go crypto/tls libraries")
|
||||
tapCmd.Flags().Bool(configStructs.IgnoreTaintedLabel, defaultTapConfig.IgnoreTainted, "Ignore tainted pods while running Worker DaemonSet")
|
||||
tapCmd.Flags().Bool(configStructs.IngressEnabledLabel, defaultTapConfig.Ingress.Enabled, "Enable Ingress")
|
||||
tapCmd.Flags().Bool(configStructs.DebugLabel, defaultTapConfig.Debug, "Enable the debug mode")
|
||||
tapCmd.Flags().Bool(configStructs.TelemetryEnabledLabel, defaultTapConfig.Telemetry.Enabled, "Enable/disable Telemetry")
|
||||
}
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/docker"
|
||||
"github.com/kubeshark/kubeshark/internal/connect"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func logPullingImage(image string, reader io.ReadCloser) {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
text := scanner.Text()
|
||||
var data map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(text), &data); err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
|
||||
var id string
|
||||
if val, ok := data["id"]; ok {
|
||||
id = val.(string)
|
||||
}
|
||||
|
||||
var status string
|
||||
if val, ok := data["status"]; ok {
|
||||
status = val.(string)
|
||||
}
|
||||
|
||||
var progress string
|
||||
if val, ok := data["progress"]; ok {
|
||||
progress = val.(string)
|
||||
}
|
||||
|
||||
e := log.Info()
|
||||
if image != "" {
|
||||
e = e.Str("image", image)
|
||||
}
|
||||
|
||||
if progress != "" {
|
||||
e = e.Str("progress", progress)
|
||||
}
|
||||
|
||||
e.Msg(fmt.Sprintf("[%-12s] %-18s", id, status))
|
||||
}
|
||||
}
|
||||
|
||||
func pullImages(ctx context.Context, cli *client.Client, imageFront string, imageHub string, imageWorker string) error {
|
||||
readerFront, err := cli.ImagePull(ctx, imageFront, types.ImagePullOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readerFront.Close()
|
||||
logPullingImage(imageFront, readerFront)
|
||||
|
||||
readerHub, err := cli.ImagePull(ctx, imageHub, types.ImagePullOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readerHub.Close()
|
||||
logPullingImage(imageHub, readerHub)
|
||||
|
||||
readerWorker, err := cli.ImagePull(ctx, imageWorker, types.ImagePullOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readerWorker.Close()
|
||||
logPullingImage(imageWorker, readerWorker)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanUpOldContainers(
|
||||
ctx context.Context,
|
||||
cli *client.Client,
|
||||
nameFront string,
|
||||
nameHub string,
|
||||
nameWorker string,
|
||||
) error {
|
||||
containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
f := fmt.Sprintf("/%s", nameFront)
|
||||
h := fmt.Sprintf("/%s", nameHub)
|
||||
w := fmt.Sprintf("/%s", nameWorker)
|
||||
if utils.Contains(container.Names, f) || utils.Contains(container.Names, h) || utils.Contains(container.Names, w) {
|
||||
err = cli.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{Force: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createAndStartContainers(
|
||||
ctx context.Context,
|
||||
cli *client.Client,
|
||||
imageFront string,
|
||||
imageHub string,
|
||||
imageWorker string,
|
||||
tarReader io.Reader,
|
||||
) (
|
||||
respFront container.ContainerCreateCreatedBody,
|
||||
respHub container.ContainerCreateCreatedBody,
|
||||
respWorker container.ContainerCreateCreatedBody,
|
||||
workerIPAddr string,
|
||||
err error,
|
||||
) {
|
||||
log.Info().Msg("Creating containers...")
|
||||
|
||||
nameFront := fmt.Sprintf("%s-front", misc.Program)
|
||||
nameHub := fmt.Sprintf("%s-hub", misc.Program)
|
||||
nameWorker := fmt.Sprintf("%s-worker", misc.Program)
|
||||
|
||||
err = cleanUpOldContainers(ctx, cli, nameFront, nameHub, nameWorker)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hostIP := "0.0.0.0"
|
||||
|
||||
hostConfigFront := &container.HostConfig{
|
||||
PortBindings: nat.PortMap{
|
||||
nat.Port(fmt.Sprintf("%d/tcp", configStructs.ContainerPort)): []nat.PortBinding{
|
||||
{
|
||||
HostIP: hostIP,
|
||||
HostPort: fmt.Sprintf("%d", config.Config.Tap.Proxy.Front.Port),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
respFront, err = cli.ContainerCreate(ctx, &container.Config{
|
||||
Image: imageFront,
|
||||
Tty: false,
|
||||
Env: []string{
|
||||
"REACT_APP_DEFAULT_FILTER= ",
|
||||
"REACT_APP_HUB_HOST= ",
|
||||
fmt.Sprintf("REACT_APP_HUB_PORT=%d", config.Config.Tap.Proxy.Hub.Port),
|
||||
},
|
||||
}, hostConfigFront, nil, nil, nameFront)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hostConfigHub := &container.HostConfig{
|
||||
PortBindings: nat.PortMap{
|
||||
nat.Port(fmt.Sprintf("%d/tcp", config.Config.Tap.Proxy.Hub.SrvPort)): []nat.PortBinding{
|
||||
{
|
||||
HostIP: hostIP,
|
||||
HostPort: fmt.Sprintf("%d", config.Config.Tap.Proxy.Hub.Port),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmdHub := []string{"-port", fmt.Sprintf("%d", config.Config.Tap.Proxy.Hub.SrvPort)}
|
||||
if config.DebugMode {
|
||||
cmdHub = append(cmdHub, fmt.Sprintf("-%s", config.DebugFlag))
|
||||
}
|
||||
|
||||
respHub, err = cli.ContainerCreate(ctx, &container.Config{
|
||||
Image: imageHub,
|
||||
Cmd: cmdHub,
|
||||
Tty: false,
|
||||
ExposedPorts: nat.PortSet{nat.Port(fmt.Sprintf("%d/tcp", config.Config.Tap.Proxy.Hub.SrvPort)): {}},
|
||||
}, hostConfigHub, nil, nil, nameHub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cmdWorker := []string{"-f", "./import", "-port", fmt.Sprintf("%d", config.Config.Tap.Proxy.Worker.SrvPort)}
|
||||
if config.DebugMode {
|
||||
cmdWorker = append(cmdWorker, fmt.Sprintf("-%s", config.DebugFlag))
|
||||
}
|
||||
|
||||
respWorker, err = cli.ContainerCreate(ctx, &container.Config{
|
||||
Image: imageWorker,
|
||||
Cmd: cmdWorker,
|
||||
Tty: false,
|
||||
}, nil, nil, nil, nameWorker)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = cli.CopyToContainer(ctx, respWorker.ID, "/app/import", tarReader, types.CopyToContainerOptions{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Info().Msg("Starting containers...")
|
||||
|
||||
if err = cli.ContainerStart(ctx, respFront.ID, types.ContainerStartOptions{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = cli.ContainerStart(ctx, respHub.ID, types.ContainerStartOptions{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = cli.ContainerStart(ctx, respWorker.ID, types.ContainerStartOptions{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var containerWorker types.ContainerJSON
|
||||
containerWorker, err = cli.ContainerInspect(ctx, respWorker.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
workerIPAddr = containerWorker.NetworkSettings.IPAddress
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func stopAndRemoveContainers(
|
||||
ctx context.Context,
|
||||
cli *client.Client,
|
||||
respFront container.ContainerCreateCreatedBody,
|
||||
respHub container.ContainerCreateCreatedBody,
|
||||
respWorker container.ContainerCreateCreatedBody,
|
||||
) (err error) {
|
||||
log.Warn().Msg("Stopping containers...")
|
||||
err = cli.ContainerStop(ctx, respFront.ID, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = cli.ContainerStop(ctx, respHub.ID, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = cli.ContainerStop(ctx, respWorker.ID, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Warn().Msg("Removing containers...")
|
||||
err = cli.ContainerRemove(ctx, respFront.ID, types.ContainerRemoveOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = cli.ContainerRemove(ctx, respHub.ID, types.ContainerRemoveOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = cli.ContainerRemove(ctx, respWorker.ID, types.ContainerRemoveOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func pcap(tarPath string) {
|
||||
docker.SetRegistry(config.Config.Tap.Docker.Registry)
|
||||
docker.SetTag(config.Config.Tap.Docker.Tag)
|
||||
|
||||
ctx := context.Background()
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
imageFront := docker.GetFrontImage()
|
||||
imageHub := docker.GetHubImage()
|
||||
imageWorker := docker.GetWorkerImage()
|
||||
|
||||
err = pullImages(ctx, cli, imageFront, imageHub, imageWorker)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
tarFile, err := os.Open(tarPath)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
defer tarFile.Close()
|
||||
tarReader := bufio.NewReader(tarFile)
|
||||
|
||||
respFront, respHub, respWorker, workerIPAddr, err := createAndStartContainers(
|
||||
ctx,
|
||||
cli,
|
||||
imageFront,
|
||||
imageHub,
|
||||
imageWorker,
|
||||
tarReader,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
workerPod := &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
NodeName: "docker",
|
||||
},
|
||||
Status: v1.PodStatus{
|
||||
PodIP: workerIPAddr,
|
||||
Phase: v1.PodRunning,
|
||||
ContainerStatuses: []v1.ContainerStatus{
|
||||
{
|
||||
Ready: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
connector = connect.NewConnector(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector.PostWorkerPodToHub(workerPod)
|
||||
|
||||
// License
|
||||
if config.Config.License != "" {
|
||||
connector.PostLicense(config.Config.License)
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("url", kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)).
|
||||
Msg(fmt.Sprintf(utils.Green, "Hub is available at:"))
|
||||
|
||||
url := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Front.Port)
|
||||
log.Info().Str("url", url).Msg(fmt.Sprintf(utils.Green, fmt.Sprintf("%s is available at:", misc.Software)))
|
||||
|
||||
if !config.Config.HeadlessMode {
|
||||
utils.OpenBrowser(url)
|
||||
}
|
||||
|
||||
ctxC, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
utils.WaitForTermination(ctxC, cancel)
|
||||
|
||||
err = stopAndRemoveContainers(ctx, cli, respFront, respHub, respWorker)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
}
|
||||
198
cmd/tapRunner.go
198
cmd/tapRunner.go
@@ -2,21 +2,20 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kubeshark/kubeshark/docker"
|
||||
"github.com/kubeshark/kubeshark/internal/connect"
|
||||
"github.com/kubeshark/kubeshark/kubernetes/helm"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/resources"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
|
||||
core "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
@@ -28,9 +27,8 @@ import (
|
||||
const cleanupTimeout = time.Minute
|
||||
|
||||
type tapState struct {
|
||||
startTime time.Time
|
||||
targetNamespaces []string
|
||||
selfServiceAccountExists bool
|
||||
startTime time.Time
|
||||
targetNamespaces []string
|
||||
}
|
||||
|
||||
var state tapState
|
||||
@@ -48,22 +46,17 @@ var ready *Readiness
|
||||
func tap() {
|
||||
ready = &Readiness{}
|
||||
state.startTime = time.Now()
|
||||
docker.SetRegistry(config.Config.Tap.Docker.Registry)
|
||||
docker.SetTag(config.Config.Tap.Docker.Tag)
|
||||
log.Info().Str("registry", docker.GetRegistry()).Str("tag", docker.GetTag()).Msg("Using Docker:")
|
||||
if config.Config.Tap.Pcap != "" {
|
||||
pcap(config.Config.Tap.Pcap)
|
||||
return
|
||||
}
|
||||
log.Info().Str("registry", config.Config.Tap.Docker.Registry).Str("tag", config.Config.Tap.Docker.Tag).Msg("Using Docker:")
|
||||
|
||||
log.Info().
|
||||
Str("limit", config.Config.Tap.StorageLimit).
|
||||
Msg(fmt.Sprintf("%s will store the traffic up to a limit (per node). Oldest TCP/UDP streams will be removed once the limit is reached.", misc.Software))
|
||||
|
||||
connector = connect.NewConnector(kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
connector = connect.NewConnector(kubernetes.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout)
|
||||
|
||||
kubernetesProvider, err := getKubernetesProviderForCli(false, false)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,12 +65,10 @@ func tap() {
|
||||
|
||||
state.targetNamespaces = kubernetesProvider.GetNamespaces()
|
||||
|
||||
if config.Config.IsNsRestrictedMode() {
|
||||
if len(state.targetNamespaces) != 1 || !utils.Contains(state.targetNamespaces, config.Config.Tap.SelfNamespace) {
|
||||
log.Error().Msg(fmt.Sprintf("%s can't resolve IPs in other namespaces when running in namespace restricted mode. You can use the same namespace for --%s and --%s", misc.Software, configStructs.NamespacesLabel, configStructs.SelfNamespaceLabel))
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Info().
|
||||
Bool("enabled", config.Config.Tap.Telemetry.Enabled).
|
||||
Str("notice", "Telemetry can be disabled by setting the flag: --telemetry-enabled=false").
|
||||
Msg("Telemetry")
|
||||
|
||||
log.Info().Strs("namespaces", state.targetNamespaces).Msg("Targeting pods in:")
|
||||
|
||||
@@ -90,27 +81,31 @@ func tap() {
|
||||
}
|
||||
|
||||
log.Info().Msg(fmt.Sprintf("Waiting for the creation of %s resources...", misc.Software))
|
||||
if state.selfServiceAccountExists, err = resources.CreateHubResources(ctx, kubernetesProvider, config.Config.IsNsRestrictedMode(), config.Config.Tap.SelfNamespace, config.Config.Tap.Resources.Hub, config.Config.ImagePullPolicy(), config.Config.ImagePullSecrets(), config.Config.Tap.Debug); err != nil {
|
||||
var statusError *k8serrors.StatusError
|
||||
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
||||
log.Info().Msg(fmt.Sprintf("%s is already running in this namespace, change the `selfnamespace` configuration or run `%s clean` to remove the currently running %s instance.", misc.Software, misc.Program, misc.Software))
|
||||
postHubStarted(ctx, kubernetesProvider, cancel, true)
|
||||
log.Info().Msg("Updated Hub about the changes in the config. Exiting.")
|
||||
printProxyCommandSuggestion()
|
||||
} else {
|
||||
defer resources.CleanUpSelfResources(ctx, cancel, kubernetesProvider, config.Config.IsNsRestrictedMode(), config.Config.Tap.SelfNamespace)
|
||||
log.Error().Err(errormessage.FormatError(err)).Msg("Error creating resources!")
|
||||
}
|
||||
|
||||
return
|
||||
rel, err := helm.NewHelm(
|
||||
config.Config.Tap.Release.Repo,
|
||||
config.Config.Tap.Release.Name,
|
||||
config.Config.Tap.Release.Namespace,
|
||||
).Install()
|
||||
if err != nil {
|
||||
if err.Error() != "cannot re-use a name that is still in use" {
|
||||
log.Error().Err(err).Send()
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Info().Msg("Found an existing installation, skipping Helm install...")
|
||||
|
||||
updateConfig(kubernetesProvider)
|
||||
postFrontStarted(ctx, kubernetesProvider, cancel)
|
||||
} else {
|
||||
log.Info().Msgf("Installed the Helm release: %s", rel.Name)
|
||||
|
||||
go watchHubEvents(ctx, kubernetesProvider, cancel)
|
||||
go watchHubPod(ctx, kubernetesProvider, cancel)
|
||||
go watchFrontPod(ctx, kubernetesProvider, cancel)
|
||||
}
|
||||
|
||||
defer finishTapExecution(kubernetesProvider)
|
||||
|
||||
go watchHubEvents(ctx, kubernetesProvider, cancel)
|
||||
go watchHubPod(ctx, kubernetesProvider, cancel)
|
||||
go watchFrontPod(ctx, kubernetesProvider, cancel)
|
||||
|
||||
// block until exit signal or error
|
||||
utils.WaitForTermination(ctx, cancel)
|
||||
|
||||
@@ -126,7 +121,7 @@ func printProxyCommandSuggestion() {
|
||||
}
|
||||
|
||||
func finishTapExecution(kubernetesProvider *kubernetes.Provider) {
|
||||
finishSelfExecution(kubernetesProvider, config.Config.IsNsRestrictedMode(), config.Config.Tap.SelfNamespace, true)
|
||||
finishSelfExecution(kubernetesProvider)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -157,9 +152,9 @@ func printNoPodsFoundSuggestion(targetNamespaces []string) {
|
||||
}
|
||||
|
||||
func watchHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s$", kubernetes.HubPodName))
|
||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s", kubernetes.HubPodName))
|
||||
podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex)
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.SelfNamespace}, podWatchHelper)
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.Release.Namespace}, podWatchHelper)
|
||||
isPodReady := false
|
||||
|
||||
timeAfter := time.After(120 * time.Second)
|
||||
@@ -198,7 +193,6 @@ func watchHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, c
|
||||
ready.Lock()
|
||||
ready.Hub = true
|
||||
ready.Unlock()
|
||||
postHubStarted(ctx, kubernetesProvider, cancel, false)
|
||||
}
|
||||
|
||||
ready.Lock()
|
||||
@@ -226,7 +220,7 @@ func watchHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, c
|
||||
|
||||
log.Error().
|
||||
Str("pod", kubernetes.HubPodName).
|
||||
Str("namespace", config.Config.Tap.SelfNamespace).
|
||||
Str("namespace", config.Config.Tap.Release.Namespace).
|
||||
Err(err).
|
||||
Msg("Failed creating pod.")
|
||||
cancel()
|
||||
@@ -248,9 +242,9 @@ func watchHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, c
|
||||
}
|
||||
|
||||
func watchFrontPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s$", kubernetes.FrontPodName))
|
||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s", kubernetes.FrontPodName))
|
||||
podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex)
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.SelfNamespace}, podWatchHelper)
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.Release.Namespace}, podWatchHelper)
|
||||
isPodReady := false
|
||||
|
||||
timeAfter := time.After(120 * time.Second)
|
||||
@@ -315,7 +309,7 @@ func watchFrontPod(ctx context.Context, kubernetesProvider *kubernetes.Provider,
|
||||
|
||||
log.Error().
|
||||
Str("pod", kubernetes.FrontPodName).
|
||||
Str("namespace", config.Config.Tap.SelfNamespace).
|
||||
Str("namespace", config.Config.Tap.Release.Namespace).
|
||||
Err(err).
|
||||
Msg("Failed creating pod.")
|
||||
|
||||
@@ -338,7 +332,7 @@ func watchFrontPod(ctx context.Context, kubernetesProvider *kubernetes.Provider,
|
||||
func watchHubEvents(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
||||
podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s", kubernetes.HubPodName))
|
||||
eventWatchHelper := kubernetes.NewEventWatchHelper(kubernetesProvider, podExactRegex, "pod")
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, eventWatchHelper, []string{config.Config.Tap.SelfNamespace}, eventWatchHelper)
|
||||
eventChan, errorChan := kubernetes.FilteredWatch(ctx, eventWatchHelper, []string{config.Config.Tap.Release.Namespace}, eventWatchHelper)
|
||||
for {
|
||||
select {
|
||||
case wEvent, ok := <-eventChan:
|
||||
@@ -404,73 +398,6 @@ func watchHubEvents(ctx context.Context, kubernetesProvider *kubernetes.Provider
|
||||
}
|
||||
}
|
||||
|
||||
func postHubStarted(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc, update bool) {
|
||||
startProxyReportErrorIfAny(
|
||||
kubernetesProvider,
|
||||
ctx,
|
||||
kubernetes.HubServiceName,
|
||||
kubernetes.HubPodName,
|
||||
configStructs.ProxyHubPortLabel,
|
||||
config.Config.Tap.Proxy.Hub.Port,
|
||||
configStructs.ContainerPort,
|
||||
"/echo",
|
||||
)
|
||||
|
||||
if !update {
|
||||
// Create workers
|
||||
err := kubernetes.CreateWorkers(
|
||||
kubernetesProvider,
|
||||
state.selfServiceAccountExists,
|
||||
ctx,
|
||||
config.Config.Tap.SelfNamespace,
|
||||
config.Config.Tap.Resources.Worker,
|
||||
config.Config.ImagePullPolicy(),
|
||||
config.Config.ImagePullSecrets(),
|
||||
config.Config.Tap.ServiceMesh,
|
||||
config.Config.Tap.Tls,
|
||||
config.Config.Tap.Debug,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
} else {
|
||||
// Pod regex
|
||||
connector.PostRegexToHub(config.Config.Tap.PodRegexStr, state.targetNamespaces)
|
||||
|
||||
// License
|
||||
if config.Config.License != "" {
|
||||
connector.PostLicense(config.Config.License)
|
||||
}
|
||||
|
||||
// Scripting
|
||||
connector.PostEnv(config.Config.Scripting.Env)
|
||||
|
||||
scripts, err := config.Config.Scripting.GetScripts()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
for _, script := range scripts {
|
||||
_, err = connector.PostScript(script)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
connector.PostScriptDone()
|
||||
}
|
||||
|
||||
if !update && !config.Config.Tap.Ingress.Enabled {
|
||||
// Hub proxy URL
|
||||
url := kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Hub.Port)
|
||||
log.Info().Str("url", url).Msg(fmt.Sprintf(utils.Green, "Hub is available at:"))
|
||||
}
|
||||
|
||||
if config.Config.Scripting.Source != "" && config.Config.Scripting.WatchScripts {
|
||||
watchScripts(false)
|
||||
}
|
||||
}
|
||||
|
||||
func postFrontStarted(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) {
|
||||
startProxyReportErrorIfAny(
|
||||
kubernetesProvider,
|
||||
@@ -487,11 +414,52 @@ func postFrontStarted(ctx context.Context, kubernetesProvider *kubernetes.Provid
|
||||
if config.Config.Tap.Ingress.Enabled {
|
||||
url = fmt.Sprintf("http://%s", config.Config.Tap.Ingress.Host)
|
||||
} else {
|
||||
url = kubernetes.GetLocalhostOnPort(config.Config.Tap.Proxy.Front.Port)
|
||||
url = kubernetes.GetProxyOnPort(config.Config.Tap.Proxy.Front.Port)
|
||||
}
|
||||
log.Info().Str("url", url).Msg(fmt.Sprintf(utils.Green, fmt.Sprintf("%s is available at:", misc.Software)))
|
||||
|
||||
if !config.Config.HeadlessMode {
|
||||
utils.OpenBrowser(url)
|
||||
}
|
||||
|
||||
for !ready.Hub {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
if config.Config.Scripting.Source != "" && config.Config.Scripting.WatchScripts {
|
||||
watchScripts(false)
|
||||
}
|
||||
}
|
||||
|
||||
func updateConfig(kubernetesProvider *kubernetes.Provider) {
|
||||
_, _ = kubernetes.SetSecret(kubernetesProvider, kubernetes.SECRET_LICENSE, config.Config.License)
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_POD_REGEX, config.Config.Tap.PodRegexStr)
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_NAMESPACES, strings.Join(config.Config.Tap.Namespaces, ","))
|
||||
|
||||
data, err := json.Marshal(config.Config.Scripting.Env)
|
||||
if err != nil {
|
||||
log.Error().Str("config", kubernetes.CONFIG_SCRIPTING_ENV).Err(err).Send()
|
||||
return
|
||||
} else {
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_SCRIPTING_ENV, string(data))
|
||||
}
|
||||
|
||||
ingressEnabled := ""
|
||||
if config.Config.Tap.Ingress.Enabled {
|
||||
ingressEnabled = "true"
|
||||
}
|
||||
|
||||
authEnabled := ""
|
||||
if config.Config.Tap.Auth.Enabled {
|
||||
authEnabled = "true"
|
||||
}
|
||||
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_INGRESS_ENABLED, ingressEnabled)
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_INGRESS_HOST, config.Config.Tap.Ingress.Host)
|
||||
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_PROXY_FRONT_PORT, fmt.Sprint(config.Config.Tap.Proxy.Front.Port))
|
||||
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_AUTH_ENABLED, authEnabled)
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_AUTH_TYPE, config.Config.Tap.Auth.Type)
|
||||
_, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_AUTH_SAML_IDP_METADATA_URL, config.Config.Tap.Auth.Saml.IdpMetadataUrl)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/misc/version"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
@@ -19,7 +20,6 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -56,11 +56,13 @@ func InitConfig(cmd *cobra.Command) error {
|
||||
"console",
|
||||
"pro",
|
||||
"manifests",
|
||||
"license",
|
||||
}, cmd.Use) {
|
||||
go version.CheckNewerVersion()
|
||||
}
|
||||
|
||||
Config = CreateDefaultConfig()
|
||||
Config.Tap.Debug = DebugMode
|
||||
cmdName = cmd.Name()
|
||||
if utils.Contains([]string{
|
||||
"clean",
|
||||
@@ -79,6 +81,7 @@ func InitConfig(cmd *cobra.Command) error {
|
||||
ConfigFilePath = path.Join(misc.GetDotFolderPath(), "config.yaml")
|
||||
if err := loadConfigFile(&Config, utils.Contains([]string{
|
||||
"manifests",
|
||||
"license",
|
||||
}, cmd.Use)); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("invalid config, %w\n"+
|
||||
|
||||
@@ -5,38 +5,98 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
const (
|
||||
KubeConfigPathConfigName = "kube-configpath"
|
||||
KubeConfigPathConfigName = "kube-configPath"
|
||||
)
|
||||
|
||||
func CreateDefaultConfig() ConfigStruct {
|
||||
return ConfigStruct{}
|
||||
return ConfigStruct{
|
||||
Tap: configStructs.TapConfig{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "kubernetes.io/os",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"linux"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Capabilities: configStructs.CapabilitiesConfig{
|
||||
NetworkCapture: []string{
|
||||
// NET_RAW is required to listen the network traffic
|
||||
"NET_RAW",
|
||||
// NET_ADMIN is required to listen the network traffic
|
||||
"NET_ADMIN",
|
||||
},
|
||||
ServiceMeshCapture: []string{
|
||||
// SYS_ADMIN is required to read /proc/PID/net/ns + to install eBPF programs (kernel < 5.8)
|
||||
"SYS_ADMIN",
|
||||
// SYS_PTRACE is required to set netns to other process + to open libssl.so of other process
|
||||
"SYS_PTRACE",
|
||||
// DAC_OVERRIDE is required to read /proc/PID/environ
|
||||
"DAC_OVERRIDE",
|
||||
},
|
||||
KernelModule: []string{
|
||||
// SYS_MODULE is required to install kernel modules
|
||||
"SYS_MODULE",
|
||||
},
|
||||
EBPFCapture: []string{
|
||||
// SYS_ADMIN is required to read /proc/PID/net/ns + to install eBPF programs (kernel < 5.8)
|
||||
"SYS_ADMIN",
|
||||
// SYS_PTRACE is required to set netns to other process + to open libssl.so of other process
|
||||
"SYS_PTRACE",
|
||||
// SYS_RESOURCE is required to change rlimits for eBPF
|
||||
"SYS_RESOURCE",
|
||||
// IPC_LOCK is required for ebpf perf buffers allocations after some amount of size buffer size:
|
||||
// https://github.com/kubeshark/tracer/blob/13e24725ba8b98216dd0e553262e6d9c56dce5fa/main.go#L82)
|
||||
"IPC_LOCK",
|
||||
},
|
||||
},
|
||||
Auth: configStructs.AuthConfig{
|
||||
Saml: configStructs.SamlConfig{
|
||||
RoleAttribute: "role",
|
||||
Roles: map[string]configStructs.Role{
|
||||
"admin": {
|
||||
Filter: "",
|
||||
CanReplayTraffic: true,
|
||||
CanDownloadPCAP: true,
|
||||
CanUseScripting: true,
|
||||
CanUpdateTargetedPods: true,
|
||||
ShowAdminConsoleLink: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type KubeConfig struct {
|
||||
ConfigPathStr string `yaml:"configpath"`
|
||||
Context string `yaml:"context"`
|
||||
ConfigPathStr string `yaml:"configPath" json:"configPath"`
|
||||
Context string `yaml:"context" json:"context"`
|
||||
}
|
||||
|
||||
type ManifestsConfig struct {
|
||||
Dump bool `yaml:"dump"`
|
||||
Dump bool `yaml:"dump" json:"dump"`
|
||||
}
|
||||
|
||||
type ConfigStruct struct {
|
||||
Tap configStructs.TapConfig `yaml:"tap"`
|
||||
Logs configStructs.LogsConfig `yaml:"logs"`
|
||||
Config configStructs.ConfigConfig `yaml:"config,omitempty"`
|
||||
Kube KubeConfig `yaml:"kube"`
|
||||
DumpLogs bool `yaml:"dumplogs" default:"false"`
|
||||
HeadlessMode bool `yaml:"headless" default:"false"`
|
||||
License string `yaml:"license" default:""`
|
||||
Scripting configStructs.ScriptingConfig `yaml:"scripting"`
|
||||
Manifests ManifestsConfig `yaml:"manifests,omitempty"`
|
||||
Tap configStructs.TapConfig `yaml:"tap" json:"tap"`
|
||||
Logs configStructs.LogsConfig `yaml:"logs" json:"logs"`
|
||||
Config configStructs.ConfigConfig `yaml:"config,omitempty" json:"config,omitempty"`
|
||||
Kube KubeConfig `yaml:"kube" json:"kube"`
|
||||
DumpLogs bool `yaml:"dumpLogs" json:"dumpLogs" default:"false"`
|
||||
HeadlessMode bool `yaml:"headless" json:"headless" default:"false"`
|
||||
License string `yaml:"license" json:"license" default:""`
|
||||
Scripting configStructs.ScriptingConfig `yaml:"scripting" json:"scripting"`
|
||||
Manifests ManifestsConfig `yaml:"manifests,omitempty" json:"manifests,omitempty"`
|
||||
Timezone string `yaml:"timezone" json:"timezone"`
|
||||
}
|
||||
|
||||
func (config *ConfigStruct) ImagePullPolicy() v1.PullPolicy {
|
||||
@@ -52,10 +112,6 @@ func (config *ConfigStruct) ImagePullSecrets() []v1.LocalObjectReference {
|
||||
return ref
|
||||
}
|
||||
|
||||
func (config *ConfigStruct) IsNsRestrictedMode() bool {
|
||||
return config.Tap.SelfNamespace != misc.Program // Notice "kubeshark" string must match the default SelfNamespace
|
||||
}
|
||||
|
||||
func (config *ConfigStruct) KubeConfigPath() string {
|
||||
if config.Kube.ConfigPathStr != "" {
|
||||
return config.Kube.ConfigPathStr
|
||||
|
||||
@@ -5,5 +5,5 @@ const (
|
||||
)
|
||||
|
||||
type ConfigConfig struct {
|
||||
Regenerate bool `yaml:"regenerate,omitempty" default:"false" readonly:""`
|
||||
Regenerate bool `yaml:"regenerate,omitempty" json:"regenerate,omitempty" default:"false" readonly:""`
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const (
|
||||
)
|
||||
|
||||
type LogsConfig struct {
|
||||
FileStr string `yaml:"file"`
|
||||
FileStr string `yaml:"file" json:"file"`
|
||||
}
|
||||
|
||||
func (config *LogsConfig) Validate() error {
|
||||
|
||||
@@ -2,7 +2,7 @@ package configStructs
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
)
|
||||
|
||||
type ScriptingConfig struct {
|
||||
Env map[string]interface{} `yaml:"env"`
|
||||
Source string `yaml:"source" default:""`
|
||||
WatchScripts bool `yaml:"watchScripts" default:"true"`
|
||||
Env map[string]interface{} `yaml:"env" json:"env" default:"{}"`
|
||||
Source string `yaml:"source" json:"source" default:""`
|
||||
WatchScripts bool `yaml:"watchScripts" json:"watchScripts" default:"true"`
|
||||
}
|
||||
|
||||
func (config *ScriptingConfig) GetScripts() (scripts []*misc.Script, err error) {
|
||||
@@ -20,8 +20,8 @@ func (config *ScriptingConfig) GetScripts() (scripts []*misc.Script, err error)
|
||||
return
|
||||
}
|
||||
|
||||
var files []fs.FileInfo
|
||||
files, err = ioutil.ReadDir(config.Source)
|
||||
var files []fs.DirEntry
|
||||
files, err = os.ReadDir(config.Source)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,109 +9,181 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
DockerRegistryLabel = "docker-registry"
|
||||
DockerTagLabel = "docker-tag"
|
||||
DockerImagePullPolicy = "docker-imagepullpolicy"
|
||||
DockerImagePullSecrets = "docker-imagepullsecrets"
|
||||
ProxyFrontPortLabel = "proxy-front-port"
|
||||
ProxyHubPortLabel = "proxy-hub-port"
|
||||
ProxyHostLabel = "proxy-host"
|
||||
NamespacesLabel = "namespaces"
|
||||
SelfNamespaceLabel = "selfnamespace"
|
||||
PersistentStorageLabel = "persistentstorage"
|
||||
StorageLimitLabel = "storagelimit"
|
||||
StorageClassLabel = "storageclass"
|
||||
DryRunLabel = "dryrun"
|
||||
PcapLabel = "pcap"
|
||||
ServiceMeshLabel = "servicemesh"
|
||||
TlsLabel = "tls"
|
||||
IgnoreTaintedLabel = "ignoreTainted"
|
||||
IngressEnabledLabel = "ingress-enabled"
|
||||
DebugLabel = "debug"
|
||||
ContainerPort = 80
|
||||
ContainerPortStr = "80"
|
||||
DockerRegistryLabel = "docker-registry"
|
||||
DockerTagLabel = "docker-tag"
|
||||
DockerImagePullPolicy = "docker-imagePullPolicy"
|
||||
DockerImagePullSecrets = "docker-imagePullSecrets"
|
||||
ProxyFrontPortLabel = "proxy-front-port"
|
||||
ProxyHubPortLabel = "proxy-hub-port"
|
||||
ProxyHostLabel = "proxy-host"
|
||||
NamespacesLabel = "namespaces"
|
||||
ReleaseNamespaceLabel = "release-namespace"
|
||||
PersistentStorageLabel = "persistentStorage"
|
||||
PersistentStorageStaticLabel = "persistentStorageStatic"
|
||||
EfsFileSytemIdAndPathLabel = "efsFileSytemIdAndPath"
|
||||
StorageLimitLabel = "storageLimit"
|
||||
StorageClassLabel = "storageClass"
|
||||
DryRunLabel = "dryRun"
|
||||
PcapLabel = "pcap"
|
||||
ServiceMeshLabel = "serviceMesh"
|
||||
TlsLabel = "tls"
|
||||
IgnoreTaintedLabel = "ignoreTainted"
|
||||
IngressEnabledLabel = "ingress-enabled"
|
||||
TelemetryEnabledLabel = "telemetry-enabled"
|
||||
DebugLabel = "debug"
|
||||
ContainerPort = 80
|
||||
ContainerPortStr = "80"
|
||||
)
|
||||
|
||||
type ResourceLimits struct {
|
||||
CPU string `yaml:"cpu" default:"750m"`
|
||||
Memory string `yaml:"memory" default:"1Gi"`
|
||||
CPU string `yaml:"cpu" json:"cpu" default:"750m"`
|
||||
Memory string `yaml:"memory" json:"memory" default:"1Gi"`
|
||||
}
|
||||
|
||||
type ResourceRequests struct {
|
||||
CPU string `yaml:"cpu" default:"50m"`
|
||||
Memory string `yaml:"memory" default:"50Mi"`
|
||||
CPU string `yaml:"cpu" json:"cpu" default:"50m"`
|
||||
Memory string `yaml:"memory" json:"memory" default:"50Mi"`
|
||||
}
|
||||
|
||||
type ResourceRequirements struct {
|
||||
Limits ResourceLimits `json:"limits"`
|
||||
Requests ResourceRequests `json:"requests"`
|
||||
Limits ResourceLimits `yaml:"limits" json:"limits"`
|
||||
Requests ResourceRequests `yaml:"requests" json:"requests"`
|
||||
}
|
||||
|
||||
type WorkerConfig struct {
|
||||
SrvPort uint16 `yaml:"srvport" default:"8897"`
|
||||
SrvPort uint16 `yaml:"srvPort" json:"srvPort" default:"30001"`
|
||||
}
|
||||
|
||||
type HubConfig struct {
|
||||
Port uint16 `yaml:"port" default:"8898"`
|
||||
SrvPort uint16 `yaml:"srvport" default:"8898"`
|
||||
SrvPort uint16 `yaml:"srvPort" json:"srvPort" default:"8898"`
|
||||
}
|
||||
|
||||
type FrontConfig struct {
|
||||
Port uint16 `yaml:"port" default:"8899"`
|
||||
SrvPort uint16 `yaml:"srvport" default:"8899"`
|
||||
Port uint16 `yaml:"port" json:"port" default:"8899"`
|
||||
}
|
||||
|
||||
type ProxyConfig struct {
|
||||
Worker WorkerConfig `yaml:"worker"`
|
||||
Hub HubConfig `yaml:"hub"`
|
||||
Front FrontConfig `yaml:"front"`
|
||||
Host string `yaml:"host" default:"127.0.0.1"`
|
||||
Worker WorkerConfig `yaml:"worker" json:"worker"`
|
||||
Hub HubConfig `yaml:"hub" json:"hub"`
|
||||
Front FrontConfig `yaml:"front" json:"front"`
|
||||
Host string `yaml:"host" json:"host" default:"127.0.0.1"`
|
||||
}
|
||||
|
||||
type DockerConfig struct {
|
||||
Registry string `yaml:"registry" default:"docker.io/kubeshark"`
|
||||
Tag string `yaml:"tag" default:"latest"`
|
||||
ImagePullPolicy string `yaml:"imagepullpolicy" default:"Always"`
|
||||
ImagePullSecrets []string `yaml:"imagepullsecrets"`
|
||||
Registry string `yaml:"registry" json:"registry" default:"docker.io/kubeshark"`
|
||||
Tag string `yaml:"tag" json:"tag" default:""`
|
||||
ImagePullPolicy string `yaml:"imagePullPolicy" json:"imagePullPolicy" default:"Always"`
|
||||
ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets"`
|
||||
}
|
||||
|
||||
type ResourcesConfig struct {
|
||||
Worker ResourceRequirements `yaml:"worker"`
|
||||
Hub ResourceRequirements `yaml:"hub"`
|
||||
Hub ResourceRequirements `yaml:"hub" json:"hub"`
|
||||
Sniffer ResourceRequirements `yaml:"sniffer" json:"sniffer"`
|
||||
Tracer ResourceRequirements `yaml:"tracer" json:"tracer"`
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Filter string `yaml:"filter" json:"filter" default:""`
|
||||
CanReplayTraffic bool `yaml:"canReplayTraffic" json:"canReplayTraffic" default:"false"`
|
||||
CanDownloadPCAP bool `yaml:"canDownloadPCAP" json:"canDownloadPCAP" default:"false"`
|
||||
CanUseScripting bool `yaml:"canUseScripting" json:"canUseScripting" default:"false"`
|
||||
CanUpdateTargetedPods bool `yaml:"canUpdateTargetedPods" json:"canUpdateTargetedPods" default:"false"`
|
||||
ShowAdminConsoleLink bool `yaml:"showAdminConsoleLink" json:"showAdminConsoleLink" default:"false"`
|
||||
}
|
||||
|
||||
type SamlConfig struct {
|
||||
IdpMetadataUrl string `yaml:"idpMetadataUrl" json:"idpMetadataUrl"`
|
||||
X509crt string `yaml:"x509crt" json:"x509crt"`
|
||||
X509key string `yaml:"x509key" json:"x509key"`
|
||||
RoleAttribute string `yaml:"roleAttribute" json:"roleAttribute"`
|
||||
Roles map[string]Role `yaml:"roles" json:"roles"`
|
||||
}
|
||||
|
||||
type AuthConfig struct {
|
||||
ApprovedDomains []string `yaml:"approvedDomains"`
|
||||
Enabled bool `yaml:"enabled" json:"enabled" default:"false"`
|
||||
Type string `yaml:"type" json:"type" default:"saml"`
|
||||
Saml SamlConfig `yaml:"saml" json:"saml"`
|
||||
}
|
||||
|
||||
type IngressConfig struct {
|
||||
Enabled bool `yaml:"enabled" default:"false"`
|
||||
Host string `yaml:"host" default:"ks.svc.cluster.local"`
|
||||
TLS []networking.IngressTLS `yaml:"tls"`
|
||||
Auth AuthConfig `yaml:"auth"`
|
||||
CertManager string `yaml:"certManager" default:"letsencrypt-prod"`
|
||||
Enabled bool `yaml:"enabled" json:"enabled" default:"false"`
|
||||
ClassName string `yaml:"className" json:"className" default:""`
|
||||
Host string `yaml:"host" json:"host" default:"ks.svc.cluster.local"`
|
||||
TLS []networking.IngressTLS `yaml:"tls" json:"tls" default:"[]"`
|
||||
Annotations map[string]string `yaml:"annotations" json:"annotations" default:"{}"`
|
||||
}
|
||||
|
||||
type ReleaseConfig struct {
|
||||
Repo string `yaml:"repo" json:"repo" default:"https://helm.kubeshark.co"`
|
||||
Name string `yaml:"name" json:"name" default:"kubeshark"`
|
||||
Namespace string `yaml:"namespace" json:"namespace" default:"default"`
|
||||
}
|
||||
|
||||
type TelemetryConfig struct {
|
||||
Enabled bool `yaml:"enabled" json:"enabled" default:"true"`
|
||||
}
|
||||
|
||||
type CapabilitiesConfig struct {
|
||||
NetworkCapture []string `yaml:"networkCapture" json:"networkCapture" default:"[]"`
|
||||
ServiceMeshCapture []string `yaml:"serviceMeshCapture" json:"serviceMeshCapture" default:"[]"`
|
||||
KernelModule []string `yaml:"kernelModule" json:"kernelModule" default:"[]"`
|
||||
EBPFCapture []string `yaml:"ebpfCapture" json:"ebpfCapture" default:"[]"`
|
||||
}
|
||||
|
||||
type KernelModuleConfig struct {
|
||||
Enabled bool `yaml:"enabled" json:"enabled" default:"true"`
|
||||
Image string `yaml:"image" json:"image" default:"kubeshark/pf-ring-module:all"`
|
||||
UnloadOnDestroy bool `yaml:"unloadOnDestroy" json:"unloadOnDestroy" default:"false"`
|
||||
}
|
||||
|
||||
type MetricsConfig struct {
|
||||
Port uint16 `yaml:"port" json:"port" default:"49100"`
|
||||
}
|
||||
|
||||
type MiscConfig struct {
|
||||
JsonTTL string `yaml:"jsonTTL" json:"jsonTTL" default:"5m"`
|
||||
PcapTTL string `yaml:"pcapTTL" json:"pcapTTL" default:"10s"`
|
||||
PcapErrorTTL string `yaml:"pcapErrorTTL" json:"pcapErrorTTL" default:"60s"`
|
||||
TrafficSampleRate int `yaml:"trafficSampleRate" json:"trafficSampleRate" default:"100"`
|
||||
TcpStreamChannelTimeoutMs int `yaml:"tcpStreamChannelTimeoutMs" json:"tcpStreamChannelTimeoutMs" default:"10000"`
|
||||
TcpStreamChannelTimeoutShow bool `yaml:"tcpStreamChannelTimeoutShow" json:"tcpStreamChannelTimeoutShow" default:"false"`
|
||||
}
|
||||
|
||||
type TapConfig struct {
|
||||
Docker DockerConfig `yaml:"docker"`
|
||||
Proxy ProxyConfig `yaml:"proxy"`
|
||||
PodRegexStr string `yaml:"regex" default:".*"`
|
||||
Namespaces []string `yaml:"namespaces"`
|
||||
SelfNamespace string `yaml:"selfnamespace" default:"kubeshark"`
|
||||
PersistentStorage bool `yaml:"persistentstorage" default:"false"`
|
||||
StorageLimit string `yaml:"storagelimit" default:"200Mi"`
|
||||
StorageClass string `yaml:"storageclass" default:"standard"`
|
||||
DryRun bool `yaml:"dryrun" default:"false"`
|
||||
Pcap string `yaml:"pcap" default:""`
|
||||
Resources ResourcesConfig `yaml:"resources"`
|
||||
ServiceMesh bool `yaml:"servicemesh" default:"true"`
|
||||
Tls bool `yaml:"tls" default:"true"`
|
||||
PacketCapture string `yaml:"packetcapture" default:"libpcap"`
|
||||
IgnoreTainted bool `yaml:"ignoreTainted" default:"false"`
|
||||
ResourceLabels map[string]string `yaml:"resourceLabels" default:"{}"`
|
||||
NodeSelectorTerms []v1.NodeSelectorTerm `yaml:"nodeSelectorTerms" default:"[]"`
|
||||
Ingress IngressConfig `yaml:"ingress"`
|
||||
Debug bool `yaml:"debug" default:"false"`
|
||||
Docker DockerConfig `yaml:"docker" json:"docker"`
|
||||
Proxy ProxyConfig `yaml:"proxy" json:"proxy"`
|
||||
PodRegexStr string `yaml:"regex" json:"regex" default:".*"`
|
||||
Namespaces []string `yaml:"namespaces" json:"namespaces" default:"[]"`
|
||||
Release ReleaseConfig `yaml:"release" json:"release"`
|
||||
PersistentStorage bool `yaml:"persistentStorage" json:"persistentStorage" default:"false"`
|
||||
PersistentStorageStatic bool `yaml:"persistentStorageStatic" json:"persistentStorageStatic" default:"false"`
|
||||
EfsFileSytemIdAndPath string `yaml:"efsFileSytemIdAndPath" json:"efsFileSytemIdAndPath" default:""`
|
||||
StorageLimit string `yaml:"storageLimit" json:"storageLimit" default:"500Mi"`
|
||||
StorageClass string `yaml:"storageClass" json:"storageClass" default:"standard"`
|
||||
DryRun bool `yaml:"dryRun" json:"dryRun" default:"false"`
|
||||
Resources ResourcesConfig `yaml:"resources" json:"resources"`
|
||||
ServiceMesh bool `yaml:"serviceMesh" json:"serviceMesh" default:"true"`
|
||||
Tls bool `yaml:"tls" json:"tls" default:"true"`
|
||||
PacketCapture string `yaml:"packetCapture" json:"packetCapture" default:"best"`
|
||||
IgnoreTainted bool `yaml:"ignoreTainted" json:"ignoreTainted" default:"false"`
|
||||
Labels map[string]string `yaml:"labels" json:"labels" default:"{}"`
|
||||
Annotations map[string]string `yaml:"annotations" json:"annotations" default:"{}"`
|
||||
NodeSelectorTerms []v1.NodeSelectorTerm `yaml:"nodeSelectorTerms" json:"nodeSelectorTerms" default:"[]"`
|
||||
Auth AuthConfig `yaml:"auth" json:"auth"`
|
||||
Ingress IngressConfig `yaml:"ingress" json:"ingress"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6" default:"true"`
|
||||
Debug bool `yaml:"debug" json:"debug" default:"false"`
|
||||
KernelModule KernelModuleConfig `yaml:"kernelModule" json:"kernelModule"`
|
||||
Telemetry TelemetryConfig `yaml:"telemetry" json:"telemetry"`
|
||||
DefaultFilter string `yaml:"defaultFilter" json:"defaultFilter"`
|
||||
ReplayDisabled bool `yaml:"replayDisabled" json:"replayDisabled" default:"false"`
|
||||
ScriptingDisabled bool `yaml:"scriptingDisabled" json:"scriptingDisabled" default:"false"`
|
||||
TargetedPodsUpdateDisabled bool `yaml:"targetedPodsUpdateDisabled" json:"targetedPodsUpdateDisabled" default:"false"`
|
||||
RecordingDisabled bool `yaml:"recordingDisabled" json:"recordingDisabled" default:"false"`
|
||||
Capabilities CapabilitiesConfig `yaml:"capabilities" json:"capabilities"`
|
||||
GlobalFilter string `yaml:"globalFilter" json:"globalFilter"`
|
||||
Metrics MetricsConfig `yaml:"metrics" json:"metrics"`
|
||||
Misc MiscConfig `yaml:"misc" json:"misc"`
|
||||
}
|
||||
|
||||
func (config *TapConfig) PodRegex() *regexp.Regexp {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
hub = "hub"
|
||||
worker = "worker"
|
||||
front = "front"
|
||||
)
|
||||
|
||||
var (
|
||||
registry = "docker.io/kubeshark/"
|
||||
tag = "latest"
|
||||
)
|
||||
|
||||
func GetRegistry() string {
|
||||
return registry
|
||||
}
|
||||
|
||||
func SetRegistry(value string) {
|
||||
if strings.HasPrefix(value, "docker.io/kubeshark") {
|
||||
registry = "docker.io/kubeshark/"
|
||||
} else {
|
||||
registry = value
|
||||
}
|
||||
}
|
||||
|
||||
func GetTag() string {
|
||||
return tag
|
||||
}
|
||||
|
||||
func SetTag(value string) {
|
||||
tag = value
|
||||
}
|
||||
|
||||
func getImage(image string) string {
|
||||
return fmt.Sprintf("%s%s:%s", registry, image, tag)
|
||||
}
|
||||
|
||||
func GetHubImage() string {
|
||||
return getImage(hub)
|
||||
}
|
||||
|
||||
func GetWorkerImage() string {
|
||||
return getImage(worker)
|
||||
}
|
||||
|
||||
func GetFrontImage() string {
|
||||
return getImage(front)
|
||||
}
|
||||
@@ -22,9 +22,9 @@ func FormatError(err error) error {
|
||||
"in the config file or setting the targeted namespace with --%s %s=<NAMEPSACE>",
|
||||
err,
|
||||
misc.Software,
|
||||
configStructs.SelfNamespaceLabel,
|
||||
configStructs.ReleaseNamespaceLabel,
|
||||
config.SetCommandName,
|
||||
configStructs.SelfNamespaceLabel)
|
||||
configStructs.ReleaseNamespaceLabel)
|
||||
} else if syntaxError, isSyntaxError := asRegexSyntaxError(err); isSyntaxError {
|
||||
errorNew = fmt.Errorf("regex %s is invalid: %w", syntaxError.Expr, err)
|
||||
} else {
|
||||
|
||||
189
go.mod
189
go.mod
@@ -1,118 +1,165 @@
|
||||
module github.com/kubeshark/kubeshark
|
||||
|
||||
go 1.17
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/creasty/defaults v1.5.2
|
||||
github.com/docker/docker v20.10.24+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/goccy/go-yaml v1.11.2
|
||||
github.com/google/go-github/v37 v37.0.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/ohler55/ojg v1.14.5
|
||||
github.com/otiai10/copy v1.10.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/robertkrimen/otto v0.2.1
|
||||
github.com/rs/zerolog v1.28.0
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.23.3
|
||||
k8s.io/apimachinery v0.23.3
|
||||
k8s.io/client-go v0.23.3
|
||||
k8s.io/kubectl v0.23.3
|
||||
helm.sh/helm/v3 v3.12.0
|
||||
k8s.io/api v0.28.3
|
||||
k8s.io/apimachinery v0.28.3
|
||||
k8s.io/client-go v0.28.3
|
||||
k8s.io/kubectl v0.28.3
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.2.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.3 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/containerd/containerd v1.7.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/distribution v2.8.0+incompatible // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/docker/cli v20.10.21+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker v20.10.24+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/swag v0.21.1 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.0.5 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.7 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gosuri/uitable v0.0.4 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/russross/blackfriday v1.6.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||
github.com/stretchr/testify v1.8.1 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/rubenv/sql-migrate v1.3.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.8.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
|
||||
google.golang.org/grpc v1.54.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/cli-runtime v0.23.3 // indirect
|
||||
k8s.io/component-base v0.23.3 // indirect
|
||||
k8s.io/klog/v2 v2.40.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf // indirect
|
||||
k8s.io/utils v0.0.0-20220127004650-9b3446523e65 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.11.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.27.1 // indirect
|
||||
k8s.io/apiserver v0.27.1 // indirect
|
||||
k8s.io/cli-runtime v0.28.3 // indirect
|
||||
k8s.io/component-base v0.28.3 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||
oras.land/oras-go v1.2.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
apiVersion: v2
|
||||
appVersion: "40.4"
|
||||
name: kubeshark
|
||||
version: "52.2.30"
|
||||
description: The API Traffic Analyzer for Kubernetes
|
||||
home: https://kubeshark.co
|
||||
keywords:
|
||||
@@ -18,8 +19,7 @@ maintainers:
|
||||
- email: info@kubeshark.co
|
||||
name: Kubeshark
|
||||
url: https://kubeshark.co
|
||||
name: kubeshark
|
||||
sources:
|
||||
- https://github.com/kubeshark/kubeshark/tree/master/helm-chart
|
||||
type: application
|
||||
version: "40.4"
|
||||
icon: https://raw.githubusercontent.com/kubeshark/assets/master/logo/vector/logo.svg
|
||||
|
||||
152
helm-chart/PF_RING.md
Normal file
152
helm-chart/PF_RING.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# PF_RING
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
- [PF\_RING](#pf_ring)
|
||||
- [Overview](#overview)
|
||||
- [Loading PF\_RING module on Kubernetes nodes](#loading-pf_ring-module-on-kubernetes-nodes)
|
||||
- [Pre-built kernel module exists and external egress allowed](#pre-built-kernel-module-exists-and-external-egress-allowed)
|
||||
- [Pre-built kernel module doesn't exist or external egress isn't allowed](#pre-built-kernel-module-doesnt-exist-or-external-egress-isnt-allowed)
|
||||
- [Appendix A: PF\_RING kernel module compilation](#appendix-a-pf_ring-kernel-module-compilation)
|
||||
- [Automated complilation](#automated-complilation)
|
||||
- [Manual compilation](#manual-compilation)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
## Overview
|
||||
|
||||
PF_RING™ is an advanced Linux kernel module and user-space framework designed for high-speed packet processing. It offers a uniform API for packet processing applications, enabling efficient handling of large volumes of network data.
|
||||
|
||||
For comprehensive information on PF_RING™, please visit the [User's Guide]((https://www.ntop.org/guides/pf_ring) and access detailed [API Documentation](http://www.ntop.org/guides/pf_ring_api/files.html).
|
||||
|
||||
## Loading PF_RING module on Kubernetes nodes
|
||||
|
||||
PF_RING kernel module loading is performed via of the `worker` component pod.
|
||||
The target container `tap.kernelModule.image` must contain `pf_ring.ko` file under path `/opt/lib/modules/<kernel version>/pf_ring.ko`.
|
||||
Kubeshark provides ready to use containers with kernel modules for the most popular kernel versions running in different managed clouds.
|
||||
|
||||
Prior to deploying `kubeshark` with PF_RING enabled, it is essential to verify if a PF_RING kernel module is already built for your kernel version.
|
||||
Kubeshark provides additional CLI tool for this purpose - [pf-ring-compiler](https://github.com/kubeshark/pf-ring-compiler).
|
||||
|
||||
Compatibility verification can be done by running:
|
||||
|
||||
```bash
|
||||
pfring-compiler compatibility
|
||||
```
|
||||
|
||||
This command checks for the availability of kernel modules for the kernel versions running across all nodes in the Kubernetes cluster.
|
||||
|
||||
Example output for a compatible cluster:
|
||||
|
||||
```bash
|
||||
Node Kernel Version Supported
|
||||
ip-192-168-77-230.us-west-2.compute.internal 5.10.199-190.747.amzn2.x86_64 true
|
||||
ip-192-168-34-216.us-west-2.compute.internal 5.10.199-190.747.amzn2.x86_64 true
|
||||
|
||||
Cluster is compatible
|
||||
```
|
||||
|
||||
Another option to verify availability of kernel modules is just inspecting available kernel module versions via:
|
||||
|
||||
```bash
|
||||
curl https://api.kubeshark.co/kernel-modules/meta/versions.jso
|
||||
```
|
||||
|
||||
Based on Kubernetes cluster compatibility and external connection capabilities, user has two options:
|
||||
|
||||
1. Use Kubeshark provided container `kubeshark/pf-ring-module`
|
||||
2. Build custom container with required kernel module version.
|
||||
|
||||
### Pre-built kernel module exists and external egress allowed
|
||||
|
||||
In this case no additional configuration required.
|
||||
Kubeshark will load PF_RING kernel module from the default `kubeshark/pf-ring-module:all` container.
|
||||
|
||||
### Pre-built kernel module doesn't exist or external egress isn't allowed
|
||||
|
||||
In this case building custom Docker image is required.
|
||||
|
||||
1. Compile PF_RING kernel module for target version
|
||||
|
||||
Skip if you have `pf_ring.ko` for the target kernel version.
|
||||
Otherwise, follow [Appendix A](#appendix-a-pf_ring-kernel-module-compilation) for details.
|
||||
|
||||
2. Build container
|
||||
|
||||
The same build process Kubeshark has can be reused (follow [pfring-compilier](https://github.com/kubeshark/pf-ring-compiler/tree/main/modules) for details).
|
||||
|
||||
3. Configure Helm values
|
||||
|
||||
```yaml
|
||||
tap:
|
||||
kernelModule:
|
||||
image: <container from stage 2>
|
||||
```
|
||||
|
||||
|
||||
## Appendix A: PF_RING kernel module compilation
|
||||
|
||||
PF_RING kernel module compilation can be completed automatically or manually.
|
||||
|
||||
### Automated complilation
|
||||
|
||||
In case your Kubernetes workers run supported Linux distribution, `kubeshark` CLI can be used to build PF_RING module:
|
||||
|
||||
```bash
|
||||
pfring-compiler compile --target <distro>
|
||||
```
|
||||
|
||||
This command requires:
|
||||
|
||||
- kubectl to be installed and configured with a proper context
|
||||
- egress connection to Internet available
|
||||
|
||||
This command:
|
||||
|
||||
1. Runs Kubernetes job with build container
|
||||
2. Waits for job to be completed
|
||||
3. Downloads `pf-ring-<kernel version>.ko` file into the current folder.
|
||||
4. Cleans up created job.
|
||||
|
||||
Currently supported distros:
|
||||
|
||||
- Ubuntu
|
||||
- RHEL 9
|
||||
- Amazon Linux 2
|
||||
|
||||
### Manual compilation
|
||||
|
||||
The process description is based on Ubuntu 22.04 distribution.
|
||||
|
||||
1. Get terminal access to the node with target kernel version
|
||||
This can be done either via SSH directly to node or with debug container running on the target node:
|
||||
|
||||
```bash
|
||||
kubectl debug node/<target node> -it --attach=true --image=ubuntu:22.04
|
||||
```
|
||||
|
||||
2. Install build tools and kernel headers
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt install -y gcc build-essential make git wget tar gzip
|
||||
apt install -y linux-headers-$(uname -r)
|
||||
```
|
||||
|
||||
3. Download PF_RING source code
|
||||
|
||||
```bash
|
||||
wget https://github.com/ntop/PF_RING/archive/refs/tags/8.4.0.tar.gz
|
||||
tar -xf 8.4.0.tar.gz
|
||||
cd PF_RING-8.4.0/kernel
|
||||
```
|
||||
|
||||
4. Compile the kernel module
|
||||
|
||||
```bash
|
||||
make KERNEL_SRC=/usr/src/linux-headers-$(uname -r)
|
||||
```
|
||||
|
||||
5. Copy `pf_ring.ko` to the local file system.
|
||||
|
||||
Use `scp` or `kubectl cp` depending on type of access(SSH or debug pod).
|
||||
@@ -1,6 +1,6 @@
|
||||
# Helm Chart of Kubeshark
|
||||
|
||||
## Officially
|
||||
## Official
|
||||
|
||||
Add the Helm repo for Kubeshark:
|
||||
|
||||
@@ -14,7 +14,7 @@ then install Kubeshark:
|
||||
helm install kubeshark kubeshark/kubeshark
|
||||
```
|
||||
|
||||
## Locally
|
||||
## Local
|
||||
|
||||
Clone the repo:
|
||||
|
||||
@@ -41,31 +41,206 @@ Uninstall Kubeshark:
|
||||
helm uninstall kubeshark
|
||||
```
|
||||
|
||||
## Accesing
|
||||
## Port-forward
|
||||
|
||||
Do the port forwarding:
|
||||
|
||||
```shell
|
||||
kubectl port-forward -n kubeshark service/kubeshark-hub 8898:80 & \
|
||||
kubectl port-forward -n kubeshark service/kubeshark-front 8899:80
|
||||
kubectl port-forward service/kubeshark-front 8899:80
|
||||
```
|
||||
|
||||
Visit [localhost:8899](http://localhost:8899)
|
||||
|
||||
## Installing with Ingress Enabled
|
||||
|
||||
## Increase the Worker's Storage Limit
|
||||
|
||||
For example, change from the default 500Mi to 5Gi:
|
||||
|
||||
```shell
|
||||
--set tap.storageLimit=5Gi
|
||||
```
|
||||
|
||||
## Add a License
|
||||
|
||||
When it's necessary, you can use:
|
||||
|
||||
```shell
|
||||
--set license=YOUR_LICENSE_GOES_HERE
|
||||
```
|
||||
|
||||
Get your license from Kubeshark's [Admin Console](https://console.kubeshark.co/).
|
||||
|
||||
## Installing with Ingress (EKS) enabled
|
||||
|
||||
```shell
|
||||
helm install kubeshark kubeshark/kubeshark -f values.yaml
|
||||
```
|
||||
|
||||
Set this `value.yaml`:
|
||||
```shell
|
||||
tap:
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "alb"
|
||||
host: ks.example.com
|
||||
tls: []
|
||||
annotations:
|
||||
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:7..8:certificate/b...65c
|
||||
alb.ingress.kubernetes.io/target-type: ip
|
||||
alb.ingress.kubernetes.io/scheme: internet-facing
|
||||
```
|
||||
|
||||
## Disabling IPV6
|
||||
|
||||
Not all have IPV6 enabled, hence this has to be disabled as follows:
|
||||
|
||||
```shell
|
||||
helm install kubeshark kubeshark/kubeshark \
|
||||
--set tap.ingress.enabled=true \
|
||||
--set tap.ingress.host=ks.svc.cluster.local \
|
||||
--set "tap.ingress.auth.approvedDomains={gmail.com}" \
|
||||
--set license=LICENSE_GOES_HERE
|
||||
--set tap.ipv6=false
|
||||
```
|
||||
|
||||
## Installing with Persistent Storage Enabled
|
||||
## Metrics
|
||||
|
||||
Please refer to [metrics](./metrics.md) documentation for details.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------|
|
||||
| `tap.docker.registry` | Docker registry to pull from | `docker.io/kubeshark` |
|
||||
| `tap.docker.tag` | Tag of the Docker images | `latest` |
|
||||
| `tap.docker.imagePullPolicy` | Kubernetes image pull policy | `Always` |
|
||||
| `tap.docker.imagePullSecrets` | Kubernetes secrets to pull the images | `[]` |
|
||||
| `tap.proxy.worker.srvPort` | Worker server port | `30001` |
|
||||
| `tap.proxy.hub.port` | Hub service port | `8898` |
|
||||
| `tap.proxy.hub.srvPort` | Hub server port | `8898` |
|
||||
| `tap.proxy.front.port` | Front-facing service port | `8899` |
|
||||
| `tap.proxy.host` | Proxy server's IP | `127.0.0.1` |
|
||||
| `tap.namespaces` | List of namespaces for the traffic capture | `[]` |
|
||||
| `tap.release.repo` | URL of the Helm chart repository | `https://helm.kubeshark.co` |
|
||||
| `tap.release.name` | Helm release name | `kubeshark` |
|
||||
| `tap.release.namespace` | Helm release namespace | `default` |
|
||||
| `tap.persistentStorage` | Use `persistentVolumeClaim` instead of `emptyDir` | `false` |
|
||||
| `tap.persistentStorageStatic` | Use static persistent volume provisioning (explicitly defined `PersistentVolume` ) | `false` |
|
||||
| `tap.efsFileSytemIdAndPath` | [EFS file system ID and, optionally, subpath and/or access point](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/examples/kubernetes/access_points/README.md) `<FileSystemId>:<Path>:<AccessPointId>` | "" |
|
||||
| `tap.storageLimit` | Limit of either the `emptyDir` or `persistentVolumeClaim` | `500Mi` |
|
||||
| `tap.storageClass` | Storage class of the `PersistentVolumeClaim` | `standard` |
|
||||
| `tap.dryRun` | Preview of all pods matching the regex, without tapping them | `false` |
|
||||
| `tap.pcap` | | `""` |
|
||||
| `tap.resources.worker.limits.cpu` | CPU limit for worker | `750m` |
|
||||
| `tap.resources.worker.limits.memory` | Memory limit for worker | `1Gi` |
|
||||
| `tap.resources.worker.requests.cpu` | CPU request for worker | `50m` |
|
||||
| `tap.resources.worker.requests.memory` | Memory request for worker | `50Mi` |
|
||||
| `tap.resources.hub.limits.cpu` | CPU limit for hub | `750m` |
|
||||
| `tap.resources.hub.limits.memory` | Memory limit for hub | `1Gi` |
|
||||
| `tap.resources.hub.requests.cpu` | CPU request for hub | `50m` |
|
||||
| `tap.resources.hub.requests.memory` | Memory request for hub | `50Mi` |
|
||||
| `tap.serviceMesh` | Capture traffic from service meshes like Istio, Linkerd, Consul, etc. | `true` |
|
||||
| `tap.tls` | Capture the encrypted/TLS traffic from cryptography libraries like OpenSSL | `true` |
|
||||
| `tap.ignoreTainted` | Whether to ignore tainted nodes | `false` |
|
||||
| `tap.labels` | Kubernetes labels to apply to all Kubeshark resources | `{}` |
|
||||
| `tap.annotations` | Kubernetes annotations to apply to all Kubeshark resources | `{}` |
|
||||
| `tap.nodeSelectorTerms` | Node selector terms | `[{"matchExpressions":[{"key":"kubernetes.io/os","operator":"In","values":["linux"]}]}]` |
|
||||
| `tap.auth.enabled` | Enable authentication | `false` |
|
||||
| `tap.auth.type` | Authentication type (1 option available: `saml`) | `saml` |
|
||||
| `tap.auth.approvedEmails` | List of approved email addresses for authentication | `[]` |
|
||||
| `tap.auth.approvedDomains` | List of approved email domains for authentication | `[]` |
|
||||
| `tap.auth.saml.idpMetadataUrl` | SAML IDP metadata URL <br/>(effective, if `tap.auth.type = saml`) | `` |
|
||||
| `tap.auth.saml.x509crt` | A self-signed X.509 `.cert` contents <br/>(effective, if `tap.auth.type = saml`) | `` |
|
||||
| `tap.auth.saml.x509key` | A self-signed X.509 `.key` contents <br/>(effective, if `tap.auth.type = saml`) | `` |
|
||||
| `tap.auth.saml.roleAttribute` | A SAML attribute name corresponding to user's authorization role <br/>(effective, if `tap.auth.type = saml`) | `role` |
|
||||
| `tap.auth.saml.roles` | A list of SAML authorization roles and their permissions <br/>(effective, if `tap.auth.type = saml`) | `{"admin":{"canDownloadPCAP":true,"canReplayTraffic":true,"canUpdateTargetedPods":true,"canUseScripting":true,"filter":"","showAdminConsoleLink":true}}` |
|
||||
| `tap.ingress.enabled` | Enable `Ingress` | `false` |
|
||||
| `tap.ingress.className` | Ingress class name | `""` |
|
||||
| `tap.ingress.host` | Host of the `Ingress` | `ks.svc.cluster.local` |
|
||||
| `tap.ingress.tls` | `Ingress` TLS configuration | `[]` |
|
||||
| `tap.ingress.annotations` | `Ingress` annotations | `{}` |
|
||||
| `tap.ipv6` | Enable IPv6 support for the front-end | `true` |
|
||||
| `tap.debug` | Enable debug mode | `false` |
|
||||
| `tap.kernelModule.enabled` | Use PF_RING kernel module([details](PF_RING.md)) | `true` |
|
||||
| `tap.kernelModule.image` | Container image containing PF_RING kernel module with supported kernel version([details](PF_RING.md)) | "kubeshark/pf-ring-module:all" |
|
||||
| `tap.kernelModule.unloadOnDestroy` | Create additional container which watches for pod termination and unloads PF_RING kernel module. | `false`|
|
||||
| `tap.telemetry.enabled` | Enable anonymous usage statistics collection | `true` |
|
||||
| `tap.defaultFilter` | Sets the default dashboard KFL filter (e.g. `http`) | `""` |
|
||||
| `tap.globalFilter` | Prepends to any KFL filter and can be used to limit what is visible in the dashboard. For example, `redact("request.headers.Authorization")` will redact the appropriate field. | `""` |
|
||||
| `logs.file` | Logs dump path | `""` |
|
||||
| `kube.configPath` | Path to the `kubeconfig` file (`$HOME/.kube/config`) | `""` |
|
||||
| `kube.context` | Kubernetes context to use for the deployment | `""` |
|
||||
| `dumpLogs` | Enable dumping of logs | `false` |
|
||||
| `headless` | Enable running in headless mode | `false` |
|
||||
| `license` | License key for the Pro/Enterprise edition | `""` |
|
||||
| `scripting.env` | Environment variables for the scripting | `{}` |
|
||||
| `scripting.source` | Source directory of the scripts | `""` |
|
||||
| `scripting.watchScripts` | Enable watch mode for the scripts in source directory | `true` |
|
||||
| `tap.metrics.port` | Pod port used to expose Prometheus metrics | `49100` |
|
||||
| `timezone` | IANA time zone applied to time shown in the front-end | `""` (local time zone applies) |
|
||||
|
||||
KernelMapping pairs kernel versions with a
|
||||
DriverContainer image. Kernel versions can be matched
|
||||
literally or using a regular expression
|
||||
|
||||
## Installing with SAML enabled
|
||||
|
||||
### Prerequisites:
|
||||
|
||||
##### 1. Generate X.509 certificate & key (TL;DR: https://ubuntu.com/server/docs/security-certificates)
|
||||
|
||||
**Example:**
|
||||
```
|
||||
openssl genrsa -out mykey.key 2048
|
||||
openssl req -new -key mykey.key -out mycsr.csr
|
||||
openssl x509 -signkey mykey.key -in mycsr.csr -req -days 365 -out mycert.crt
|
||||
```
|
||||
|
||||
**What you get:**
|
||||
- `mycert.crt` - use it for `tap.auth.saml.x509crt`
|
||||
- `mykey.key` - use it for `tap.auth.saml.x509crt`
|
||||
|
||||
##### 2. Prepare your SAML IDP
|
||||
|
||||
You should set up the required SAML IDP (Google, Auth0, your custom IDP, etc.)
|
||||
|
||||
During setup, an IDP provider will typically request to enter:
|
||||
- Metadata URL
|
||||
- ACS URL (Assertion Consumer Service URL, aka Callback URL)
|
||||
- SLO URL (Single Logout URL)
|
||||
|
||||
Correspondingly, you will enter these (if you run the most default Kubeshark setup):
|
||||
- [http://localhost:8899/saml/metadata](http://localhost:8899/saml/metadata)
|
||||
- [http://localhost:8899/saml/acs](http://localhost:8899/saml/acs)
|
||||
- [http://localhost:8899/saml/slo](http://localhost:8899/saml/slo)
|
||||
|
||||
Otherwise, if you have `tap.ingress.enabled == true`, change protocol & domain respectively - showing example domain:
|
||||
- [https://kubeshark.example.com/saml/metadata](https://kubeshark.example.com/saml/metadata)
|
||||
- [https://kubeshark.example.com/saml/acs](https://kubeshark.example.com/saml/acs)
|
||||
- [https://kubeshark.example.com/saml/slo](https://kubeshark.example.com/saml/slo)
|
||||
|
||||
```shell
|
||||
helm install kubeshark kubeshark/kubeshark \
|
||||
--set tap.persistentstorage=true \
|
||||
--set license=LICENSE_GOES_HERE
|
||||
helm install kubeshark kubeshark/kubeshark -f values.yaml
|
||||
```
|
||||
|
||||
Set this `value.yaml`:
|
||||
```shell
|
||||
tap:
|
||||
auth:
|
||||
enabled: true
|
||||
type: saml
|
||||
saml:
|
||||
idpMetadataUrl: "https://tiptophelmet.us.auth0.com/samlp/metadata/MpWiDCMMB5ShU1HRnhdb1sHM6VWqdnDG"
|
||||
x509crt: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDlTCCAn0CFFRUzMh+dZvp+FvWd4gRaiBVN8EvMA0GCSqGSIb3DQEBCwUAMIGG
|
||||
MSQwIgYJKoZIhvcNAQkBFhV3ZWJtYXN0ZXJAZXhhbXBsZS5jb20wHhcNMjMxMjI4
|
||||
........<redacted: please, generate your own X.509 cert>........
|
||||
ZMzM7YscqZwoVhTOhrD4/5nIfOD/hTWG/MBe2Um1V1IYF8aVEllotTKTgsF6ZblA
|
||||
miCOgl6lIlZy
|
||||
-----END CERTIFICATE-----
|
||||
x509key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDlgDFKsRHj+mok
|
||||
euOF0IpwToOEpQGtafB75ytv3psD/tQAzEIug+rkDriVvsfcvafj0qcaTeYvnCoz
|
||||
........<redacted: please, generate your own X.509 key>.........
|
||||
sUpBCu0E3nRJM/QB2ui5KhNR7uvPSL+kSsaEq19/mXqsL+mRi9aqy2wMEvUSU/kt
|
||||
UaV5sbRtTzYLxpOSQyi8CEFA+A==
|
||||
-----END PRIVATE KEY-----
|
||||
```
|
||||
|
||||
55
helm-chart/metrics.md
Normal file
55
helm-chart/metrics.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Metrics
|
||||
|
||||
Kubeshark provides metrics from `worker` components.
|
||||
It can be useful for monitoring and debugging purpose.
|
||||
|
||||
## Configuration
|
||||
|
||||
By default, Kubeshark uses port `49100` to expose metrics via service `kubeshark-worker-metrics`.
|
||||
|
||||
In case you use [kube-prometheus-stack] (https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) community Helm chart, additional scrape configuration for Kubeshark worker metrics endpoint can be configured with values:
|
||||
|
||||
```
|
||||
prometheus:
|
||||
enabled: true
|
||||
prometheusSpec:
|
||||
additionalScrapeConfigs: |
|
||||
- job_name: 'kubeshark-worker-metrics'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
target_label: pod
|
||||
- source_labels: [__meta_kubernetes_pod_node_name]
|
||||
target_label: node
|
||||
- source_labels: [__meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: ^metrics$
|
||||
- source_labels: [__address__, __meta_kubernetes_endpoint_port_number]
|
||||
action: replace
|
||||
regex: ([^:]+)(?::\d+)?
|
||||
replacement: $1:49100
|
||||
target_label: __address__
|
||||
- action: labelmap
|
||||
regex: __meta_kubernetes_service_label_(.+)
|
||||
```
|
||||
|
||||
|
||||
## Available metrics
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| kubeshark_received_packets_total | Counter | Total number of packets received |
|
||||
| kubeshark_dropped_packets_total | Counter | Total number of packets dropped |
|
||||
| kubeshark_processed_bytes_total | Counter | Total number of bytes processed |
|
||||
| kubeshark_tcp_packets_total | Counter | Total number of TCP packets |
|
||||
| kubeshark_dns_packets_total | Counter | Total number of DNS packets |
|
||||
| kubeshark_icmp_packets_total | Counter | Total number of ICMP packets |
|
||||
| kubeshark_reassembled_tcp_payloads_total | Counter | Total number of reassembled TCP payloads |
|
||||
| kubeshark_matched_pairs_total | Counter | Total number of matched pairs |
|
||||
| kubeshark_dropped_tcp_streams_total | Counter | Total number of dropped TCP streams |
|
||||
| kubeshark_live_tcp_streams | Gauge | Number of live TCP streams |
|
||||
|
||||
## Ready-to-use Dashboard
|
||||
|
||||
You can import a ready-to-use dashboard from [Grafana's Dashboards Portal](https://grafana.com/grafana/dashboards/20359-kubeshark-dashboard-v1-0-003/).
|
||||
@@ -1,12 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: '{{ .Values.tap.selfnamespace }}'
|
||||
spec: {}
|
||||
status: {}
|
||||
@@ -1,12 +1,12 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-service-account
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "kubeshark.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
@@ -1,28 +1,61 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-cluster-role
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-cluster-role-{{ .Release.Namespace }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- extensions
|
||||
- apps
|
||||
- networking.k8s.io
|
||||
resources:
|
||||
- pods
|
||||
- services
|
||||
- endpoints
|
||||
- persistentvolumeclaims
|
||||
- ingresses
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
verbs:
|
||||
- get
|
||||
resourceNames:
|
||||
- kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-self-config-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- v1
|
||||
resourceNames:
|
||||
- kubeshark-secret
|
||||
- kubeshark-config-map
|
||||
resources:
|
||||
- secrets
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- update
|
||||
- patch
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-cluster-role-binding
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-cluster-role-binding-{{ .Release.Namespace }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubeshark-cluster-role
|
||||
name: kubeshark-cluster-role-{{ .Release.Namespace }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubeshark-service-account
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
name: {{ include "kubeshark.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-self-config-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: kubeshark-self-config-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubeshark.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
88
helm-chart/templates/04-hub-deployment.yaml
Normal file
88
helm-chart/templates/04-hub-deployment.yaml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "kubeshark.name" . }}-hub
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
replicas: 1 # Set the desired number of replicas
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 8 }}
|
||||
spec:
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: {{ include "kubeshark.serviceAccountName" . }}
|
||||
containers:
|
||||
- name: kubeshark-hub
|
||||
command:
|
||||
- ./hub
|
||||
- -port
|
||||
- "8080"
|
||||
{{- if .Values.tap.debug }}
|
||||
- -debug
|
||||
{{- end }}
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: KUBESHARK_CLOUD_API_URL
|
||||
value: 'https://api.kubeshark.co'
|
||||
image: '{{ .Values.tap.docker.registry }}/hub:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (printf "v%s" .Chart.Version) }}'
|
||||
imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }}
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
resources:
|
||||
limits:
|
||||
cpu: {{ .Values.tap.resources.hub.limits.cpu }}
|
||||
memory: {{ .Values.tap.resources.hub.limits.memory }}
|
||||
requests:
|
||||
cpu: {{ .Values.tap.resources.hub.requests.cpu }}
|
||||
memory: {{ .Values.tap.resources.hub.requests.memory }}
|
||||
volumeMounts:
|
||||
- name: saml-x509-volume
|
||||
mountPath: "/etc/saml/x509"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: saml-x509-volume
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
name: kubeshark-saml-x509-crt-secret
|
||||
items:
|
||||
- key: AUTH_SAML_X509_CRT
|
||||
path: kubeshark.crt
|
||||
- secret:
|
||||
name: kubeshark-saml-x509-key-secret
|
||||
items:
|
||||
- key: AUTH_SAML_X509_KEY
|
||||
path: kubeshark.key
|
||||
@@ -1,51 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-hub
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-hub
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- '{{ .Values.tap.debug | ternary "./hub -debug" "./hub" }}'
|
||||
env:
|
||||
- name: POD_REGEX
|
||||
value: '{{ .Values.tap.regex }}'
|
||||
- name: NAMESPACES
|
||||
value: '{{ gt (len .Values.tap.namespaces) 0 | ternary (join "," .Values.tap.namespaces) "" }}'
|
||||
- name: LICENSE
|
||||
value: '{{ .Values.license }}'
|
||||
- name: SCRIPTING_ENV
|
||||
value: '{}'
|
||||
- name: SCRIPTING_SCRIPTS
|
||||
value: '[]'
|
||||
- name: AUTH_APPROVED_DOMAINS
|
||||
value: '{{ gt (len .Values.tap.ingress.auth.approvedDomains) 0 | ternary (join "," .Values.tap.ingress.auth.approvedDomains) "" }}'
|
||||
image: '{{ .Values.tap.docker.registry }}/hub:{{ .Values.tap.docker.tag }}'
|
||||
imagePullPolicy: '{{ .Values.tap.docker.imagepullpolicy }}'
|
||||
name: kubeshark-hub
|
||||
ports:
|
||||
- containerPort: 80
|
||||
hostPort: {{ .Values.tap.proxy.hub.srvport }}
|
||||
resources:
|
||||
limits:
|
||||
cpu: '{{ .Values.tap.resources.hub.limits.cpu }}'
|
||||
memory: '{{ .Values.tap.resources.hub.limits.memory }}'
|
||||
requests:
|
||||
cpu: '{{ .Values.tap.resources.hub.requests.cpu }}'
|
||||
memory: '{{ .Values.tap.resources.hub.requests.memory }}'
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
status: {}
|
||||
@@ -1,21 +1,21 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-hub
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-hub
|
||||
port: 80
|
||||
targetPort: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: kubeshark-hub
|
||||
type: NodePort
|
||||
status:
|
||||
loadBalancer: {}
|
||||
app.kubeshark.co/app: hub
|
||||
type: ClusterIP
|
||||
|
||||
80
helm-chart/templates/06-front-deployment.yaml
Normal file
80
helm-chart/templates/06-front-deployment.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: front
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "kubeshark.name" . }}-front
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
replicas: 1 # Set the desired number of replicas
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: front
|
||||
{{- include "kubeshark.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: front
|
||||
{{- include "kubeshark.labels" . | nindent 8 }}
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: REACT_APP_DEFAULT_FILTER
|
||||
value: '{{ not (eq .Values.tap.defaultFilter "") | ternary .Values.tap.defaultFilter " " }}'
|
||||
- name: REACT_APP_AUTH_ENABLED
|
||||
value: '{{ .Values.tap.auth.enabled }}'
|
||||
- name: REACT_APP_AUTH_TYPE
|
||||
value: '{{ not (eq .Values.tap.auth.type "") | ternary .Values.tap.auth.type " " }}'
|
||||
- name: REACT_APP_AUTH_SAML_IDP_METADATA_URL
|
||||
value: '{{ not (eq .Values.tap.auth.saml.idpMetadataUrl "") | ternary .Values.tap.auth.saml.idpMetadataUrl " " }}'
|
||||
- name: REACT_APP_TIMEZONE
|
||||
value: '{{ not (eq .Values.timezone "") | ternary .Values.timezone " " }}'
|
||||
- name: REACT_APP_REPLAY_DISABLED
|
||||
value: '{{ .Values.tap.replayDisabled }}'
|
||||
- name: REACT_APP_SCRIPTING_DISABLED
|
||||
value: '{{ .Values.tap.scriptingDisabled }}'
|
||||
- name: REACT_APP_TARGETED_PODS_UPDATE_DISABLED
|
||||
value: '{{ .Values.tap.targetedPodsUpdateDisabled }}'
|
||||
- name: REACT_APP_RECORDING_DISABLED
|
||||
value: '{{ .Values.tap.recordingDisabled }}'
|
||||
image: '{{ .Values.tap.docker.registry }}/front:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (printf "v%s" .Chart.Version) }}'
|
||||
imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }}
|
||||
name: kubeshark-front
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
timeoutSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: kubeshark-nginx-config-map
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: {{ include "kubeshark.serviceAccountName" . }}
|
||||
@@ -1,50 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-front
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-front
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: REACT_APP_DEFAULT_FILTER
|
||||
value: ' '
|
||||
- name: REACT_APP_HUB_HOST
|
||||
value: ' '
|
||||
- name: REACT_APP_HUB_PORT
|
||||
value: '{{ .Values.tap.ingress.enabled | ternary "80/api" "8898" }}'
|
||||
image: '{{ .Values.tap.docker.registry }}/front:{{ .Values.tap.docker.tag }}'
|
||||
imagePullPolicy: '{{ .Values.tap.docker.imagepullpolicy }}'
|
||||
name: kubeshark-front
|
||||
ports:
|
||||
- containerPort: 80
|
||||
hostPort: {{ .Values.tap.proxy.front.srvport }}
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
periodSeconds: 1
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 80
|
||||
timeoutSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
status: {}
|
||||
@@ -1,21 +1,20 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-front
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-front
|
||||
port: 80
|
||||
targetPort: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: kubeshark-front
|
||||
type: NodePort
|
||||
status:
|
||||
loadBalancer: {}
|
||||
app.kubeshark.co/app: front
|
||||
type: ClusterIP
|
||||
|
||||
@@ -1,22 +1,43 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
{{- if .Values.tap.persistentstorage }}
|
||||
{{- if .Values.tap.persistentStorageStatic }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: kubeshark-persistent-volume
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
capacity:
|
||||
storage: {{ .Values.tap.storageLimit }}
|
||||
volumeMode: Filesystem
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: {{ .Values.tap.storageClass }}
|
||||
{{- if .Values.tap.efsFileSytemIdAndPath }}
|
||||
csi:
|
||||
driver: efs.csi.aws.com
|
||||
volumeHandle: {{ .Values.tap.efsFileSytemIdAndPath }}
|
||||
{{ end }}
|
||||
---
|
||||
{{ end }}
|
||||
{{- if .Values.tap.persistentStorage }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-persistent-volume-claim
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: '{{ .Values.tap.storagelimit }}'
|
||||
storageClassName: '{{ .Values.tap.storageclass }}'
|
||||
storage: {{ .Values.tap.storageLimit }}
|
||||
storageClassName: {{ .Values.tap.storageClass }}
|
||||
status: {}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,66 +1,190 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
app.kubeshark.co/app: worker
|
||||
sidecar.istio.io/inject: "false"
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
app.kubeshark.co/app: worker
|
||||
{{- include "kubeshark.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
app.kubeshark.co/app: worker
|
||||
{{- include "kubeshark.labels" . | nindent 8 }}
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
{{- if .Values.tap.kernelModule.enabled }}
|
||||
initContainers:
|
||||
- name: load-pf-ring
|
||||
image: {{ .Values.tap.kernelModule.image }}
|
||||
imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }}
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
{{- range .Values.tap.capabilities.kernelModule }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
{{- end }}
|
||||
containers:
|
||||
- command:
|
||||
- '{{ .Values.tap.debug | ternary "./worker -debug" "./worker" }}'
|
||||
- ./worker
|
||||
- -i
|
||||
- any
|
||||
- -port
|
||||
- '{{ .Values.tap.proxy.worker.srvport }}'
|
||||
- '{{ .Values.tap.proxy.worker.srvPort }}'
|
||||
- -metrics-port
|
||||
- '{{ .Values.tap.metrics.port }}'
|
||||
- -packet-capture
|
||||
- '{{ .Values.tap.packetcapture }}'
|
||||
- '{{ .Values.tap.packetCapture }}'
|
||||
- -unixsocket
|
||||
{{- if .Values.tap.serviceMesh }}
|
||||
- -servicemesh
|
||||
- -tls
|
||||
{{- end }}
|
||||
- -procfs
|
||||
- /hostproc
|
||||
image: '{{ .Values.tap.docker.registry }}/worker:{{ .Values.tap.docker.tag }}'
|
||||
imagePullPolicy: '{{ .Values.tap.docker.imagepullpolicy }}'
|
||||
name: kubeshark-worker-daemon-set
|
||||
{{- if .Values.tap.kernelModule.enabled }}
|
||||
- -kernel-module
|
||||
{{- end }}
|
||||
{{- if ne .Values.tap.packetCapture "ebpf" }}
|
||||
- -disable-ebpf
|
||||
{{- end }}
|
||||
{{- if .Values.tap.debug }}
|
||||
- -debug
|
||||
- -dumptracer
|
||||
- "100000000"
|
||||
{{- end }}
|
||||
image: '{{ .Values.tap.docker.registry }}/worker:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (printf "v%s" .Chart.Version) }}'
|
||||
imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }}
|
||||
name: sniffer
|
||||
ports:
|
||||
- containerPort: {{ .Values.tap.proxy.worker.srvport }}
|
||||
hostPort: {{ .Values.tap.proxy.worker.srvport }}
|
||||
- containerPort: {{ .Values.tap.metrics.port }}
|
||||
protocol: TCP
|
||||
name: metrics
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: TCP_STREAM_CHANNEL_TIMEOUT_MS
|
||||
value: '{{ .Values.tap.misc.tcpStreamChannelTimeoutMs }}'
|
||||
- name: TCP_STREAM_CHANNEL_TIMEOUT_SHOW
|
||||
value: '{{ .Values.tap.misc.tcpStreamChannelTimeoutShow }}'
|
||||
- name: KUBESHARK_CLOUD_API_URL
|
||||
value: 'https://api.kubeshark.co'
|
||||
resources:
|
||||
limits:
|
||||
cpu: '{{ .Values.tap.resources.worker.limits.cpu }}'
|
||||
memory: '{{ .Values.tap.resources.worker.limits.memory }}'
|
||||
cpu: {{ .Values.tap.resources.sniffer.limits.cpu }}
|
||||
memory: {{ .Values.tap.resources.sniffer.limits.memory }}
|
||||
requests:
|
||||
cpu: '{{ .Values.tap.resources.worker.requests.cpu }}'
|
||||
memory: '{{ .Values.tap.resources.worker.requests.memory }}'
|
||||
cpu: {{ .Values.tap.resources.sniffer.requests.cpu }}
|
||||
memory: {{ .Values.tap.resources.sniffer.requests.memory }}
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- DAC_OVERRIDE
|
||||
- SYS_RESOURCE
|
||||
{{- range .Values.tap.capabilities.networkCapture }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
{{- if .Values.tap.serviceMesh }}
|
||||
{{- range .Values.tap.capabilities.serviceMeshCapture }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
drop:
|
||||
- ALL
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 5
|
||||
tcpSocket:
|
||||
port: {{ .Values.tap.proxy.worker.srvPort }}
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 5
|
||||
tcpSocket:
|
||||
port: {{ .Values.tap.proxy.worker.srvPort }}
|
||||
volumeMounts:
|
||||
- mountPath: /hostproc
|
||||
name: proc
|
||||
readOnly: true
|
||||
- mountPath: /sys
|
||||
name: sys
|
||||
readOnly: true
|
||||
- mountPath: /app/data
|
||||
name: data
|
||||
{{- if and (eq .Values.tap.kernelModule.enabled true) (eq .Values.tap.kernelModule.unloadOnDestroy true) }}
|
||||
- name: unload-pf-ring
|
||||
image: {{ .Values.tap.kernelModule.image }}
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "trap 'rmmod pf_ring && sleep 3' SIGTERM; while true; do sleep 1; done"]
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
{{- range .Values.tap.capabilities.kernelModule }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
drop:
|
||||
- ALL
|
||||
{{- end }}
|
||||
{{- if .Values.tap.tls }}
|
||||
- command:
|
||||
- ./tracer
|
||||
- -procfs
|
||||
- /hostproc
|
||||
{{- if .Values.tap.debug }}
|
||||
- -debug
|
||||
{{- end }}
|
||||
image: '{{ .Values.tap.docker.registry }}/worker:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (printf "v%s" .Chart.Version) }}'
|
||||
imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }}
|
||||
name: tracer
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
resources:
|
||||
limits:
|
||||
cpu: {{ .Values.tap.resources.tracer.limits.cpu }}
|
||||
memory: {{ .Values.tap.resources.tracer.limits.memory }}
|
||||
requests:
|
||||
cpu: {{ .Values.tap.resources.tracer.requests.cpu }}
|
||||
memory: {{ .Values.tap.resources.tracer.requests.memory }}
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
{{- range .Values.tap.capabilities.ebpfCapture }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
{{- range .Values.tap.capabilities.networkCapture }}
|
||||
{{ print "- " . }}
|
||||
{{- end }}
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
@@ -70,19 +194,27 @@ spec:
|
||||
- mountPath: /sys
|
||||
name: sys
|
||||
readOnly: true
|
||||
{{- if .Values.tap.persistentstorage }}
|
||||
- mountPath: /app/data
|
||||
name: kubeshark-persistent-volume
|
||||
{{- end }}
|
||||
name: data
|
||||
{{- end }}
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
serviceAccountName: kubeshark-service-account
|
||||
serviceAccountName: {{ include "kubeshark.serviceAccountName" . }}
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
{{- if not .Values.tap.ignoreTainted }}
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
{{- end }}
|
||||
{{- if gt (len .Values.tap.nodeSelectorTerms) 0}}
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
{{- toYaml .Values.tap.nodeSelectorTerms | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /proc
|
||||
@@ -90,8 +222,14 @@ spec:
|
||||
- hostPath:
|
||||
path: /sys
|
||||
name: sys
|
||||
{{- if .Values.tap.persistentstorage }}
|
||||
- name: kubeshark-persistent-volume
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
- name: data
|
||||
{{- if .Values.tap.persistentStorage }}
|
||||
persistentVolumeClaim:
|
||||
claimName: kubeshark-persistent-volume-claim
|
||||
{{- else }}
|
||||
emptyDir:
|
||||
sizeLimit: {{ .Values.tap.storageLimit }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
{{- if .Values.tap.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: IngressClass
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-ingress-class
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
spec:
|
||||
controller: k8s.io/ingress-nginx
|
||||
{{- end }}
|
||||
39
helm-chart/templates/10-ingress.yaml
Normal file
39
helm-chart/templates/10-ingress.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
{{- if .Values.tap.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
nginx.org/websocket-services: "kubeshark-front"
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.tap.ingress.annotations }}
|
||||
{{- toYaml .Values.tap.ingress.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
name: kubeshark-ingress
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
{{- if .Values.tap.ingress.className }}
|
||||
ingressClassName: {{ .Values.tap.ingress.className }}
|
||||
{{- end }}
|
||||
rules:
|
||||
- host: {{ .Values.tap.ingress.host }}
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: kubeshark-front
|
||||
port:
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
||||
{{- if .Values.tap.ingress.tls }}
|
||||
tls:
|
||||
{{- toYaml .Values.tap.ingress.tls | nindent 2 }}
|
||||
{{- end }}
|
||||
status:
|
||||
loadBalancer: {}
|
||||
{{- end }}
|
||||
@@ -1,40 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
{{- if .Values.tap.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
certmanager.k8s.io/cluster-issuer: '{{ .Values.tap.ingress.certManager }}'
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /$2
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-ingress
|
||||
namespace: '{{ .Values.tap.selfnamespace }}'
|
||||
spec:
|
||||
ingressClassName: kubeshark-ingress-class
|
||||
rules:
|
||||
- host: '{{ .Values.tap.ingress.host }}'
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: kubeshark-hub
|
||||
port:
|
||||
number: 80
|
||||
path: /api(/|$)(.*)
|
||||
pathType: Prefix
|
||||
- backend:
|
||||
service:
|
||||
name: kubeshark-front
|
||||
port:
|
||||
number: 80
|
||||
path: /()(.*)
|
||||
pathType: Prefix
|
||||
tls: {{ .Values.tap.ingress.tls | toYaml }}
|
||||
status:
|
||||
loadBalancer: {}
|
||||
{{- end }}
|
||||
61
helm-chart/templates/11-nginx-config-map.yaml
Normal file
61
helm-chart/templates/11-nginx-config-map.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kubeshark-nginx-config-map
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
data:
|
||||
default.conf: |
|
||||
server {
|
||||
listen 8080;
|
||||
{{- if .Values.tap.ipv6 }}
|
||||
listen [::]:8080;
|
||||
{{- end }}
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stdout;
|
||||
|
||||
client_body_buffer_size 64k;
|
||||
client_header_buffer_size 32k;
|
||||
large_client_header_buffers 8 64k;
|
||||
|
||||
location /api {
|
||||
rewrite ^/api(.*)$ $1 break;
|
||||
proxy_pass http://kubeshark-hub;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade websocket;
|
||||
proxy_set_header Connection Upgrade;
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
proxy_pass_header Authorization;
|
||||
proxy_connect_timeout 4s;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 12s;
|
||||
proxy_pass_request_headers on;
|
||||
}
|
||||
|
||||
location /saml {
|
||||
rewrite ^/saml(.*)$ /saml$1 break;
|
||||
proxy_pass http://kubeshark-hub;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_connect_timeout 4s;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 12s;
|
||||
proxy_pass_request_headers on;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
expires -1;
|
||||
add_header Cache-Control no-cache;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
|
||||
31
helm-chart/templates/12-config-map.yaml
Normal file
31
helm-chart/templates/12-config-map.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-config-map
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
data:
|
||||
POD_REGEX: '{{ .Values.tap.regex }}'
|
||||
NAMESPACES: '{{ gt (len .Values.tap.namespaces) 0 | ternary (join "," .Values.tap.namespaces) "" }}'
|
||||
SCRIPTING_SCRIPTS: '{}'
|
||||
INGRESS_ENABLED: '{{ .Values.tap.ingress.enabled }}'
|
||||
INGRESS_HOST: '{{ .Values.tap.ingress.host }}'
|
||||
PROXY_FRONT_PORT: '{{ .Values.tap.proxy.front.port }}'
|
||||
AUTH_ENABLED: '{{ .Values.tap.auth.enabled | ternary "true" "" }}'
|
||||
AUTH_TYPE: '{{ .Values.tap.auth.type }}'
|
||||
AUTH_SAML_IDP_METADATA_URL: '{{ .Values.tap.auth.saml.idpMetadataUrl }}'
|
||||
AUTH_SAML_ROLE_ATTRIBUTE: '{{ .Values.tap.auth.saml.roleAttribute }}'
|
||||
AUTH_SAML_ROLES: '{{ .Values.tap.auth.saml.roles | toJson }}'
|
||||
TELEMETRY_DISABLED: '{{ not .Values.tap.telemetry.enabled | ternary "true" "" }}'
|
||||
REPLAY_DISABLED: '{{ .Values.tap.replayDisabled | ternary "true" "" }}'
|
||||
SCRIPTING_DISABLED: '{{ .Values.tap.scriptingDisabled | ternary "true" "" }}'
|
||||
TARGETED_PODS_UPDATE_DISABLED: '{{ .Values.tap.targetedPodsUpdateDisabled | ternary "true" "" }}'
|
||||
RECORDING_DISABLED: '{{ .Values.tap.recordingDisabled | ternary "true" "" }}'
|
||||
GLOBAL_FILTER: {{ include "kubeshark.escapeDoubleQuotes" .Values.tap.globalFilter | quote }}
|
||||
TRAFFIC_SAMPLE_RATE: '{{ .Values.tap.misc.trafficSampleRate }}'
|
||||
JSON_TTL: '{{ .Values.tap.misc.jsonTTL }}'
|
||||
PCAP_TTL: '{{ .Values.tap.misc.pcapTTL }}'
|
||||
PCAP_ERROR_TTL: '{{ .Values.tap.misc.pcapErrorTTL }}'
|
||||
TIMEZONE: '{{ not (eq .Values.timezone "") | ternary .Values.timezone " " }}'
|
||||
41
helm-chart/templates/13-secret.yaml
Normal file
41
helm-chart/templates/13-secret.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-secret
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
stringData:
|
||||
LICENSE: '{{ .Values.license }}'
|
||||
SCRIPTING_ENV: '{{ .Values.scripting.env | toJson }}'
|
||||
|
||||
---
|
||||
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-saml-x509-crt-secret
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
stringData:
|
||||
AUTH_SAML_X509_CRT: |
|
||||
{{ .Values.tap.auth.saml.x509crt | nindent 4 }}
|
||||
|
||||
---
|
||||
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-saml-x509-key-secret
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
stringData:
|
||||
AUTH_SAML_X509_KEY: |
|
||||
{{ .Values.tap.auth.saml.x509key | nindent 4 }}
|
||||
|
||||
---
|
||||
@@ -0,0 +1,52 @@
|
||||
{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" }}
|
||||
apiVersion: security.openshift.io/v1
|
||||
kind: SecurityContextConstraints
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
{{- if .Values.tap.annotations }}
|
||||
{{- toYaml .Values.tap.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
name: kubeshark-scc
|
||||
priority: 10
|
||||
allowPrivilegedContainer: true
|
||||
allowHostDirVolumePlugin: true
|
||||
allowHostNetwork: true
|
||||
allowHostPorts: true
|
||||
allowHostPID: true
|
||||
allowHostIPC: true
|
||||
readOnlyRootFilesystem: false
|
||||
requiredDropCapabilities:
|
||||
- MKNOD
|
||||
allowedCapabilities:
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- DAC_OVERRIDE
|
||||
- SYS_RESOURCE
|
||||
- SYS_MODULE
|
||||
runAsUser:
|
||||
type: RunAsAny
|
||||
fsGroup:
|
||||
type: MustRunAs
|
||||
seLinuxContext:
|
||||
type: RunAsAny
|
||||
supplementalGroups:
|
||||
type: RunAsAny
|
||||
seccompProfiles:
|
||||
- '*'
|
||||
volumes:
|
||||
- configMap
|
||||
- downwardAPI
|
||||
- emptyDir
|
||||
- persistentVolumeClaim
|
||||
- secret
|
||||
- hostPath
|
||||
- projected
|
||||
- ephemeral
|
||||
users:
|
||||
- system:serviceaccount:{{ .Release.Namespace }}:kubeshark-service-account
|
||||
{{- end }}
|
||||
18
helm-chart/templates/15-worker-service-metrics.yaml
Normal file
18
helm-chart/templates/15-worker-service-metrics.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-worker-metrics
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations:
|
||||
prometheus.io/scrape: 'true'
|
||||
prometheus.io/port: '{{ .Values.tap.metrics.port }}'
|
||||
spec:
|
||||
selector:
|
||||
app.kubeshark.co/app: worker
|
||||
{{- include "kubeshark.labels" . | nindent 4 }}
|
||||
ports:
|
||||
- name: metrics
|
||||
protocol: TCP
|
||||
port: {{ .Values.tap.metrics.port }}
|
||||
targetPort: {{ .Values.tap.metrics.port }}
|
||||
58
helm-chart/templates/16-network-policies.yaml
Normal file
58
helm-chart/templates/16-network-policies.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-hub-network-policy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: hub
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- {}
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-front-network-policy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: front
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- {}
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-worker-network-policy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: worker
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: {{ .Values.tap.proxy.worker.srvPort }}
|
||||
- protocol: TCP
|
||||
port: {{ .Values.tap.metrics.port }}
|
||||
egress:
|
||||
- {}
|
||||
27
helm-chart/templates/NOTES.txt
Normal file
27
helm-chart/templates/NOTES.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Thank you for installing {{ title .Chart.Name }}.
|
||||
|
||||
Registry: {{ .Values.tap.docker.registry }}
|
||||
Tag: {{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (printf "v%s" .Chart.Version) }}
|
||||
|
||||
Your deployment has been successful. The release is named `{{ .Release.Name }}` and it has been deployed in the `{{ .Release.Namespace }}` namespace.
|
||||
|
||||
{{- if .Values.tap.telemetry.enabled }}
|
||||
Notice: Telemetry is enabled. Kubeshark will collect anonymous usage statistics.
|
||||
{{ end }}
|
||||
|
||||
{{- if .Values.tap.ingress.enabled }}
|
||||
|
||||
You can now access the application through the following URL:
|
||||
http{{ if .Values.tap.ingress.tls }}s{{ end }}://{{ .Values.tap.ingress.host }}
|
||||
|
||||
{{- else }}
|
||||
To access the application, follow these steps:
|
||||
|
||||
1. Perform port forwarding with the following commands:
|
||||
|
||||
kubectl port-forward -n {{ .Release.Namespace }} service/kubeshark-front 8899:80
|
||||
|
||||
2. Once port forwarding is done, you can access the application by visiting the following URL in your web browser:
|
||||
http://0.0.0.0:8899
|
||||
|
||||
{{ end }}
|
||||
58
helm-chart/templates/_helpers.tpl
Normal file
58
helm-chart/templates/_helpers.tpl
Normal file
@@ -0,0 +1,58 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "kubeshark.name" -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "kubeshark.fullname" -}}
|
||||
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "kubeshark.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "kubeshark.labels" -}}
|
||||
helm.sh/chart: {{ include "kubeshark.chart" . }}
|
||||
{{ include "kubeshark.selectorLabels" . }}
|
||||
app.kubernetes.io/version: {{ .Chart.Version | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- if .Values.tap.labels }}
|
||||
{{ toYaml .Values.tap.labels }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "kubeshark.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "kubeshark.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "kubeshark.serviceAccountName" -}}
|
||||
{{- printf "%s-service-account" .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Escape double quotes in a string
|
||||
*/}}
|
||||
{{- define "kubeshark.escapeDoubleQuotes" -}}
|
||||
{{- regexReplaceAll "\"" . "\"" -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
tap:
|
||||
docker:
|
||||
registry: docker.io/kubeshark
|
||||
tag: latest
|
||||
imagepullpolicy: Always
|
||||
imagepullsecrets: []
|
||||
tag: ""
|
||||
imagePullPolicy: Always
|
||||
imagePullSecrets: []
|
||||
proxy:
|
||||
worker:
|
||||
srvport: 8897
|
||||
srvPort: 30001
|
||||
hub:
|
||||
port: 8898
|
||||
srvport: 8898
|
||||
srvPort: 8898
|
||||
front:
|
||||
port: 8899
|
||||
srvport: 8899
|
||||
host: 127.0.0.1
|
||||
regex: .*
|
||||
namespaces: []
|
||||
selfnamespace: kubeshark
|
||||
persistentstorage: false
|
||||
storagelimit: 200Mi
|
||||
storageclass: standard
|
||||
dryrun: false
|
||||
pcap: ""
|
||||
release:
|
||||
repo: https://helm.kubeshark.co
|
||||
name: kubeshark
|
||||
namespace: default
|
||||
persistentStorage: false
|
||||
persistentStorageStatic: false
|
||||
efsFileSytemIdAndPath: ""
|
||||
storageLimit: 500Mi
|
||||
storageClass: standard
|
||||
dryRun: false
|
||||
resources:
|
||||
worker:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
hub:
|
||||
limits:
|
||||
cpu: 750m
|
||||
@@ -37,29 +32,102 @@ tap:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
servicemesh: true
|
||||
sniffer:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
tracer:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
serviceMesh: true
|
||||
tls: true
|
||||
packetcapture: libpcap
|
||||
packetCapture: best
|
||||
ignoreTainted: false
|
||||
resourceLabels: {}
|
||||
nodeSelectorTerms: []
|
||||
labels: {}
|
||||
annotations: {}
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/os
|
||||
operator: In
|
||||
values:
|
||||
- linux
|
||||
auth:
|
||||
enabled: false
|
||||
type: saml
|
||||
saml:
|
||||
idpMetadataUrl: ""
|
||||
x509crt: ""
|
||||
x509key: ""
|
||||
roleAttribute: role
|
||||
roles:
|
||||
admin:
|
||||
filter: ""
|
||||
canReplayTraffic: true
|
||||
canDownloadPCAP: true
|
||||
canUseScripting: true
|
||||
canUpdateTargetedPods: true
|
||||
showAdminConsoleLink: true
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
host: ks.svc.cluster.local
|
||||
tls: []
|
||||
auth:
|
||||
approvedDomains: []
|
||||
certManager: letsencrypt-prod
|
||||
annotations: {}
|
||||
ipv6: true
|
||||
debug: false
|
||||
kernelModule:
|
||||
enabled: true
|
||||
image: kubeshark/pf-ring-module:all
|
||||
unloadOnDestroy: false
|
||||
telemetry:
|
||||
enabled: true
|
||||
defaultFilter: ""
|
||||
replayDisabled: false
|
||||
scriptingDisabled: false
|
||||
targetedPodsUpdateDisabled: false
|
||||
recordingDisabled: false
|
||||
capabilities:
|
||||
networkCapture:
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
serviceMeshCapture:
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- DAC_OVERRIDE
|
||||
kernelModule:
|
||||
- SYS_MODULE
|
||||
ebpfCapture:
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- SYS_RESOURCE
|
||||
- IPC_LOCK
|
||||
globalFilter: ""
|
||||
metrics:
|
||||
port: 49100
|
||||
misc:
|
||||
jsonTTL: 5m
|
||||
pcapTTL: 10s
|
||||
pcapErrorTTL: 60s
|
||||
trafficSampleRate: 100
|
||||
tcpStreamChannelTimeoutMs: 10000
|
||||
tcpStreamChannelTimeoutShow: false
|
||||
logs:
|
||||
file: ""
|
||||
kube:
|
||||
configpath: ""
|
||||
configPath: ""
|
||||
context: ""
|
||||
dumplogs: false
|
||||
dumpLogs: false
|
||||
headless: false
|
||||
license: ""
|
||||
scripting:
|
||||
env: {}
|
||||
source: ""
|
||||
watchScripts: true
|
||||
timezone: ""
|
||||
|
||||
94
install.sh
Normal file
94
install.sh
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
|
||||
EXE_NAME=kubeshark
|
||||
ALIAS_NAME=ks
|
||||
PROG_NAME=Kubeshark
|
||||
INSTALL_PATH=/usr/local/bin/$EXE_NAME
|
||||
ALIAS_PATH=/usr/local/bin/$ALIAS_NAME
|
||||
REPO=https://github.com/kubeshark/kubeshark
|
||||
OS=$(echo $(uname -s) | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(echo $(uname -m) | tr '[:upper:]' '[:lower:]')
|
||||
SUPPORTED_PAIRS="linux_amd64 linux_arm64 darwin_amd64 darwin_arm64"
|
||||
|
||||
ESC="\033["
|
||||
F_DEFAULT=39
|
||||
F_RED=31
|
||||
F_GREEN=32
|
||||
F_YELLOW=33
|
||||
B_DEFAULT=49
|
||||
B_RED=41
|
||||
B_BLUE=44
|
||||
B_LIGHT_BLUE=104
|
||||
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
ARCH="amd64"
|
||||
fi
|
||||
|
||||
if [ "$ARCH" = "aarch64" ]; then
|
||||
ARCH="arm64"
|
||||
fi
|
||||
|
||||
echo $SUPPORTED_PAIRS | grep -w -q "${OS}_${ARCH}"
|
||||
|
||||
if [ $? != 0 ] ; then
|
||||
echo "\n${ESC}${F_RED}m🛑 Unsupported OS \"$OS\" or architecture \"$ARCH\". Failed to install $PROG_NAME.${ESC}${F_DEFAULT}m"
|
||||
echo "${ESC}${B_RED}mPlease report 🐛 to $REPO/issues${ESC}${F_DEFAULT}m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for Homebrew and kubeshark installation
|
||||
if command -v brew >/dev/null; then
|
||||
if brew list kubeshark &>/dev/null; then
|
||||
echo "📦 Found $PROG_NAME instance installed with Homebrew"
|
||||
echo "${ESC}${F_GREEN}m⬇️ Removing before installation with script${ESC}${F_DEFAULT}m"
|
||||
brew uninstall kubeshark
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "\n🦈 ${ESC}${F_DEFAULT};${B_BLUE}m Started to download $PROG_NAME ${ESC}${B_DEFAULT};${F_DEFAULT}m"
|
||||
|
||||
if curl -# --fail -Lo $EXE_NAME ${REPO}/releases/latest/download/${EXE_NAME}_${OS}_${ARCH} ; then
|
||||
chmod +x $PWD/$EXE_NAME
|
||||
echo "\n${ESC}${F_GREEN}m⬇️ $PROG_NAME is downloaded into $PWD/$EXE_NAME${ESC}${F_DEFAULT}m"
|
||||
else
|
||||
echo "\n${ESC}${F_RED}m🛑 Couldn't download ${REPO}/releases/latest/download/${EXE_NAME}_${OS}_${ARCH}\n\
|
||||
⚠️ Check your internet connection.\n\
|
||||
⚠️ Make sure 'curl' command is available.\n\
|
||||
⚠️ Make sure there is no directory named '${EXE_NAME}' in ${PWD}\n\
|
||||
${ESC}${F_DEFAULT}m"
|
||||
echo "${ESC}${B_RED}mPlease report 🐛 to $REPO/issues${ESC}${F_DEFAULT}m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
use_cmd=$EXE_NAME
|
||||
printf "Do you want to install system-wide? Requires sudo 😇 (y/N)? "
|
||||
old_stty_cfg=$(stty -g)
|
||||
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg
|
||||
if echo "$answer" | grep -iq "^y" ;then
|
||||
echo "$answer"
|
||||
sudo mv ./$EXE_NAME $INSTALL_PATH || exit 1
|
||||
echo "${ESC}${F_GREEN}m$PROG_NAME is installed into $INSTALL_PATH${ESC}${F_DEFAULT}m\n"
|
||||
|
||||
ls $ALIAS_PATH >> /dev/null 2>&1
|
||||
if [ $? != 0 ] ; then
|
||||
printf "Do you want to add 'ks' alias for Kubeshark? (y/N)? "
|
||||
old_stty_cfg=$(stty -g)
|
||||
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg
|
||||
if echo "$answer" | grep -iq "^y" ; then
|
||||
echo "$answer"
|
||||
sudo ln -s $INSTALL_PATH $ALIAS_PATH
|
||||
|
||||
use_cmd=$ALIAS_NAME
|
||||
else
|
||||
echo "$answer"
|
||||
fi
|
||||
else
|
||||
use_cmd=$ALIAS_NAME
|
||||
fi
|
||||
else
|
||||
echo "$answer"
|
||||
use_cmd="./$EXE_NAME"
|
||||
fi
|
||||
|
||||
echo "${ESC}${F_GREEN}m✅ You can use the ${ESC}${F_DEFAULT};${B_LIGHT_BLUE}m $use_cmd ${ESC}${B_DEFAULT};${F_GREEN}m command now.${ESC}${F_DEFAULT}m"
|
||||
echo "\n${ESC}${F_YELLOW}mPlease give us a star 🌟 on ${ESC}${F_DEFAULT}m$REPO${ESC}${F_YELLOW}m if you ❤️ $PROG_NAME!${ESC}${F_DEFAULT}m"
|
||||
@@ -5,10 +5,13 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
|
||||
@@ -73,7 +76,7 @@ func (connector *Connector) PostWorkerPodToHub(pod *v1.Pod) {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postWorkerUrl, "application/json", bytes.NewBuffer(podMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if resp, err = utils.Post(postWorkerUrl, "application/json", bytes.NewBuffer(podMarshalled), connector.client, config.Config.License); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
@@ -87,39 +90,6 @@ func (connector *Connector) PostWorkerPodToHub(pod *v1.Pod) {
|
||||
}
|
||||
}
|
||||
|
||||
type postRegexRequest struct {
|
||||
Regex string `json:"regex"`
|
||||
Namespaces []string `json:"namespaces"`
|
||||
}
|
||||
|
||||
func (connector *Connector) PostRegexToHub(regex string, namespaces []string) {
|
||||
postRegexUrl := fmt.Sprintf("%s/pods/regex", connector.url)
|
||||
|
||||
payload := postRegexRequest{
|
||||
Regex: regex,
|
||||
Namespaces: namespaces,
|
||||
}
|
||||
|
||||
if payloadMarshalled, err := json.Marshal(payload); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal the pod regex:")
|
||||
} else {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postRegexUrl, "application/json", bytes.NewBuffer(payloadMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
log.Warn().Err(err).Msg("Failed sending the pod regex to Hub. Retrying...")
|
||||
} else {
|
||||
log.Debug().Str("regex", regex).Strs("namespaces", namespaces).Msg("Reported pod regex to Hub:")
|
||||
return
|
||||
}
|
||||
time.Sleep(DefaultSleep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type postLicenseRequest struct {
|
||||
License string `json:"license"`
|
||||
}
|
||||
@@ -137,7 +107,7 @@ func (connector *Connector) PostLicense(license string) {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postLicenseUrl, "application/json", bytes.NewBuffer(payloadMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if resp, err = utils.Post(postLicenseUrl, "application/json", bytes.NewBuffer(payloadMarshalled), connector.client, config.Config.License); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
@@ -151,64 +121,27 @@ func (connector *Connector) PostLicense(license string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (connector *Connector) PostLicenseSingle(license string) {
|
||||
postLicenseUrl := fmt.Sprintf("%s/license", connector.url)
|
||||
|
||||
payload := postLicenseRequest{
|
||||
License: license,
|
||||
}
|
||||
|
||||
if payloadMarshalled, err := json.Marshal(payload); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal the payload:")
|
||||
} else {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postLicenseUrl, "application/json", bytes.NewBuffer(payloadMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
log.Warn().Err(err).Msg("Failed sending the license to Hub.")
|
||||
} else {
|
||||
log.Debug().Str("license", license).Msg("Reported license to Hub:")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (connector *Connector) PostEnv(env map[string]interface{}) {
|
||||
if len(env) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
postEnvUrl := fmt.Sprintf("%s/scripts/env", connector.url)
|
||||
|
||||
if envMarshalled, err := json.Marshal(env); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal the env:")
|
||||
} else {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postEnvUrl, "application/json", bytes.NewBuffer(envMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
log.Warn().Err(err).Msg("Failed sending the scripting environment variables to Hub. Retrying...")
|
||||
} else {
|
||||
log.Debug().Interface("env", env).Msg("Reported scripting environment variables to Hub:")
|
||||
return
|
||||
}
|
||||
time.Sleep(DefaultSleep)
|
||||
}
|
||||
}
|
||||
type postScriptRequest struct {
|
||||
Title string `json:"title"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func (connector *Connector) PostScript(script *misc.Script) (index int64, err error) {
|
||||
postScriptUrl := fmt.Sprintf("%s/scripts", connector.url)
|
||||
|
||||
payload := postScriptRequest{
|
||||
Title: script.Title,
|
||||
Code: script.Code,
|
||||
}
|
||||
|
||||
var scriptMarshalled []byte
|
||||
if scriptMarshalled, err = json.Marshal(script); err != nil {
|
||||
if scriptMarshalled, err = json.Marshal(payload); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal the script:")
|
||||
} else {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postScriptUrl, "application/json", bytes.NewBuffer(scriptMarshalled), connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if resp, err = utils.Post(postScriptUrl, "application/json", bytes.NewBuffer(scriptMarshalled), connector.client, config.Config.License); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
@@ -257,6 +190,7 @@ func (connector *Connector) PutScript(script *misc.Script, index int64) (err err
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("License-Key", config.Config.License)
|
||||
|
||||
var resp *http.Response
|
||||
resp, err = client.Do(req)
|
||||
@@ -295,6 +229,7 @@ func (connector *Connector) DeleteScript(index int64) (err error) {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("License-Key", config.Config.License)
|
||||
|
||||
var resp *http.Response
|
||||
resp, err = client.Do(req)
|
||||
@@ -318,22 +253,39 @@ func (connector *Connector) DeleteScript(index int64) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (connector *Connector) PostScriptDone() {
|
||||
postScripDonetUrl := fmt.Sprintf("%s/scripts/done", connector.url)
|
||||
func (connector *Connector) PostPcapsMerge(out *os.File) {
|
||||
postEnvUrl := fmt.Sprintf("%s/pcaps/merge", connector.url)
|
||||
|
||||
ok := false
|
||||
var err error
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postScripDonetUrl, "application/json", nil, connector.client); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
if envMarshalled, err := json.Marshal(map[string]string{"query": ""}); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal the env:")
|
||||
} else {
|
||||
ok := false
|
||||
for !ok {
|
||||
var resp *http.Response
|
||||
if resp, err = utils.Post(postEnvUrl, "application/json", bytes.NewBuffer(envMarshalled), connector.client, config.Config.License); err != nil || resp.StatusCode != http.StatusOK {
|
||||
if _, ok := err.(*url.Error); ok {
|
||||
break
|
||||
}
|
||||
log.Warn().Err(err).Msg("Failed exported PCAP download. Retrying...")
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check server response
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Error().Str("status", resp.Status).Err(err).Msg("Failed exported PCAP download.")
|
||||
return
|
||||
}
|
||||
|
||||
// Writer the body to file
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed writing PCAP export:")
|
||||
return
|
||||
}
|
||||
log.Info().Str("path", out.Name()).Msg("Downloaded exported PCAP:")
|
||||
return
|
||||
}
|
||||
log.Warn().Err(err).Msg("Failed sending the POST scripts done to Hub. Retrying...")
|
||||
} else {
|
||||
log.Debug().Msg("Reported POST scripts done to Hub.")
|
||||
return
|
||||
time.Sleep(DefaultSleep)
|
||||
}
|
||||
time.Sleep(DefaultSleep)
|
||||
}
|
||||
}
|
||||
|
||||
71
kubernetes/config.go
Normal file
71
kubernetes/config.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
SUFFIX_SECRET = "secret"
|
||||
SUFFIX_CONFIG_MAP = "config-map"
|
||||
SECRET_LICENSE = "LICENSE"
|
||||
CONFIG_POD_REGEX = "POD_REGEX"
|
||||
CONFIG_NAMESPACES = "NAMESPACES"
|
||||
CONFIG_SCRIPTING_ENV = "SCRIPTING_ENV"
|
||||
CONFIG_INGRESS_ENABLED = "INGRESS_ENABLED"
|
||||
CONFIG_INGRESS_HOST = "INGRESS_HOST"
|
||||
CONFIG_PROXY_FRONT_PORT = "PROXY_FRONT_PORT"
|
||||
CONFIG_AUTH_ENABLED = "AUTH_ENABLED"
|
||||
CONFIG_AUTH_TYPE = "AUTH_TYPE"
|
||||
CONFIG_AUTH_SAML_IDP_METADATA_URL = "AUTH_SAML_IDP_METADATA_URL"
|
||||
)
|
||||
|
||||
func SetSecret(provider *Provider, key string, value string) (updated bool, err error) {
|
||||
var secret *v1.Secret
|
||||
secret, err = provider.clientSet.CoreV1().Secrets(config.Config.Tap.Release.Namespace).Get(context.TODO(), SELF_RESOURCES_PREFIX+SUFFIX_SECRET, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if secret.StringData[key] != value {
|
||||
updated = true
|
||||
}
|
||||
secret.Data[key] = []byte(value)
|
||||
|
||||
_, err = provider.clientSet.CoreV1().Secrets(config.Config.Tap.Release.Namespace).Update(context.TODO(), secret, metav1.UpdateOptions{})
|
||||
if err == nil {
|
||||
if updated {
|
||||
log.Info().Str("secret", key).Str("value", value).Msg("Updated:")
|
||||
}
|
||||
} else {
|
||||
log.Error().Str("secret", key).Err(err).Send()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SetConfig(provider *Provider, key string, value string) (updated bool, err error) {
|
||||
var configMap *v1.ConfigMap
|
||||
configMap, err = provider.clientSet.CoreV1().ConfigMaps(config.Config.Tap.Release.Namespace).Get(context.TODO(), SELF_RESOURCES_PREFIX+SUFFIX_CONFIG_MAP, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if configMap.Data[key] != value {
|
||||
updated = true
|
||||
}
|
||||
configMap.Data[key] = value
|
||||
|
||||
_, err = provider.clientSet.CoreV1().ConfigMaps(config.Config.Tap.Release.Namespace).Update(context.TODO(), configMap, metav1.UpdateOptions{})
|
||||
if err == nil {
|
||||
if updated {
|
||||
log.Info().Str("config", key).Str("value", value).Msg("Updated:")
|
||||
}
|
||||
} else {
|
||||
log.Error().Str("config", key).Err(err).Send()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,28 +1,11 @@
|
||||
package kubernetes
|
||||
|
||||
const (
|
||||
SelfResourcesPrefix = "kubeshark-"
|
||||
FrontPodName = SelfResourcesPrefix + "front"
|
||||
SELF_RESOURCES_PREFIX = "kubeshark-"
|
||||
FrontPodName = SELF_RESOURCES_PREFIX + "front"
|
||||
FrontServiceName = FrontPodName
|
||||
HubPodName = SelfResourcesPrefix + "hub"
|
||||
HubPodName = SELF_RESOURCES_PREFIX + "hub"
|
||||
HubServiceName = HubPodName
|
||||
ClusterRoleBindingName = SelfResourcesPrefix + "cluster-role-binding"
|
||||
ClusterRoleName = SelfResourcesPrefix + "cluster-role"
|
||||
K8sAllNamespaces = ""
|
||||
RoleBindingName = SelfResourcesPrefix + "role-binding"
|
||||
RoleName = SelfResourcesPrefix + "role"
|
||||
ServiceAccountName = SelfResourcesPrefix + "service-account"
|
||||
WorkerDaemonSetName = SelfResourcesPrefix + "worker-daemon-set"
|
||||
WorkerPodName = SelfResourcesPrefix + "worker"
|
||||
PersistentVolumeName = SelfResourcesPrefix + "persistent-volume"
|
||||
PersistentVolumeClaimName = SelfResourcesPrefix + "persistent-volume-claim"
|
||||
IngressName = SelfResourcesPrefix + "ingress"
|
||||
IngressClassName = SelfResourcesPrefix + "ingress-class"
|
||||
PersistentVolumeHostPath = "/app/data"
|
||||
MinKubernetesServerVersion = "1.16.0"
|
||||
)
|
||||
|
||||
const (
|
||||
LabelManagedBy = SelfResourcesPrefix + "managed-by"
|
||||
LabelCreatedBy = SelfResourcesPrefix + "created-by"
|
||||
)
|
||||
|
||||
192
kubernetes/cp.go
Normal file
192
kubernetes/cp.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
func CopyFromPod(ctx context.Context, provider *Provider, pod v1.Pod, srcPath string, dstPath string) error {
|
||||
const containerName = "sniffer"
|
||||
cmdArr := []string{"tar", "cf", "-", srcPath}
|
||||
req := provider.clientSet.CoreV1().RESTClient().
|
||||
Post().
|
||||
Namespace(pod.Namespace).
|
||||
Resource("pods").
|
||||
Name(pod.Name).
|
||||
SubResource("exec").
|
||||
VersionedParams(&v1.PodExecOptions{
|
||||
Container: containerName,
|
||||
Command: cmdArr,
|
||||
Stdin: true,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
TTY: false,
|
||||
}, scheme.ParameterCodec)
|
||||
|
||||
exec, err := remotecommand.NewSPDYExecutor(&provider.clientConfig, "POST", req.URL())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reader, outStream := io.Pipe()
|
||||
errReader, errStream := io.Pipe()
|
||||
go logErrors(errReader, pod)
|
||||
go func() {
|
||||
defer outStream.Close()
|
||||
err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{
|
||||
Stdin: os.Stdin,
|
||||
Stdout: outStream,
|
||||
Stderr: errStream,
|
||||
Tty: false,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("pod", pod.Name).Msg("SPDYExecutor:")
|
||||
}
|
||||
}()
|
||||
|
||||
prefix := getPrefix(srcPath)
|
||||
prefix = path.Clean(prefix)
|
||||
prefix = stripPathShortcuts(prefix)
|
||||
dstPath = path.Join(dstPath, path.Base(prefix))
|
||||
err = untarAll(reader, dstPath, prefix)
|
||||
// fo(reader)
|
||||
return err
|
||||
}
|
||||
|
||||
// func fo(fi io.Reader) {
|
||||
// fo, err := os.Create("output.tar")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
// // make a buffer to keep chunks that are read
|
||||
// buf := make([]byte, 1024)
|
||||
// for {
|
||||
// // read a chunk
|
||||
// n, err := fi.Read(buf)
|
||||
// if err != nil && err != io.EOF {
|
||||
// panic(err)
|
||||
// }
|
||||
// if n == 0 {
|
||||
// break
|
||||
// }
|
||||
|
||||
// // write a chunk
|
||||
// if _, err := fo.Write(buf[:n]); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
func logErrors(reader io.Reader, pod v1.Pod) {
|
||||
r := bufio.NewReader(reader)
|
||||
for {
|
||||
msg, _, err := r.ReadLine()
|
||||
log.Warn().Str("pod", pod.Name).Str("msg", string(msg)).Msg("SPDYExecutor:")
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Error().Err(err).Send()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func untarAll(reader io.Reader, destDir, prefix string) error {
|
||||
tarReader := tar.NewReader(reader)
|
||||
for {
|
||||
header, err := tarReader.Next()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(header.Name, prefix) {
|
||||
return fmt.Errorf("tar contents corrupted")
|
||||
}
|
||||
|
||||
mode := header.FileInfo().Mode()
|
||||
destFileName := filepath.Join(destDir, header.Name[len(prefix):])
|
||||
|
||||
baseName := filepath.Dir(destFileName)
|
||||
if err := os.MkdirAll(baseName, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if header.FileInfo().IsDir() {
|
||||
if err := os.MkdirAll(destFileName, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
evaledPath, err := filepath.EvalSymlinks(baseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mode&os.ModeSymlink != 0 {
|
||||
linkname := header.Linkname
|
||||
|
||||
if !filepath.IsAbs(linkname) {
|
||||
_ = filepath.Join(evaledPath, linkname)
|
||||
}
|
||||
|
||||
if err := os.Symlink(linkname, destFileName); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
outFile, err := os.Create(destFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outFile.Close()
|
||||
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := outFile.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPrefix(file string) string {
|
||||
return strings.TrimLeft(file, "/")
|
||||
}
|
||||
|
||||
func stripPathShortcuts(p string) string {
|
||||
newPath := p
|
||||
trimmed := strings.TrimPrefix(newPath, "../")
|
||||
|
||||
for trimmed != newPath {
|
||||
newPath = trimmed
|
||||
trimmed = strings.TrimPrefix(newPath, "../")
|
||||
}
|
||||
|
||||
// trim leftover {".", ".."}
|
||||
if newPath == "." || newPath == ".." {
|
||||
newPath = ""
|
||||
}
|
||||
|
||||
if len(newPath) > 0 && string(newPath[0]) == "/" {
|
||||
return newPath[1:]
|
||||
}
|
||||
|
||||
return newPath
|
||||
}
|
||||
186
kubernetes/helm/helm.go
Normal file
186
kubernetes/helm/helm.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package helm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
"helm.sh/helm/v3/pkg/cli"
|
||||
"helm.sh/helm/v3/pkg/downloader"
|
||||
"helm.sh/helm/v3/pkg/getter"
|
||||
"helm.sh/helm/v3/pkg/kube"
|
||||
"helm.sh/helm/v3/pkg/registry"
|
||||
"helm.sh/helm/v3/pkg/release"
|
||||
"helm.sh/helm/v3/pkg/repo"
|
||||
)
|
||||
|
||||
const ENV_HELM_DRIVER = "HELM_DRIVER"
|
||||
|
||||
var settings = cli.New()
|
||||
|
||||
type Helm struct {
|
||||
repo string
|
||||
releaseName string
|
||||
releaseNamespace string
|
||||
}
|
||||
|
||||
func NewHelm(repo string, releaseName string, releaseNamespace string) *Helm {
|
||||
return &Helm{
|
||||
repo: repo,
|
||||
releaseName: releaseName,
|
||||
releaseNamespace: releaseNamespace,
|
||||
}
|
||||
}
|
||||
|
||||
func parseOCIRef(chartRef string) (string, string, error) {
|
||||
refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`)
|
||||
caps := refTagRegexp.FindStringSubmatch(chartRef)
|
||||
if len(caps) != 4 {
|
||||
return "", "", errors.Errorf("improperly formatted oci chart reference: %s", chartRef)
|
||||
}
|
||||
chartRef = caps[1]
|
||||
tag := caps[3]
|
||||
|
||||
return chartRef, tag, nil
|
||||
}
|
||||
|
||||
func (h *Helm) Install() (rel *release.Release, err error) {
|
||||
kubeConfigPath := config.Config.KubeConfigPath()
|
||||
actionConfig := new(action.Configuration)
|
||||
if err = actionConfig.Init(kube.GetConfig(kubeConfigPath, "", h.releaseNamespace), h.releaseNamespace, os.Getenv(ENV_HELM_DRIVER), func(format string, v ...interface{}) {
|
||||
log.Info().Msgf(format, v...)
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
client := action.NewInstall(actionConfig)
|
||||
client.Namespace = h.releaseNamespace
|
||||
client.ReleaseName = h.releaseName
|
||||
|
||||
chartPath := os.Getenv(fmt.Sprintf("%s_HELM_CHART_PATH", strings.ToUpper(misc.Program)))
|
||||
if chartPath == "" {
|
||||
var chartURL string
|
||||
chartURL, err = repo.FindChartInRepoURL(h.repo, h.releaseName, "", "", "", "", getter.All(&cli.EnvSettings{}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cp string
|
||||
cp, err = client.ChartPathOptions.LocateChart(chartURL, settings)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
m := &downloader.Manager{
|
||||
Out: os.Stdout,
|
||||
ChartPath: cp,
|
||||
Keyring: client.ChartPathOptions.Keyring,
|
||||
SkipUpdate: false,
|
||||
Getters: getter.All(settings),
|
||||
RepositoryConfig: settings.RepositoryConfig,
|
||||
RepositoryCache: settings.RepositoryCache,
|
||||
Debug: settings.Debug,
|
||||
}
|
||||
|
||||
dl := downloader.ChartDownloader{
|
||||
Out: m.Out,
|
||||
Verify: m.Verify,
|
||||
Keyring: m.Keyring,
|
||||
RepositoryConfig: m.RepositoryConfig,
|
||||
RepositoryCache: m.RepositoryCache,
|
||||
RegistryClient: m.RegistryClient,
|
||||
Getters: m.Getters,
|
||||
Options: []getter.Option{
|
||||
getter.WithInsecureSkipVerifyTLS(false),
|
||||
},
|
||||
}
|
||||
|
||||
repoPath := filepath.Dir(m.ChartPath)
|
||||
err = os.MkdirAll(repoPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
version := ""
|
||||
if registry.IsOCI(chartURL) {
|
||||
chartURL, version, err = parseOCIRef(chartURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dl.Options = append(dl.Options,
|
||||
getter.WithRegistryClient(m.RegistryClient),
|
||||
getter.WithTagName(version))
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("url", chartURL).
|
||||
Str("repo-path", repoPath).
|
||||
Msg("Downloading Helm chart:")
|
||||
|
||||
if _, _, err = dl.DownloadTo(chartURL, version, repoPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
chartPath = m.ChartPath
|
||||
}
|
||||
var chart *chart.Chart
|
||||
chart, err = loader.Load(chartPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Info().
|
||||
Str("release", chart.Metadata.Name).
|
||||
Str("version", chart.Metadata.Version).
|
||||
Strs("source", chart.Metadata.Sources).
|
||||
Str("kube-version", chart.Metadata.KubeVersion).
|
||||
Msg("Installing using Helm:")
|
||||
|
||||
var configMarshalled []byte
|
||||
configMarshalled, err = json.Marshal(config.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var configUnmarshalled map[string]interface{}
|
||||
err = json.Unmarshal(configMarshalled, &configUnmarshalled)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rel, err = client.Run(chart, configUnmarshalled)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (h *Helm) Uninstall() (resp *release.UninstallReleaseResponse, err error) {
|
||||
kubeConfigPath := config.Config.KubeConfigPath()
|
||||
actionConfig := new(action.Configuration)
|
||||
if err = actionConfig.Init(kube.GetConfig(kubeConfigPath, "", h.releaseNamespace), h.releaseNamespace, os.Getenv(ENV_HELM_DRIVER), func(format string, v ...interface{}) {
|
||||
log.Info().Msgf(format, v...)
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
client := action.NewUninstall(actionConfig)
|
||||
|
||||
resp, err = client.Run(h.releaseName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/rs/zerolog/log"
|
||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||
"k8s.io/client-go/tools/portforward"
|
||||
@@ -23,6 +24,7 @@ const selfServicePort = 80
|
||||
|
||||
func StartProxy(kubernetesProvider *Provider, proxyHost string, srcPort uint16, selfNamespace string, selfServiceName string) (*http.Server, error) {
|
||||
log.Info().
|
||||
Str("proxy-host", proxyHost).
|
||||
Str("namespace", selfNamespace).
|
||||
Str("service", selfServiceName).
|
||||
Int("src-port", int(srcPort)).
|
||||
@@ -66,8 +68,12 @@ func getSelfHubProxiedHostAndPath(selfNamespace string, selfServiceName string)
|
||||
return fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%d/proxy", selfNamespace, selfServiceName, selfServicePort)
|
||||
}
|
||||
|
||||
func GetLocalhostOnPort(port uint16) string {
|
||||
return fmt.Sprintf("http://localhost:%d", port)
|
||||
func GetProxyOnPort(port uint16) string {
|
||||
return fmt.Sprintf("http://%s:%d", config.Config.Tap.Proxy.Host, port)
|
||||
}
|
||||
|
||||
func GetHubUrl() string {
|
||||
return fmt.Sprintf("%s/api", GetProxyOnPort(config.Config.Tap.Proxy.Front.Port))
|
||||
}
|
||||
|
||||
func getRerouteHttpHandlerSelfAPI(proxyHandler http.Handler, selfNamespace string, selfServiceName string) http.Handler {
|
||||
@@ -100,7 +106,7 @@ func getRerouteHttpHandlerSelfStatic(proxyHandler http.Handler, selfNamespace st
|
||||
}
|
||||
|
||||
func NewPortForward(kubernetesProvider *Provider, namespace string, podRegex *regexp.Regexp, srcPort uint16, dstPort uint16, ctx context.Context) (*portforward.PortForwarder, error) {
|
||||
pods, err := kubernetesProvider.ListAllRunningPodsMatchingRegex(ctx, podRegex, []string{namespace})
|
||||
pods, err := kubernetesProvider.ListPodsByAppLabel(ctx, namespace, map[string]string{"app.kubeshark.co/app": "front"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(pods) == 0 {
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
core "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
applyconfapp "k8s.io/client-go/applyconfigurations/apps/v1"
|
||||
applyconfcore "k8s.io/client-go/applyconfigurations/core/v1"
|
||||
v1 "k8s.io/client-go/applyconfigurations/core/v1"
|
||||
applyconfmeta "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||
)
|
||||
|
||||
type DaemonSetPod struct {
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
Spec core.PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
}
|
||||
|
||||
type DaemonSetSpec struct {
|
||||
Selector metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,1,opt,name=selector"`
|
||||
Template DaemonSetPod `json:"template,omitempty" protobuf:"bytes,2,opt,name=template"`
|
||||
}
|
||||
|
||||
type DaemonSet struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
Spec DaemonSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
}
|
||||
|
||||
func (d *DaemonSet) GenerateApplyConfiguration(name string, namespace string, podName string, provider *Provider) *applyconfapp.DaemonSetApplyConfiguration {
|
||||
// Pod
|
||||
p := d.Spec.Template.Spec
|
||||
podSpec := applyconfcore.PodSpec()
|
||||
podSpec.WithHostNetwork(p.HostNetwork)
|
||||
podSpec.WithDNSPolicy(p.DNSPolicy)
|
||||
podSpec.WithTerminationGracePeriodSeconds(*p.TerminationGracePeriodSeconds)
|
||||
podSpec.WithServiceAccountName(p.ServiceAccountName)
|
||||
|
||||
// Containers
|
||||
for _, c := range d.Spec.Template.Spec.Containers {
|
||||
// Common
|
||||
container := applyconfcore.Container()
|
||||
container.WithName(c.Name)
|
||||
container.WithImage(c.Image)
|
||||
container.WithImagePullPolicy(c.ImagePullPolicy)
|
||||
container.WithCommand(c.Command...)
|
||||
|
||||
// Linux capabilities
|
||||
caps := applyconfcore.Capabilities().WithAdd(c.SecurityContext.Capabilities.Add...).WithDrop(c.SecurityContext.Capabilities.Drop...)
|
||||
container.WithSecurityContext(applyconfcore.SecurityContext().WithCapabilities(caps))
|
||||
|
||||
// Environment variables
|
||||
var envvars []*v1.EnvVarApplyConfiguration
|
||||
for _, e := range c.Env {
|
||||
envvars = append(envvars, applyconfcore.EnvVar().WithName(e.Name).WithValue(e.Value))
|
||||
}
|
||||
container.WithEnv(envvars...)
|
||||
|
||||
// Resource limits
|
||||
resources := applyconfcore.ResourceRequirements().WithRequests(c.Resources.Requests).WithLimits(c.Resources.Limits)
|
||||
container.WithResources(resources)
|
||||
|
||||
// Volume mounts
|
||||
for _, m := range c.VolumeMounts {
|
||||
volumeMount := applyconfcore.VolumeMount().WithName(m.Name).WithMountPath(m.MountPath).WithReadOnly(m.ReadOnly)
|
||||
container.WithVolumeMounts(volumeMount)
|
||||
}
|
||||
|
||||
podSpec.WithContainers(container)
|
||||
}
|
||||
|
||||
// Node affinity (RequiredDuringSchedulingIgnoredDuringExecution only)
|
||||
if p.Affinity != nil {
|
||||
nodeSelector := applyconfcore.NodeSelector()
|
||||
for _, term := range p.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
|
||||
nodeSelectorTerm := applyconfcore.NodeSelectorTerm()
|
||||
for _, selector := range term.MatchExpressions {
|
||||
nodeSelectorRequirement := applyconfcore.NodeSelectorRequirement()
|
||||
nodeSelectorRequirement.WithKey(selector.Key)
|
||||
nodeSelectorRequirement.WithOperator(selector.Operator)
|
||||
nodeSelectorRequirement.WithValues(selector.Values...)
|
||||
nodeSelectorTerm.WithMatchExpressions(nodeSelectorRequirement)
|
||||
}
|
||||
for _, selector := range term.MatchFields {
|
||||
nodeSelectorRequirement := applyconfcore.NodeSelectorRequirement()
|
||||
nodeSelectorRequirement.WithKey(selector.Key)
|
||||
nodeSelectorRequirement.WithOperator(selector.Operator)
|
||||
nodeSelectorRequirement.WithValues(selector.Values...)
|
||||
nodeSelectorTerm.WithMatchFields(nodeSelectorRequirement)
|
||||
}
|
||||
nodeSelector.WithNodeSelectorTerms(nodeSelectorTerm)
|
||||
}
|
||||
nodeAffinity := applyconfcore.NodeAffinity()
|
||||
nodeAffinity.WithRequiredDuringSchedulingIgnoredDuringExecution(nodeSelector)
|
||||
affinity := applyconfcore.Affinity()
|
||||
affinity.WithNodeAffinity(nodeAffinity)
|
||||
podSpec.WithAffinity(affinity)
|
||||
}
|
||||
|
||||
// Tolerations
|
||||
for _, t := range p.Tolerations {
|
||||
toleration := applyconfcore.Toleration()
|
||||
toleration.WithKey(t.Key)
|
||||
toleration.WithOperator(t.Operator)
|
||||
toleration.WithValue(t.Value)
|
||||
toleration.WithEffect(t.Effect)
|
||||
if t.TolerationSeconds != nil {
|
||||
toleration.WithTolerationSeconds(*t.TolerationSeconds)
|
||||
}
|
||||
podSpec.WithTolerations(toleration)
|
||||
}
|
||||
|
||||
// Volumes
|
||||
for _, v := range p.Volumes {
|
||||
volume := applyconfcore.Volume()
|
||||
if v.HostPath != nil {
|
||||
volume.WithName(v.Name).WithHostPath(applyconfcore.HostPathVolumeSource().WithPath(v.HostPath.Path))
|
||||
}
|
||||
if v.PersistentVolumeClaim != nil {
|
||||
volume.WithName(v.Name).WithPersistentVolumeClaim(applyconfcore.PersistentVolumeClaimVolumeSource().WithClaimName(v.PersistentVolumeClaim.ClaimName))
|
||||
}
|
||||
podSpec.WithVolumes(volume)
|
||||
}
|
||||
|
||||
// Image pull secrets
|
||||
if len(p.ImagePullSecrets) > 0 {
|
||||
localObjectReference := applyconfcore.LocalObjectReference()
|
||||
for _, o := range p.ImagePullSecrets {
|
||||
localObjectReference.WithName(o.Name)
|
||||
}
|
||||
podSpec.WithImagePullSecrets(localObjectReference)
|
||||
}
|
||||
|
||||
podTemplate := applyconfcore.PodTemplateSpec()
|
||||
podTemplate.WithLabels(buildWithDefaultLabels(map[string]string{
|
||||
"app": podName,
|
||||
}, provider))
|
||||
podTemplate.WithSpec(podSpec)
|
||||
|
||||
labelSelector := applyconfmeta.LabelSelector()
|
||||
labelSelector.WithMatchLabels(map[string]string{"app": podName})
|
||||
|
||||
daemonSet := applyconfapp.DaemonSet(name, namespace)
|
||||
daemonSet.
|
||||
WithLabels(buildWithDefaultLabels(map[string]string{}, provider)).
|
||||
WithSpec(applyconfapp.DaemonSetSpec().WithSelector(labelSelector).WithTemplate(podTemplate))
|
||||
|
||||
return daemonSet
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
)
|
||||
|
||||
func buildWithDefaultLabels(labels map[string]string, provider *Provider) map[string]string {
|
||||
labels[LabelManagedBy] = provider.managedBy
|
||||
labels[LabelCreatedBy] = provider.createdBy
|
||||
|
||||
for k, v := range config.Config.Tap.ResourceLabels {
|
||||
labels[k] = v
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/docker"
|
||||
"github.com/rs/zerolog/log"
|
||||
core "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func CreateWorkers(
|
||||
kubernetesProvider *Provider,
|
||||
selfServiceAccountExists bool,
|
||||
ctx context.Context,
|
||||
namespace string,
|
||||
resources configStructs.ResourceRequirements,
|
||||
imagePullPolicy core.PullPolicy,
|
||||
imagePullSecrets []core.LocalObjectReference,
|
||||
serviceMesh bool,
|
||||
tls bool,
|
||||
debug bool,
|
||||
) error {
|
||||
if config.Config.Tap.PersistentStorage {
|
||||
persistentVolumeClaim, err := kubernetesProvider.BuildPersistentVolumeClaim()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = kubernetesProvider.CreatePersistentVolumeClaim(
|
||||
ctx,
|
||||
namespace,
|
||||
persistentVolumeClaim,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
image := docker.GetWorkerImage()
|
||||
|
||||
var serviceAccountName string
|
||||
if selfServiceAccountExists {
|
||||
serviceAccountName = ServiceAccountName
|
||||
} else {
|
||||
serviceAccountName = ""
|
||||
}
|
||||
|
||||
log.Info().Msg("Creating the worker DaemonSet...")
|
||||
|
||||
if err := kubernetesProvider.ApplyWorkerDaemonSet(
|
||||
ctx,
|
||||
namespace,
|
||||
WorkerDaemonSetName,
|
||||
image,
|
||||
WorkerPodName,
|
||||
serviceAccountName,
|
||||
resources,
|
||||
imagePullPolicy,
|
||||
imagePullSecrets,
|
||||
serviceMesh,
|
||||
tls,
|
||||
debug,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Msg("Successfully created the worker DaemonSet.")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark
|
||||
spec: {}
|
||||
status: {}
|
||||
@@ -1,12 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-service-account
|
||||
namespace: kubeshark
|
||||
@@ -1,28 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-cluster-role
|
||||
namespace: kubeshark
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- extensions
|
||||
- apps
|
||||
- networking.k8s.io
|
||||
resources:
|
||||
- pods
|
||||
- services
|
||||
- endpoints
|
||||
- persistentvolumeclaims
|
||||
- ingresses
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- watch
|
||||
@@ -1,20 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-cluster-role-binding
|
||||
namespace: kubeshark
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubeshark-cluster-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubeshark-service-account
|
||||
namespace: kubeshark
|
||||
@@ -1,48 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-hub
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-hub
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- ./hub
|
||||
env:
|
||||
- name: POD_REGEX
|
||||
value: .*
|
||||
- name: NAMESPACES
|
||||
- name: LICENSE
|
||||
- name: SCRIPTING_ENV
|
||||
value: '{}'
|
||||
- name: SCRIPTING_SCRIPTS
|
||||
value: '[]'
|
||||
- name: AUTH_APPROVED_DOMAINS
|
||||
image: docker.io/kubeshark/hub:latest
|
||||
imagePullPolicy: Always
|
||||
name: kubeshark-hub
|
||||
ports:
|
||||
- containerPort: 80
|
||||
hostPort: 8898
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
status: {}
|
||||
@@ -1,21 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-hub
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-hub
|
||||
port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: kubeshark-hub
|
||||
type: NodePort
|
||||
status:
|
||||
loadBalancer: {}
|
||||
@@ -1,50 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-front
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-front
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: REACT_APP_DEFAULT_FILTER
|
||||
value: ' '
|
||||
- name: REACT_APP_HUB_HOST
|
||||
value: ' '
|
||||
- name: REACT_APP_HUB_PORT
|
||||
value: "8898"
|
||||
image: docker.io/kubeshark/front:latest
|
||||
imagePullPolicy: Always
|
||||
name: kubeshark-front
|
||||
ports:
|
||||
- containerPort: 80
|
||||
hostPort: 8899
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
periodSeconds: 1
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 80
|
||||
timeoutSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
status: {}
|
||||
@@ -1,21 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-front
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-front
|
||||
port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: kubeshark-front
|
||||
type: NodePort
|
||||
status:
|
||||
loadBalancer: {}
|
||||
@@ -1,20 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-persistent-volume-claim
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 200Mi
|
||||
storageClassName: standard
|
||||
status: {}
|
||||
@@ -1,93 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: kubeshark-worker-daemon-set
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- ./worker
|
||||
- -i
|
||||
- any
|
||||
- -port
|
||||
- "8897"
|
||||
- -packet-capture
|
||||
- libpcap
|
||||
- -servicemesh
|
||||
- -tls
|
||||
- -procfs
|
||||
- /hostproc
|
||||
image: docker.io/kubeshark/worker:latest
|
||||
imagePullPolicy: Always
|
||||
name: kubeshark-worker-daemon-set
|
||||
ports:
|
||||
- containerPort: 8897
|
||||
hostPort: 8897
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- DAC_OVERRIDE
|
||||
- SYS_RESOURCE
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- mountPath: /hostproc
|
||||
name: proc
|
||||
readOnly: true
|
||||
- mountPath: /sys
|
||||
name: sys
|
||||
readOnly: true
|
||||
- mountPath: /app/data
|
||||
name: kubeshark-persistent-volume
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /proc
|
||||
name: proc
|
||||
- hostPath:
|
||||
path: /sys
|
||||
name: sys
|
||||
- name: kubeshark-persistent-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: kubeshark-persistent-volume-claim
|
||||
@@ -1,14 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: IngressClass
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-ingress-class
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
controller: k8s.io/ingress-nginx
|
||||
@@ -1,37 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY KUBESHARK CLI. DO NOT EDIT!
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /$2
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
kubeshark-cli-version: v1
|
||||
kubeshark-created-by: kubeshark
|
||||
kubeshark-managed-by: kubeshark
|
||||
name: kubeshark-ingress
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
ingressClassName: kubeshark-ingress-class
|
||||
rules:
|
||||
- host: ks.svc.cluster.local
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: kubeshark-hub
|
||||
port:
|
||||
number: 80
|
||||
path: /api(/|$)(.*)
|
||||
pathType: Prefix
|
||||
- backend:
|
||||
service:
|
||||
name: kubeshark-front
|
||||
port:
|
||||
number: 80
|
||||
path: /()(.*)
|
||||
pathType: Prefix
|
||||
status:
|
||||
loadBalancer: {}
|
||||
@@ -28,8 +28,7 @@ kubectl delete clusterrole kubeshark-cluster-role
|
||||
Do the port forwarding:
|
||||
|
||||
```shell
|
||||
kubectl port-forward -n kubeshark service/kubeshark-hub 8898:80 & \
|
||||
kubectl port-forward -n kubeshark service/kubeshark-front 8899:80
|
||||
kubectl port-forward service/kubeshark-front 8899:80
|
||||
```
|
||||
|
||||
Visit [localhost:8899](http://localhost:8899)
|
||||
|
||||
782
manifests/complete.yaml
Normal file
782
manifests/complete.yaml
Normal file
@@ -0,0 +1,782 @@
|
||||
---
|
||||
# Source: kubeshark/templates/16-network-policies.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-hub-network-policy
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: hub
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- {}
|
||||
---
|
||||
# Source: kubeshark/templates/16-network-policies.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-front-network-policy
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: front
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- {}
|
||||
---
|
||||
# Source: kubeshark/templates/16-network-policies.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: kubeshark-worker-network-policy
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: worker
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 30001
|
||||
- protocol: TCP
|
||||
port: 49100
|
||||
egress:
|
||||
- {}
|
||||
---
|
||||
# Source: kubeshark/templates/01-service-account.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-service-account
|
||||
namespace: default
|
||||
---
|
||||
# Source: kubeshark/templates/13-secret.yaml
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-secret
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
stringData:
|
||||
LICENSE: ''
|
||||
SCRIPTING_ENV: '{}'
|
||||
---
|
||||
# Source: kubeshark/templates/13-secret.yaml
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-saml-x509-crt-secret
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
stringData:
|
||||
AUTH_SAML_X509_CRT: |
|
||||
---
|
||||
# Source: kubeshark/templates/13-secret.yaml
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-saml-x509-key-secret
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
stringData:
|
||||
AUTH_SAML_X509_KEY: |
|
||||
---
|
||||
# Source: kubeshark/templates/11-nginx-config-map.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kubeshark-nginx-config-map
|
||||
namespace: default
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
data:
|
||||
default.conf: |
|
||||
server {
|
||||
listen 8080;
|
||||
listen [::]:8080;
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stdout;
|
||||
|
||||
client_body_buffer_size 64k;
|
||||
client_header_buffer_size 32k;
|
||||
large_client_header_buffers 8 64k;
|
||||
|
||||
location /api {
|
||||
rewrite ^/api(.*)$ $1 break;
|
||||
proxy_pass http://kubeshark-hub;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade websocket;
|
||||
proxy_set_header Connection Upgrade;
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
proxy_pass_header Authorization;
|
||||
proxy_connect_timeout 4s;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 12s;
|
||||
proxy_pass_request_headers on;
|
||||
}
|
||||
|
||||
location /saml {
|
||||
rewrite ^/saml(.*)$ /saml$1 break;
|
||||
proxy_pass http://kubeshark-hub;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_connect_timeout 4s;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 12s;
|
||||
proxy_pass_request_headers on;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
expires -1;
|
||||
add_header Cache-Control no-cache;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
---
|
||||
# Source: kubeshark/templates/12-config-map.yaml
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-config-map
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
data:
|
||||
POD_REGEX: '.*'
|
||||
NAMESPACES: ''
|
||||
SCRIPTING_SCRIPTS: '{}'
|
||||
INGRESS_ENABLED: 'false'
|
||||
INGRESS_HOST: 'ks.svc.cluster.local'
|
||||
PROXY_FRONT_PORT: '8899'
|
||||
AUTH_ENABLED: ''
|
||||
AUTH_TYPE: 'saml'
|
||||
AUTH_SAML_IDP_METADATA_URL: ''
|
||||
AUTH_SAML_ROLE_ATTRIBUTE: 'role'
|
||||
AUTH_SAML_ROLES: '{"admin":{"canDownloadPCAP":true,"canReplayTraffic":true,"canUpdateTargetedPods":true,"canUseScripting":true,"filter":"","showAdminConsoleLink":true}}'
|
||||
TELEMETRY_DISABLED: ''
|
||||
REPLAY_DISABLED: ''
|
||||
SCRIPTING_DISABLED: ''
|
||||
TARGETED_PODS_UPDATE_DISABLED: ''
|
||||
RECORDING_DISABLED: ''
|
||||
GLOBAL_FILTER: ""
|
||||
TRAFFIC_SAMPLE_RATE: '100'
|
||||
JSON_TTL: '5m'
|
||||
PCAP_TTL: '10s'
|
||||
PCAP_ERROR_TTL: '60s'
|
||||
TIMEZONE: ' '
|
||||
---
|
||||
# Source: kubeshark/templates/02-cluster-role.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-cluster-role-default
|
||||
namespace: default
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- extensions
|
||||
- apps
|
||||
resources:
|
||||
- pods
|
||||
- services
|
||||
- endpoints
|
||||
- persistentvolumeclaims
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
verbs:
|
||||
- get
|
||||
resourceNames:
|
||||
- kube-system
|
||||
---
|
||||
# Source: kubeshark/templates/03-cluster-role-binding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-cluster-role-binding-default
|
||||
namespace: default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubeshark-cluster-role-default
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubeshark-service-account
|
||||
namespace: default
|
||||
---
|
||||
# Source: kubeshark/templates/02-cluster-role.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-self-config-role
|
||||
namespace: default
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- v1
|
||||
resourceNames:
|
||||
- kubeshark-secret
|
||||
- kubeshark-config-map
|
||||
resources:
|
||||
- secrets
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- update
|
||||
- patch
|
||||
---
|
||||
# Source: kubeshark/templates/03-cluster-role-binding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-self-config-role-binding
|
||||
namespace: default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: kubeshark-self-config-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubeshark-service-account
|
||||
namespace: default
|
||||
---
|
||||
# Source: kubeshark/templates/05-hub-service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-hub
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-hub
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app.kubeshark.co/app: hub
|
||||
type: ClusterIP
|
||||
---
|
||||
# Source: kubeshark/templates/07-front-service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-front
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- name: kubeshark-front
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app.kubeshark.co/app: front
|
||||
type: ClusterIP
|
||||
---
|
||||
# Source: kubeshark/templates/15-worker-service-metrics.yaml
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kubeshark-worker-metrics
|
||||
namespace: default
|
||||
annotations:
|
||||
prometheus.io/scrape: 'true'
|
||||
prometheus.io/port: '49100'
|
||||
spec:
|
||||
selector:
|
||||
app.kubeshark.co/app: worker
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
ports:
|
||||
- name: metrics
|
||||
protocol: TCP
|
||||
port: 49100
|
||||
targetPort: 49100
|
||||
---
|
||||
# Source: kubeshark/templates/09-worker-daemon-set.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: worker
|
||||
sidecar.istio.io/inject: "false"
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: worker
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: worker
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
name: kubeshark-worker-daemon-set
|
||||
namespace: kubeshark
|
||||
spec:
|
||||
initContainers:
|
||||
- name: load-pf-ring
|
||||
image: kubeshark/pf-ring-module:all
|
||||
imagePullPolicy: Always
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- SYS_MODULE
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
containers:
|
||||
- command:
|
||||
- ./worker
|
||||
- -i
|
||||
- any
|
||||
- -port
|
||||
- '30001'
|
||||
- -metrics-port
|
||||
- '49100'
|
||||
- -packet-capture
|
||||
- 'best'
|
||||
- -unixsocket
|
||||
- -servicemesh
|
||||
- -procfs
|
||||
- /hostproc
|
||||
- -kernel-module
|
||||
- -disable-ebpf
|
||||
image: 'docker.io/kubeshark/worker:v52.2.30'
|
||||
imagePullPolicy: Always
|
||||
name: sniffer
|
||||
ports:
|
||||
- containerPort: 49100
|
||||
protocol: TCP
|
||||
name: metrics
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: TCP_STREAM_CHANNEL_TIMEOUT_MS
|
||||
value: '10000'
|
||||
- name: TCP_STREAM_CHANNEL_TIMEOUT_SHOW
|
||||
value: 'false'
|
||||
- name: KUBESHARK_CLOUD_API_URL
|
||||
value: 'https://api.kubeshark.co'
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- DAC_OVERRIDE
|
||||
drop:
|
||||
- ALL
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 5
|
||||
tcpSocket:
|
||||
port: 30001
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 5
|
||||
tcpSocket:
|
||||
port: 30001
|
||||
volumeMounts:
|
||||
- mountPath: /hostproc
|
||||
name: proc
|
||||
readOnly: true
|
||||
- mountPath: /sys
|
||||
name: sys
|
||||
readOnly: true
|
||||
- mountPath: /app/data
|
||||
name: data
|
||||
- command:
|
||||
- ./tracer
|
||||
- -procfs
|
||||
- /hostproc
|
||||
image: 'docker.io/kubeshark/worker:v52.2.30'
|
||||
imagePullPolicy: Always
|
||||
name: tracer
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- SYS_ADMIN
|
||||
- SYS_PTRACE
|
||||
- SYS_RESOURCE
|
||||
- IPC_LOCK
|
||||
- NET_RAW
|
||||
- NET_ADMIN
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- mountPath: /hostproc
|
||||
name: proc
|
||||
readOnly: true
|
||||
- mountPath: /sys
|
||||
name: sys
|
||||
readOnly: true
|
||||
- mountPath: /app/data
|
||||
name: data
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
serviceAccountName: kubeshark-service-account
|
||||
terminationGracePeriodSeconds: 0
|
||||
tolerations:
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/os
|
||||
operator: In
|
||||
values:
|
||||
- linux
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /proc
|
||||
name: proc
|
||||
- hostPath:
|
||||
path: /sys
|
||||
name: sys
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
- name: data
|
||||
emptyDir:
|
||||
sizeLimit: 500Mi
|
||||
---
|
||||
# Source: kubeshark/templates/04-hub-deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-hub
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1 # Set the desired number of replicas
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: hub
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: hub
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
containers:
|
||||
- name: kubeshark-hub
|
||||
command:
|
||||
- ./hub
|
||||
- -port
|
||||
- "8080"
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: KUBESHARK_CLOUD_API_URL
|
||||
value: 'https://api.kubeshark.co'
|
||||
image: 'docker.io/kubeshark/hub:v52.2.30'
|
||||
imagePullPolicy: Always
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
volumeMounts:
|
||||
- name: saml-x509-volume
|
||||
mountPath: "/etc/saml/x509"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: saml-x509-volume
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
name: kubeshark-saml-x509-crt-secret
|
||||
items:
|
||||
- key: AUTH_SAML_X509_CRT
|
||||
path: kubeshark.crt
|
||||
- secret:
|
||||
name: kubeshark-saml-x509-key-secret
|
||||
items:
|
||||
- key: AUTH_SAML_X509_KEY
|
||||
path: kubeshark.key
|
||||
---
|
||||
# Source: kubeshark/templates/06-front-deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: front
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
annotations:
|
||||
name: kubeshark-front
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1 # Set the desired number of replicas
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubeshark.co/app: front
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubeshark.co/app: front
|
||||
helm.sh/chart: kubeshark-52.2.30
|
||||
app.kubernetes.io/name: kubeshark
|
||||
app.kubernetes.io/instance: kubeshark
|
||||
app.kubernetes.io/version: "52.2.30"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: REACT_APP_DEFAULT_FILTER
|
||||
value: ' '
|
||||
- name: REACT_APP_AUTH_ENABLED
|
||||
value: 'false'
|
||||
- name: REACT_APP_AUTH_TYPE
|
||||
value: 'saml'
|
||||
- name: REACT_APP_AUTH_SAML_IDP_METADATA_URL
|
||||
value: ' '
|
||||
- name: REACT_APP_TIMEZONE
|
||||
value: ' '
|
||||
- name: REACT_APP_REPLAY_DISABLED
|
||||
value: 'false'
|
||||
- name: REACT_APP_SCRIPTING_DISABLED
|
||||
value: 'false'
|
||||
- name: REACT_APP_TARGETED_PODS_UPDATE_DISABLED
|
||||
value: 'false'
|
||||
- name: REACT_APP_RECORDING_DISABLED
|
||||
value: 'false'
|
||||
image: 'docker.io/kubeshark/front:v52.2.30'
|
||||
imagePullPolicy: Always
|
||||
name: kubeshark-front
|
||||
livenessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
initialDelaySeconds: 3
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
timeoutSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
cpu: 750m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 50Mi
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: kubeshark-nginx-config-map
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
serviceAccountName: kubeshark-service-account
|
||||
25
manifests/prometheus/kube_prometheus_stack.yaml
Normal file
25
manifests/prometheus/kube_prometheus_stack.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
grafana:
|
||||
additionalDataSources: []
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
scrapeInterval: 10s
|
||||
evaluationInterval: 30s
|
||||
additionalScrapeConfigs: |
|
||||
- job_name: 'kubeshark-worker-metrics'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
target_label: pod
|
||||
- source_labels: [__meta_kubernetes_pod_node_name]
|
||||
target_label: node
|
||||
- source_labels: [__meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: ^metrics$
|
||||
- source_labels: [__address__, __meta_kubernetes_endpoint_port_number]
|
||||
action: replace
|
||||
regex: ([^:]+)(?::\d+)?
|
||||
replacement: $1:49100
|
||||
target_label: __address__
|
||||
- action: labelmap
|
||||
regex: __meta_kubernetes_service_label_(.+)
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: info@kubeshark.com
|
||||
email: info@kubeshark.co
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod-key
|
||||
solvers:
|
||||
|
||||
@@ -12,8 +12,8 @@ var (
|
||||
Description = "The API Traffic Analyzer for Kubernetes"
|
||||
Website = "https://kubeshark.co"
|
||||
Email = "info@kubeshark.co"
|
||||
Ver = "0.0"
|
||||
Branch = "develop"
|
||||
Ver = "0.0.0"
|
||||
Branch = "master"
|
||||
GitCommitHash = "" // this var is overridden using ldflags in makefile when building
|
||||
BuildTimestamp = "" // this var is overridden using ldflags in makefile when building
|
||||
RBACVersion = "v1"
|
||||
|
||||
@@ -14,14 +14,14 @@ import (
|
||||
)
|
||||
|
||||
func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath string) error {
|
||||
podExactRegex := regexp.MustCompile("^" + kubernetes.SelfResourcesPrefix)
|
||||
pods, err := provider.ListAllPodsMatchingRegex(ctx, podExactRegex, []string{config.Config.Tap.SelfNamespace})
|
||||
podExactRegex := regexp.MustCompile("^" + kubernetes.SELF_RESOURCES_PREFIX)
|
||||
pods, err := provider.ListAllPodsMatchingRegex(ctx, podExactRegex, []string{config.Config.Tap.Release.Namespace})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pods) == 0 {
|
||||
return fmt.Errorf("No %s pods found in namespace %s", misc.Software, config.Config.Tap.SelfNamespace)
|
||||
return fmt.Errorf("No %s pods found in namespace %s", misc.Software, config.Config.Tap.Release.Namespace)
|
||||
}
|
||||
|
||||
newZipFile, err := os.Create(filePath)
|
||||
@@ -60,17 +60,17 @@ func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath strin
|
||||
}
|
||||
}
|
||||
|
||||
events, err := provider.GetNamespaceEvents(ctx, config.Config.Tap.SelfNamespace)
|
||||
events, err := provider.GetNamespaceEvents(ctx, config.Config.Tap.Release.Namespace)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to get k8b events!")
|
||||
} else {
|
||||
log.Debug().Str("namespace", config.Config.Tap.SelfNamespace).Msg("Successfully read events.")
|
||||
log.Debug().Str("namespace", config.Config.Tap.Release.Namespace).Msg("Successfully read events.")
|
||||
}
|
||||
|
||||
if err := AddStrToZip(zipWriter, events, fmt.Sprintf("%s_events.log", config.Config.Tap.SelfNamespace)); err != nil {
|
||||
if err := AddStrToZip(zipWriter, events, fmt.Sprintf("%s_events.log", config.Config.Tap.Release.Namespace)); err != nil {
|
||||
log.Error().Err(err).Msg("Failed write logs!")
|
||||
} else {
|
||||
log.Debug().Str("namespace", config.Config.Tap.SelfNamespace).Msg("Successfully added events.")
|
||||
log.Debug().Str("namespace", config.Config.Tap.Release.Namespace).Msg("Successfully added events.")
|
||||
}
|
||||
|
||||
if err := AddFileToZip(zipWriter, config.ConfigFilePath); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func CheckNewerVersion() {
|
||||
if os.Getenv("KUBESHARK_DISABLE_VERSION_CHECK") != "" {
|
||||
if os.Getenv(fmt.Sprintf("%s_DISABLE_VERSION_CHECK", strings.ToUpper(misc.Program))) != "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/errormessage"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/kubeshark/kubeshark/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
func CleanUpSelfResources(ctx context.Context, cancel context.CancelFunc, kubernetesProvider *kubernetes.Provider, isNsRestrictedMode bool, selfResourcesNamespace string) {
|
||||
log.Warn().Msg(fmt.Sprintf("Removing %s resources...", misc.Software))
|
||||
|
||||
var leftoverResources []string
|
||||
|
||||
if isNsRestrictedMode {
|
||||
leftoverResources = cleanUpRestrictedMode(ctx, kubernetesProvider, selfResourcesNamespace)
|
||||
} else {
|
||||
leftoverResources = cleanUpNonRestrictedMode(ctx, cancel, kubernetesProvider, selfResourcesNamespace)
|
||||
}
|
||||
|
||||
if len(leftoverResources) > 0 {
|
||||
errMsg := "Failed to remove the following resources."
|
||||
for _, resource := range leftoverResources {
|
||||
errMsg += "\n- " + resource
|
||||
}
|
||||
log.Error().Msg(fmt.Sprintf(utils.Red, errMsg))
|
||||
}
|
||||
}
|
||||
|
||||
func cleanUpNonRestrictedMode(ctx context.Context, cancel context.CancelFunc, kubernetesProvider *kubernetes.Provider, selfResourcesNamespace string) []string {
|
||||
leftoverResources := make([]string, 0)
|
||||
|
||||
if err := kubernetesProvider.RemoveIngressClass(ctx, kubernetes.IngressClassName); err != nil {
|
||||
resourceDesc := kubernetes.IngressClassName
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemoveNamespace(ctx, selfResourcesNamespace); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Namespace %s", selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
defer waitUntilNamespaceDeleted(ctx, cancel, kubernetesProvider, selfResourcesNamespace)
|
||||
}
|
||||
|
||||
if resources, err := kubernetesProvider.ListManagedClusterRoles(ctx); err != nil {
|
||||
resourceDesc := "ClusterRoles"
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
for _, resource := range resources.Items {
|
||||
if err := kubernetesProvider.RemoveClusterRole(ctx, resource.Name); err != nil {
|
||||
resourceDesc := fmt.Sprintf("ClusterRole %s", resource.Name)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if resources, err := kubernetesProvider.ListManagedClusterRoleBindings(ctx); err != nil {
|
||||
resourceDesc := "ClusterRoleBindings"
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
for _, resource := range resources.Items {
|
||||
if err := kubernetesProvider.RemoveClusterRoleBinding(ctx, resource.Name); err != nil {
|
||||
resourceDesc := fmt.Sprintf("ClusterRoleBinding %s", resource.Name)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return leftoverResources
|
||||
}
|
||||
|
||||
func waitUntilNamespaceDeleted(ctx context.Context, cancel context.CancelFunc, kubernetesProvider *kubernetes.Provider, selfResourcesNamespace string) {
|
||||
// Call cancel if a terminating signal was received. Allows user to skip the wait.
|
||||
go func() {
|
||||
utils.WaitForTermination(ctx, cancel)
|
||||
}()
|
||||
|
||||
if err := kubernetesProvider.WaitUtilNamespaceDeleted(ctx, selfResourcesNamespace); err != nil {
|
||||
switch {
|
||||
case ctx.Err() == context.Canceled:
|
||||
log.Printf("Do nothing. User interrupted the wait")
|
||||
log.Warn().
|
||||
Str("namespace", selfResourcesNamespace).
|
||||
Msg("Did nothing. User interrupted the wait.")
|
||||
case err == wait.ErrWaitTimeout:
|
||||
log.Warn().
|
||||
Str("namespace", selfResourcesNamespace).
|
||||
Msg("Timed out while deleting the namespace.")
|
||||
default:
|
||||
log.Warn().
|
||||
Err(errormessage.FormatError(err)).
|
||||
Str("namespace", selfResourcesNamespace).
|
||||
Msg("Unknown error while deleting the namespace.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cleanUpRestrictedMode(ctx context.Context, kubernetesProvider *kubernetes.Provider, selfResourcesNamespace string) []string {
|
||||
leftoverResources := make([]string, 0)
|
||||
|
||||
if err := kubernetesProvider.RemoveService(ctx, selfResourcesNamespace, kubernetes.FrontServiceName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Service %s in namespace %s", kubernetes.FrontServiceName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemoveService(ctx, selfResourcesNamespace, kubernetes.HubServiceName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Service %s in namespace %s", kubernetes.HubServiceName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemovePersistentVolumeClaim(ctx, selfResourcesNamespace, kubernetes.PersistentVolumeClaimName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Persistent Volume %s in namespace %s", kubernetes.PersistentVolumeClaimName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemoveDaemonSet(ctx, selfResourcesNamespace, kubernetes.WorkerDaemonSetName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("DaemonSet %s in namespace %s", kubernetes.WorkerDaemonSetName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if resources, err := kubernetesProvider.ListManagedServiceAccounts(ctx, selfResourcesNamespace); err != nil {
|
||||
resourceDesc := fmt.Sprintf("ServiceAccounts in namespace %s", selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
for _, resource := range resources.Items {
|
||||
if err := kubernetesProvider.RemoveServiceAccount(ctx, selfResourcesNamespace, resource.Name); err != nil {
|
||||
resourceDesc := fmt.Sprintf("ServiceAccount %s in namespace %s", resource.Name, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if resources, err := kubernetesProvider.ListManagedRoles(ctx, selfResourcesNamespace); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Roles in namespace %s", selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
for _, resource := range resources.Items {
|
||||
if err := kubernetesProvider.RemoveRole(ctx, selfResourcesNamespace, resource.Name); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Role %s in namespace %s", resource.Name, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if resources, err := kubernetesProvider.ListManagedRoleBindings(ctx, selfResourcesNamespace); err != nil {
|
||||
resourceDesc := fmt.Sprintf("RoleBindings in namespace %s", selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
} else {
|
||||
for _, resource := range resources.Items {
|
||||
if err := kubernetesProvider.RemoveRoleBinding(ctx, selfResourcesNamespace, resource.Name); err != nil {
|
||||
resourceDesc := fmt.Sprintf("RoleBinding %s in namespace %s", resource.Name, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemovePod(ctx, selfResourcesNamespace, kubernetes.HubPodName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Pod %s in namespace %s", kubernetes.HubPodName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
if err := kubernetesProvider.RemovePod(ctx, selfResourcesNamespace, kubernetes.FrontPodName); err != nil {
|
||||
resourceDesc := fmt.Sprintf("Pod %s in namespace %s", kubernetes.FrontPodName, selfResourcesNamespace)
|
||||
handleDeletionError(err, resourceDesc, &leftoverResources)
|
||||
}
|
||||
|
||||
return leftoverResources
|
||||
}
|
||||
|
||||
func handleDeletionError(err error, resourceDesc string, leftoverResources *[]string) {
|
||||
log.Warn().Err(errormessage.FormatError(err)).Msg(fmt.Sprintf("Error while removing %s", resourceDesc))
|
||||
*leftoverResources = append(*leftoverResources, resourceDesc)
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubeshark/kubeshark/config"
|
||||
"github.com/kubeshark/kubeshark/config/configStructs"
|
||||
"github.com/kubeshark/kubeshark/docker"
|
||||
"github.com/kubeshark/kubeshark/errormessage"
|
||||
"github.com/kubeshark/kubeshark/kubernetes"
|
||||
"github.com/kubeshark/kubeshark/misc"
|
||||
"github.com/rs/zerolog/log"
|
||||
core "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func CreateHubResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, isNsRestrictedMode bool, selfNamespace string, hubResources configStructs.ResourceRequirements, imagePullPolicy core.PullPolicy, imagePullSecrets []core.LocalObjectReference, debug bool) (bool, error) {
|
||||
if !isNsRestrictedMode {
|
||||
if err := createSelfNamespace(ctx, kubernetesProvider, selfNamespace); err != nil {
|
||||
log.Debug().Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
err := kubernetesProvider.CreateSelfRBAC(ctx, selfNamespace)
|
||||
var selfServiceAccountExists bool
|
||||
if err != nil {
|
||||
selfServiceAccountExists = true
|
||||
log.Warn().Err(errormessage.FormatError(err)).Msg(fmt.Sprintf("Failed to ensure the resources required for IP resolving. %s will not resolve target IPs to names.", misc.Software))
|
||||
}
|
||||
|
||||
hubOpts := &kubernetes.PodOptions{
|
||||
Namespace: selfNamespace,
|
||||
PodName: kubernetes.HubPodName,
|
||||
PodImage: docker.GetHubImage(),
|
||||
ServiceAccountName: kubernetes.ServiceAccountName,
|
||||
Resources: hubResources,
|
||||
ImagePullPolicy: imagePullPolicy,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
Debug: debug,
|
||||
}
|
||||
|
||||
frontOpts := &kubernetes.PodOptions{
|
||||
Namespace: selfNamespace,
|
||||
PodName: kubernetes.FrontPodName,
|
||||
PodImage: docker.GetWorkerImage(),
|
||||
ServiceAccountName: kubernetes.ServiceAccountName,
|
||||
Resources: hubResources,
|
||||
ImagePullPolicy: imagePullPolicy,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
Debug: debug,
|
||||
}
|
||||
|
||||
if err := createSelfHubPod(ctx, kubernetesProvider, hubOpts); err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
|
||||
if err := createFrontPod(ctx, kubernetesProvider, frontOpts); err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
|
||||
_, err = kubernetesProvider.CreateService(ctx, selfNamespace, kubernetesProvider.BuildHubService(selfNamespace))
|
||||
if err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
log.Info().Str("service", kubernetes.HubServiceName).Msg("Successfully created a service.")
|
||||
|
||||
_, err = kubernetesProvider.CreateService(ctx, selfNamespace, kubernetesProvider.BuildFrontService(selfNamespace))
|
||||
if err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
log.Info().Str("service", kubernetes.FrontServiceName).Msg("Successfully created a service.")
|
||||
|
||||
if config.Config.Tap.Ingress.Enabled {
|
||||
_, err = kubernetesProvider.CreateIngressClass(ctx, kubernetesProvider.BuildIngressClass())
|
||||
if err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
log.Info().Str("ingress-class", kubernetes.IngressClassName).Msg("Successfully created an ingress class.")
|
||||
|
||||
_, err = kubernetesProvider.CreateIngress(ctx, selfNamespace, kubernetesProvider.BuildIngress())
|
||||
if err != nil {
|
||||
return selfServiceAccountExists, err
|
||||
}
|
||||
log.Info().Str("ingress", kubernetes.IngressName).Msg("Successfully created an ingress.")
|
||||
}
|
||||
|
||||
return selfServiceAccountExists, nil
|
||||
}
|
||||
|
||||
func createSelfNamespace(ctx context.Context, kubernetesProvider *kubernetes.Provider, selfNamespace string) error {
|
||||
_, err := kubernetesProvider.CreateNamespace(ctx, kubernetesProvider.BuildNamespace(selfNamespace))
|
||||
return err
|
||||
}
|
||||
|
||||
func createSelfHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, opts *kubernetes.PodOptions) error {
|
||||
pod, err := kubernetesProvider.BuildHubPod(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = kubernetesProvider.CreatePod(ctx, opts.Namespace, pod); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Str("pod", pod.Name).Msg("Successfully created a pod.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFrontPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, opts *kubernetes.PodOptions) error {
|
||||
pod, err := kubernetesProvider.BuildFrontPod(opts, config.Config.Tap.Proxy.Host, fmt.Sprintf("%d", config.Config.Tap.Proxy.Hub.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = kubernetesProvider.CreatePod(ctx, opts.Namespace, pod); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info().Str("pod", pod.Name).Msg("Successfully created a pod.")
|
||||
return nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user