Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Ignore bazel symlink directories
bazel-bin
bazel-out
bazel-testlogs
bazel-ksniff

# Ignore existing build artifacts
kubectl-sniff
kubectl-sniff-windows
kubectl-sniff-darwin
kubectl-sniff-darwin-arm64
static-tcpdump
ksniff.zip
tcpdump-*
21 changes: 21 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Enable Bzlmod
common --enable_bzlmod

# Common build options
build --incompatible_enable_cc_toolchain_resolution
build --enable_platform_specific_config

# Go specific options
build --@rules_go//go/config:pure

# Platform-specific configurations
build:linux --platforms=@rules_go//go/toolchain:linux_amd64
build:darwin --platforms=@rules_go//go/toolchain:darwin_amd64
build:darwin_arm64 --platforms=@rules_go//go/toolchain:darwin_arm64
build:windows --platforms=@rules_go//go/toolchain:windows_amd64

# Test output
test --test_output=errors

# Performance
build --jobs=auto
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8.4.2
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
*~
.#*

# OS X Desktop Service Store
.DS_Store

.generated

# Build and test process
.coverage
coverage_html

# bzlmod lockfile which is useless:
# "Importantly, it only includes dependencies that are included in the current invocation of the build"
/MODULE.bazel.lock

/bazel-*

# Local bazel overrides
.bazelrc-local

# Go
go.mod
go.sum
!/go.mod
!/go.sum
88 changes: 88 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright (C) 2021 Cisco Systems, Inc.

# See CONTRIBUTING.md for instructions.
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
#
# Hook naming convention - prefixes by category (run order):
# Format: - Code formatters that modify files
# Deps: - Dependency/lockfile hygiene (go mod tidy, pip-compile, tfupdate)
# Lint: - Static analysis/linting (read-only checks)
# Files: - File hygiene checks (whitespace, symlinks, text normalization)
# License: - Copyright/license checks
# SAST: - Security static analysis (secrets, config scanning, code analysis)
# Vuln: - Dependency vulnerability scanning

repos:
# ============================================================================
# FORMAT: Code formatters (modify files)
# ============================================================================
- repo: https://github.com/keith/pre-commit-buildifier
rev: 8.2.1
hooks:
- id: buildifier
name: "Format: buildifier"
args:
# Keep this argument in sync with .bazelci/presubmit.yml and the buildifier-lint hook in LINT section
- --warnings=-bzl-visibility,-function-docstring-args,-function-docstring-return,-print,-unnamed-macro,-provider-params,-function-docstring-header,-no-effect,-uninitialized,-rule-impl-return

# ============================================================================
# LINT: Static analysis (read-only checks)
# ============================================================================
- repo: https://github.com/keith/pre-commit-buildifier
rev: 8.2.1
hooks:
- id: buildifier-lint
name: "Lint: buildifier-lint"
args:
# Keep this argument in sync with the buildifier hook in FORMAT section
- --warnings=-bzl-visibility,-function-docstring-args,-function-docstring-return,-print,-unnamed-macro,-provider-params,-function-docstring-header,-no-effect,-uninitialized,-rule-impl-return

- repo: https://github.com/syntaqx/git-hooks
rev: v0.0.18
hooks:
- id: shellcheck
name: "Lint: shellcheck"
exclude: "aws_launch_template_.*"

- repo: git@github.com:omnicate/pre-commit-policy-bot.git
rev: v0.0.2
hooks:
- id: validate
name: "Lint: policy-bot-validate"

# ============================================================================
# FILES: File hygiene checks
# ============================================================================
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
name: "Files: trailing-whitespace"
args: [--markdown-linebreak-ext=md]
# provisioning-tools has test fixtures with significant formatting
exclude: "connectivity/provisioning-tools/src/test/kotlin/io/omnicate/connectivity/tools/(ImportSimCardsTest|mvno/MappingTest).kt"
- id: check-merge-conflict
name: "Files: check-merge-conflict"
- id: end-of-file-fixer
name: "Files: end-of-file-fixer"
exclude: ".*\\.svg$|voice/li/test/data/.*\\.bin$|copyright.txt|vendor-images/README.md"
- id: check-executables-have-shebangs
name: "Files: check-executables-have-shebangs"
- id: check-shebang-scripts-are-executable
name: "Files: check-shebang-scripts-are-executable"
exclude: "aws_launch_template_.*"
- id: check-symlinks
name: "Files: check-symlinks"
- id: destroyed-symlinks
name: "Files: destroyed-symlinks"

- repo: https://github.com/sirosen/texthooks
rev: 0.7.1
hooks:
- id: fix-smartquotes
name: "Files: fix-smartquotes"
exclude: ".+\\.vue$|.+\\.vm|.+\\.java|.+\\.kt|.+\\.xml|.+\\.json|.+\\.sql|.*.gen.go$"
- id: fix-ligatures
name: "Files: fix-ligatures"
exclude: ".+\\.vue$|.+\\.vm|.+\\.java|.+\\.kt|.+\\.xml|.+\\.json|.+\\.sql|.*.gen.go$"
81 changes: 81 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
load("@gazelle//:def.bzl", "gazelle")
load("@rules_go//go:def.bzl", "go_binary")

# gazelle:prefix ksniff
gazelle(name = "gazelle")

# Linux binary
go_binary(
name = "kubectl-sniff-linux",
embed = ["//cmd:kubectl-sniff_lib"],
goarch = "amd64",
goos = "linux",
pure = "on",
visibility = ["//visibility:public"],
)

# Darwin (macOS) binary - amd64
go_binary(
name = "kubectl-sniff-darwin",
embed = ["//cmd:kubectl-sniff_lib"],
goarch = "amd64",
goos = "darwin",
pure = "on",
visibility = ["//visibility:public"],
)

# Darwin (macOS) binary - arm64
go_binary(
name = "kubectl-sniff-darwin-arm64",
embed = ["//cmd:kubectl-sniff_lib"],
goarch = "arm64",
goos = "darwin",
pure = "on",
visibility = ["//visibility:public"],
)

# Windows binary
go_binary(
name = "kubectl-sniff-windows",
embed = ["//cmd:kubectl-sniff_lib"],
goarch = "amd64",
goos = "windows",
pure = "on",
visibility = ["//visibility:public"],
)

# Default binary for current platform
go_binary(
name = "kubectl-sniff",
embed = ["//cmd:kubectl-sniff_lib"],
pure = "on",
visibility = ["//visibility:public"],
)

# Static tcpdump binary
# This target builds a statically-linked tcpdump binary from source.
# On Linux: Builds a fully static tcpdump binary (equivalent to Makefile's static-tcpdump target)
# On macOS/other: Creates a placeholder script explaining that this must be built on Linux
#
# Usage:
# bazel build //:static-tcpdump
#
# The binary will be available at:
# bazel-bin/external/+_repo_rules+tcpdump/tcpdump_bin
alias(
name = "static-tcpdump",
actual = "@tcpdump//:tcpdump_bin",
visibility = ["//visibility:public"],
)

# Filegroup for all binaries
filegroup(
name = "all-binaries",
srcs = [
":kubectl-sniff-darwin",
":kubectl-sniff-darwin-arm64",
":kubectl-sniff-linux",
":kubectl-sniff-windows",
],
visibility = ["//visibility:public"],
)
38 changes: 38 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module(
name = "ksniff",
version = "0.0.0",
)

bazel_dep(name = "rules_go", version = "0.59.0")
bazel_dep(name = "gazelle", version = "0.47.0")
bazel_dep(name = "platforms", version = "1.0.0")

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.25.7")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")

# Use all Go dependencies
use_repo(go_deps, "com_github_mitchellh_go_homedir")
use_repo(go_deps, "com_github_pkg_errors")
use_repo(go_deps, "com_github_sirupsen_logrus")
use_repo(go_deps, "com_github_spf13_cobra")
use_repo(go_deps, "com_github_spf13_pflag")
use_repo(go_deps, "com_github_spf13_viper")
use_repo(go_deps, "com_github_stretchr_testify")
use_repo(go_deps, "io_k8s_api")
use_repo(go_deps, "io_k8s_apimachinery")
use_repo(go_deps, "io_k8s_cli_runtime")
use_repo(go_deps, "io_k8s_client_go")

# HTTP archive for tcpdump
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "tcpdump",
build_file = "//:tcpdump.BUILD",
sha256 = "798b3536a29832ce0cbb07fafb1ce5097c95e308a6f592d14052e1ef1505fe79",
strip_prefix = "tcpdump-4.9.2",
urls = ["https://www.tcpdump.org/release/tcpdump-4.9.2.tar.gz"],
)
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Ksniff [isn't production ready yet](https://github.com/eldadru/ksniff/issues/96#
Installation via krew (https://github.com/GoogleContainerTools/krew)

kubectl krew install sniff
For manual installation, download the latest release package, unzip it and use the attached makefile:

For manual installation, download the latest release package, unzip it and use the attached makefile:

unzip ksniff.zip
make install
Expand All @@ -42,11 +42,11 @@ Requirements:
2. go 1.11 or newer

Compiling:

linux: make linux
windows: make windows
mac: make darwin


To compile a static tcpdump binary:

Expand All @@ -56,10 +56,10 @@ To compile a static tcpdump binary:

kubectl < 1.12:
kubectl plugin sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]

kubectl >= 1.12:
kubectl sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]

POD_NAME: Required. the name of the kubernetes pod to start capture it's traffic.
NAMESPACE_NAME: Optional. Namespace name. used to specify the target namespace to operate on.
CONTAINER_NAME: Optional. If omitted, the first container in the pod will be chosen.
Expand All @@ -71,9 +71,16 @@ To compile a static tcpdump binary:

#### Air gapped environments
Use `--image` and `--tcpdump-image` flags (or KUBECTL_PLUGINS_LOCAL_FLAG_IMAGE and KUBECTL_PLUGINS_LOCAL_FLAG_TCPDUMP_IMAGE environment variables) to override the default container images and use your own e.g (docker):

kubectl plugin sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] --image <PRIVATE_REPO>/docker --tcpdump-image <PRIVATE_REPO>/tcpdump


#### Private registry with imagePullSecret
If your custom images are stored in a private registry that requires authentication, you can specify an imagePullSecret using the `--image-pull-secret` flag (or KUBECTL_PLUGINS_LOCAL_FLAG_IMAGE_PULL_SECRET environment variable):

kubectl plugin sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] --image <PRIVATE_REPO>/docker --tcpdump-image <PRIVATE_REPO>/tcpdump --image-pull-secret <SECRET_NAME>

The secret must exist in the same namespace where the ksniff privileged pod will be created.


#### Non-Privileged and Scratch Pods
To reduce attack surface and have small and lean containers, many production-ready containers runs as non-privileged user
Expand All @@ -82,7 +89,7 @@ or even as a scratch container.
To support those containers as well, ksniff now ships with the "-p" (privileged) mode.
When executed with the -p flag, ksniff will create a new pod on the remote kubernetes cluster that will have access to the node docker daemon.

ksniff will than use that pod to execute a container attached to the target container network namespace
ksniff will than use that pod to execute a container attached to the target container network namespace
and perform the actual network capture.

#### Piping output to stdout
Expand All @@ -94,12 +101,12 @@ Example using `tshark`:
kubectl sniff pod-name -f "port 80" -o - | tshark -r -

### Contribution
More than welcome! please don't hesitate to open bugs, questions, pull requests
More than welcome! please don't hesitate to open bugs, questions, pull requests

### Future Work
1. Instead of uploading static tcpdump, use the future support of "kubectl debug" feature
(https://github.com/kubernetes/community/pull/649) which should be a much cleaner solution.

### Known Issues

#### Wireshark and TShark cannot read pcap
Expand Down
14 changes: 14 additions & 0 deletions README_golang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Go dependencies

For the following commands its recommended to use the Bazel target `rules_go//go`, ensuring a consistent Go version.

In order to add a dependency, you need to:
1. add it to the global `go.mod` using `bazel run @rules_go//go -- get name@version`. To view the latest version, run `go list -m -versions name`.
2. run `bazel run @rules_go//go -- mod tidy`.

Since this will update dependencies for _all_ Go programs in the
monorepo, you should retest all the Go dependencies afterwards:

```
bazel test $(bazel query 'kind(go_.*, //...) except attr("tags", "manual", //...)')
```
13 changes: 13 additions & 0 deletions cmd/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "kubectl-sniff_lib",
srcs = ["kubectl-sniff.go"],
importpath = "ksniff/cmd",
visibility = ["//visibility:public"],
deps = [
"//pkg/cmd",
"@com_github_spf13_pflag//:pflag",
"@io_k8s_cli_runtime//pkg/genericclioptions",
],
)
Loading