* auth: drop AUTH_ROLES; add AUTH_GROUP_MAPPING + built-in defaultRole
Companion to kubeshark/hub#permissions-refactoring. Aligns the CLI
config struct, chart values, and rendered ConfigMap with the
post-refactor hub.
config/configStructs/tapConfig.go:
- Drop AuthConfig.Roles (admin-authored map[string]Role) and the
Role + ScriptingPermissions structs they referenced.
- Drop AuthConfig.DefaultFilter (no namespace scoping in v1).
- Add AuthConfig.GroupMapping (map[string]string) — SSO group name
→ built-in role translation.
- Tighten DefaultRole godoc to reference the four built-in role
constants (kubeshark-admin / kubeshark-realtime /
kubeshark-snapshot / kubeshark-viewer) and the strict-deny
semantics on empty.
config/configStruct.go:
- Drop the legacy "admin" entry from the AuthConfig default —
operators now configure DefaultRole + GroupMapping instead.
- Default RolesClaim is now "groups" (Okta/OIDC convention; was
"role"), matching the hub's runtime default.
helm-chart/templates/12-config-map.yaml:
- Drop AUTH_ROLES emission (key no longer read by hub).
- Add AUTH_GROUP_MAPPING emission from tap.auth.groupMapping (JSON
map; hub validates each value against the built-in role names at
sync time).
helm-chart/values.yaml: regenerated from the Go config — drops the
tap.auth.roles block, adds tap.auth.groupMapping with the new
documentation header for DefaultRole.
Breaking change: deployments carrying tap.auth.roles in their values
will silently lose those role definitions. Migration is to remove the
roles: block and either (a) name their SSO groups to match the four
built-in role constants, or (b) populate tap.auth.groupMapping with
explicit translations.
* auth: set helm default role to kubeshark-viewer
Per round-2 permissions clarifications: SSO users whose claim doesn't
match any built-in role and isn't in AUTH_GROUP_MAPPING should fall
back to a read-only baseline instead of strict-deny ("").
defaultRole="" causes the dashboard to 403-storm gated endpoints from
unmatched users; viewer (snapshot:read only) gives them a sensible
read-only UX while still preventing any state change.
* auth: add tap.auth.roles operator-defined role catalogue
Chart-side companion to hub commit 67162b2e (Phase C of the permissions
refactor). Operators can now declare named roles with their own
capability set + namespace scope under tap.auth.roles; the
12-config-map renders these as AUTH_ROLES JSON for the hub to consume.
- config/configStructs: AuthConfig.Roles map[string]RoleConfig with
Capabilities + Namespaces; doc comments updated for groupMapping +
defaultRole to reflect that user-defined names are now accepted.
- config/configStruct.go: zero-value initializer for Roles so
`kubeshark config` renders `roles: {}` consistently.
- helm-chart/templates/12-config-map.yaml: AUTH_ROLES emits the
full roles map as JSON; hub-side syncAuthRoles validates names
(kubeshark-* prefix reserved) and capabilities (unknown caps
warn-dropped).
- helm-chart/values.yaml: regenerated. Diff is the single `roles: {}`
line under tap.auth.
Spot-checked the rendered ConfigMap:
AUTH_ROLES: '{"payments-viewer":{"capabilities":["snapshot:read",
"dissection:live"],
"namespaces":"payments"}}'
which is exactly the shape the hub parser expects.
* auth: emit CHART_VERSION into hub ConfigMap (Phase V)
Hub commit 51abc954 reads this key on first SyncConfig and warns when
its embedded version.Ver disagrees with the chart at the major
component. Provided alongside as the chart-side companion to keep
both sides on one PR per repo on the permissions-refactoring branch.
* Revert "auth: emit CHART_VERSION into hub ConfigMap (Phase V)"
This reverts c21e4c42. Companion to hub revert 61a275b6 — the hub no
longer reads CHART_VERSION, so emitting it serves no purpose.
* chore: drop internal plan ref from auth config comment
Plans live as local working docs, not in the repo — strip the cross-repo
plans/permissions-decisions.md reference from the AuthConfig.Roles comment.
* cli: authenticate Hub HTTP requests with License-Key (gated-auth phase 1)
Add a License-Key RoundTripper plus NewHubHTTPClient / HubAuthTransport
helpers in utils, and route the MCP runner's Hub clients (connect, --url
validate, file download, tools list) through them so the CLI keeps working
once the Hub enforces auth. License-Key is a custom header, so it survives
the kube API-server service proxy (a bearer token would not). Surface
ErrHubAuthRequired on a 401/302 from the Hub.
console already sends License-Key on its ws connection. pprof is not
covered here: it shells out to 'go tool pprof <hubUrl>' / opens a browser,
external fetches that can't carry a custom header (follow-up).
* cli: mint a ServiceAccount token for gated Hub auth (phase 2a)
Provider.MintHubToken requests a short-lived token (audience kubeshark-hub)
for the kubeshark-cli ServiceAccount via the TokenRequest API. The Hub
client now prefers that token via the X-Kubeshark-Authorization custom
header (which survives the kube API-server proxy), falling back to
License-Key when minting isn't possible (--url mode, SA missing, or no
RBAC to mint). The MCP runner mints once at startup.
Pairs with hub branch cli-sa-auth. Needs the helm kubeshark-cli SA + RBAC
and the hub AUTH_CLI_SERVICE_ACCOUNTS allowlist to validate end-to-end.
* cli: authenticate console ws with the ServiceAccount token (phase 2a)
console mints the kubeshark-cli token like the MCP runner and sends it via
X-Kubeshark-Authorization, falling back to License-Key when minting isn't
possible.
* helm: kubeshark-cli ServiceAccount + token-minter RBAC + allowlist (phase 2a)
When tap.auth.cli.enabled, create the kubeshark-cli ServiceAccount and a
Role granting 'create' on serviceaccounts/token for it (bound to
configurable tap.auth.cli.subjects), and set AUTH_CLI_SERVICE_ACCOUNTS so
the Hub allowlists it. Binding the Role to a subject is what grants that
subject CLI access to a gated Hub.
* helm: render AUTH_GROUP_MAPPING in the hub config-map
The local chart never rendered AUTH_GROUP_MAPPING, so tap.auth.groupMapping
was silently dropped — SSO groups and the kubeshark-cli SA fell back to
AUTH_DEFAULT_ROLE instead of their mapped roles.
* helm: project kubeshark-hub SA token onto worker for internalauth (gated-auth)
The worker seeds its name-resolution map and capture targets via plain
HTTP GETs to the hub (/resolver/history, /pods/targeted, /pods/all). With
auth enabled these routes sit behind Auth() and return 401, leaving the
worker with an empty resolver map (all traffic shows unresolved).
Project a short-lived SA token (audience kubeshark-hub) onto the sniffer
container and expose its path via HUB_INTERNAL_TOKEN_PATH so the worker
presents it as a Bearer to the hub's internalauth gate. Gated on
tap.auth.enabled; auth-disabled clusters are unchanged.
* cli/mcp: auto-renew hub token in proxy mode; explicit token + clear expiry in --url mode
The MCP server minted a hub SA token once at startup and reused it for
the life of the process, so a long-running server 401'd silently after
the ~1h token TTL.
- utils/http: the hub round-tripper now sources the SA token via a
func() string per request (static constructors preserved), so a
renewing source keeps long-lived clients authenticated.
- kubernetes: add HubTokenRenewer — re-mints the kubeshark-cli token
before expiry (using the TokenRequest expiry, 5m margin), concurrency-safe.
- mcp proxy mode: use the renewer so the token auto-renews.
- mcp --url mode: cannot mint (no kube access) — accept an explicit
--token / KUBESHARK_HUB_TOKEN, and on 401 surface a clear 'token
expired/invalid, re-mint and restart' message instead of an opaque
API error.
console is intentionally untouched (non-functional pending the
Connect-RPC re-point); it gets renewal when that migration lands.
* cli/mcp: throttle hub-token re-mint on failure; accurate proxy 401 message
Review follow-up. HubTokenRenewer.Token() re-minted on every request while
the token was empty, so a cluster where minting can't succeed (no RBAC, SA
missing) paid a blocking ~10s CreateToken round-trip per request (under the
lock). Add a 30s retry throttle: on mint failure, back off and fall back to
the prior token / License-Key. Also correct the proxy-mode 401 message — a
token-bearing 401 means the minted token was rejected (allowlist/audience),
not an RBAC-to-mint failure.
* cli/mcp: authenticate --list-tools with the hub token source
fetchAndDisplayTools used a no-token client, so 'kubeshark mcp
--list-tools' 401'd against a gated Hub even with a valid --token. Factor
the proxy/url token-source selection into hubTokenSource() (reused by
runMCPWithConfig) and pass it through to fetchAndDisplayTools, which now
also reports a clear 401 instead of an opaque parse error.
* docs(mcp): document gated-Hub auth — --token for URL mode, proxy auto-renew
Explain that proxy mode mints and auto-renews the kubeshark-cli token, URL
mode needs an explicit --token / KUBESHARK_HUB_TOKEN (can't auto-renew) and
reports a clear 401 on expiry. Add --token to the CLI options table.
* cli/mcp: address Copilot review (token fallback, SSO redirects, messages)
- hubtoken: HubTokenRenewer.Token() no longer hands out an already-expired
token on mint failure — returns "" so the round-tripper falls back to the
License-Key instead of looping on 401s.
- utils/http: hub clients no longer follow SSO redirects (StopOnSSORedirect
CheckRedirect on 302/303), and IsAuthRequired covers 302+303, so auth
detection is reliable instead of silently following to an HTML login page.
- mcpRunner: fetchHubMCP/callHubTool/fetchAndDisplayTools/callDownloadFile
use utils.IsAuthRequired (401 + unfollowed redirect) instead of bare 401;
download path checks it before writing the body to disk; URL-mode auth
message now also mentions the License-Key fallback.
* Merge branch 'master' into gated-auth
Conflicts were in the helm chart's auth config, where master's permissions
refactor (fcceed23) reordered the AUTH_* config-map keys and replaced the
inline tap.auth.roles tree with roles/rolesClaim/defaultRole/groupMapping —
directly alongside gated-auth's new CLI ServiceAccount-token auth. Neither
side removed the other's work, so both are kept.
Also promote tap.auth.cli to a real config field. It had been hand-written
into helm-chart/values.yaml, which is generated by `make generate-helm-values`
(bin/kubeshark__ config > helm-chart/values.yaml). The next regeneration would
have silently dropped the key, leaving 22-cli-auth.yaml unable to render the
ServiceAccount. Add CliAuthConfig/CliAuthSubject to AuthConfig and regenerate
values.yaml from source, so the block now round-trips.
Subject fields carry omitempty so User/Group entries don't emit an empty
namespace and ServiceAccount entries don't emit an empty apiGroup, keeping
the rendered RoleBinding idiomatic.
values.yaml is generated and cannot hold comments, so the tap.auth.cli docs
live in helm-chart/README.md alongside the other tap.auth.* rows. Drop the
internal plan phase labels from the CLI and utils comments; phases exist only
in local planning docs.
---------
Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
* cli: mark 'console' as non-functional / under refactoring
Hub PR #464 moved scripting-console log streaming off the /scripts/logs
WebSocket onto a Connect-RPC streaming service (ScriptLogsDashboard).
The console command still dials ws://.../api/scripts/logs, a route the
hub no longer serves, so it never streams and spins in its reconnect
loop. Surface this in the command help (Short/Long) and as a runtime
warning until the client is re-pointed at the Connect-RPC stream.
* cli: early-exit 'console' while under refactoring
Instead of warning and then entering the (now broken) reconnect loop, the
console command logs the under-refactoring notice and returns immediately
so users don't get stuck in a spinning client that never streams.
* cli: silence unused linter on retained console helpers
---------
Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
* Reapply "Add get_file_url and download_file MCP tools"
This reverts commit a46f05c4aa.
* Use dedicated HTTP client for file downloads to support large files
The default httpClient has a 30s total timeout that would fail for
large PCAP downloads (up to 10GB). Use a separate client with only
connection-level timeouts (TLS handshake, response headers) so the
body can stream without a deadline.
Allow users to specify a local Helm chart folder via CLI flag or config,
which takes precedence over the KUBESHARK_HELM_CHART_PATH env variable and
the remote Helm repo. Also update nginx proxy config to disable buffering
for better streaming and large snapshot support.
When tools like export_snapshot_pcap return a relative file path,
the MCP client needs a way to resolve it to a full URL or download
the file locally. These two new tools bridge that gap.
The Hub API expects 'name' field but the MCP server was sending 'tool'.
This caused all Hub-forwarded tools (list_l4_flows, get_l4_flow_summary,
list_api_calls, etc.) to fail with 'tool name is required' error.
Local tools like check_kubeshark_status were unaffected as they don't
call the Hub API.
* Add MCP (Model Context Protocol) server command
Implement `kubeshark mcp` command that runs an MCP server over stdio,
enabling AI assistants to query Kubeshark's network visibility data.
Features:
- MCP protocol implementation (JSON-RPC 2.0 over stdio)
- Dynamic tool discovery from Hub's /api/mcp endpoint
- Local cluster management tools (check_kubeshark_status, start_kubeshark, stop_kubeshark)
- --url flag for direct connection to existing Kubeshark deployment
- --kubeconfig flag for proxy mode with kubectl
- --allow-destructive flag to enable start/stop operations (safe by default)
- --list-tools flag to display available tools
- --mcp-config flag to generate MCP client configuration
- 5-minute cache TTL for Hub tools/prompts
- Prompts for common analysis tasks
* Address code review comments for MCP implementation
- Add 30s timeout to HTTP client to prevent hanging requests
- Add scanner.Err() check after stdin processing loop
- Close HTTP response bodies to prevent resource leaks
- Add goroutine to wait on started process to prevent zombies
- Simplify polling loop by removing ineffective context check
- Advertise check_kubeshark_status in URL mode (was callable but hidden)
- Update documentation to clarify URL mode only disables start/stop
* Fix lint errors in mcpRunner.go
- Use type conversion instead of struct literals for hubMCPTool -> mcpTool
and hubMCPPromptArg -> mcpPromptArg (S1016 gosimple)
- Lowercase error string to follow Go conventions (ST1005 staticcheck)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add MCP server unit tests
Comprehensive unit tests for the MCP server implementation:
- Protocol tests (initialize, tools/list, tools/call, prompts/list, prompts/get)
- Tool tests (check_kubeshark_status, start_kubeshark, stop_kubeshark)
- Hub integration tests (tool fetching, caching, prompt handling)
- Error handling tests
- Edge case tests
* Fix MCP unit tests to use correct /tools/call endpoint
- Update all Hub tool tests to use POST /tools/call endpoint instead
of individual paths like /workloads, /calls, /stats
- Verify arguments in POST body instead of URL query parameters
- Add newMockHubHandler helper for proper Hub endpoint mocking
- Split TestMCP_ToolsList into three tests:
- TestMCP_ToolsList_CLIOnly: Tests without Hub backend
- TestMCP_ToolsList_WithDestructive: Tests with destructive flag
- TestMCP_ToolsList_WithHubBackend: Tests with mock Hub providing tools
- Fix TestMCP_FullConversation to mock Hub MCP endpoint correctly
- Rename URL encoding tests for clarity
- All tests now correctly reflect the implementation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Simplify MCP unit tests
- Remove section header comments (10 headers)
- Consolidate similar tests using table-driven patterns
- Simplify test assertions with more concise checks
- Combine edge case tests into single test function
- Reduce verbose test structures
Total reduction: 1477 → 495 lines (66%)
All 24 tests still pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add MCP integration test framework
Add integration tests that run against a real Kubernetes cluster:
- MCP protocol tests (initialize, tools/list, prompts/list)
- Cluster management tests (check_kubeshark_status, start_kubeshark, stop_kubeshark)
- Full lifecycle test (check -> start -> check -> stop -> check)
- API tools tests (list_workloads, list_api_calls, get_api_stats)
Also includes:
- Makefile targets for running integration tests
- Test helper functions (startMCPSession, cleanupKubeshark, etc.)
- Documentation (README.md, TEMPLATE.md, ISSUE_TEMPLATE.md)
* Address review comments on integration tests
Makefile:
- Use unique temporary files (mktemp) instead of shared /tmp/integration-test.log
to prevent race conditions when multiple test targets run concurrently
- Remove redundant test-integration-verbose target (test-integration already uses -v)
- Add cleanup (rm -f) for temporary log files
integration/mcp_test.go:
- Capture stderr from MCP server for debugging failures
- Add getStderr() method to mcpSession for accessing captured stderr
- Fix potential goroutine leak by adding return statements after t.Fatalf
- Remove t.Run subtests in TestMCP_APIToolsRequireKubeshark to clarify
sequential execution with shared session
- Fix benchmark to use getKubesharkBinary helper for consistency
- Add Kubernetes cluster check to benchmark (graceful skip)
- Add proper error handling for pipe creation in benchmark
- Remove unnecessary bytes import workaround (now actually used for stderr)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Simplify and clean up MCP integration tests
- Remove unrelated L4 viewer files (1239 lines)
- Remove template/issue documentation files (419 lines)
- Trim README to essential content only
- Remove TEMPLATE comments from common_test.go
- Add initialize() helper to reduce test boilerplate
- Add hasKubernetesCluster() helper for benchmarks
- Simplify all test functions with consistent patterns
Total reduction: 2964 → 866 lines (71%)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add MCP registry metadata for official registry submission
Add metadata files for submitting Kubeshark MCP server to the official
MCP registry at registry.modelcontextprotocol.io:
- mcp/server.json: Registry metadata with tools, prompts, and configuration
- mcp/README.md: MCP server documentation and usage guide
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add MCP (Model Context Protocol) server command
Implement `kubeshark mcp` command that runs an MCP server over stdio,
enabling AI assistants to query Kubeshark's network visibility data.
Features:
- MCP protocol implementation (JSON-RPC 2.0 over stdio)
- Dynamic tool discovery from Hub's /api/mcp endpoint
- Local cluster management tools (check_kubeshark_status, start_kubeshark, stop_kubeshark)
- --url flag for direct connection to existing Kubeshark deployment
- --kubeconfig flag for proxy mode with kubectl
- --allow-destructive flag to enable start/stop operations (safe by default)
- --list-tools flag to display available tools
- --mcp-config flag to generate MCP client configuration
- 5-minute cache TTL for Hub tools/prompts
- Prompts for common analysis tasks
* Address code review comments for MCP implementation
- Add 30s timeout to HTTP client to prevent hanging requests
- Add scanner.Err() check after stdin processing loop
- Close HTTP response bodies to prevent resource leaks
- Add goroutine to wait on started process to prevent zombies
- Simplify polling loop by removing ineffective context check
- Advertise check_kubeshark_status in URL mode (was callable but hidden)
- Update documentation to clarify URL mode only disables start/stop
* Fix lint errors in mcpRunner.go
- Use type conversion instead of struct literals for hubMCPTool -> mcpTool
and hubMCPPromptArg -> mcpPromptArg (S1016 gosimple)
- Lowercase error string to follow Go conventions (ST1005 staticcheck)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* 🚑 Migrate to `kubehq.com` in helm values
* 🚑 Migrate to `kubehq.com` in cloud-api-url envs
* 🚑 Migrate to `kubehq.com` in manifest label keys
* 🚑 Migrate to `kubehq.com` in `Chart.yaml`
* 🚑 Migrate to `kubehq.com` in helm-chart notes/readme
* Fix spammy logs
* Fix err related to value missing from pcap config
* Test target dir only when provided
* Improve consistency of error handling
* Remove obsolete code
---------
Co-authored-by: bogdan.balan1 <bogdanvalentin.balan@1nce.com>
* First commit in this PR
Added `scripting.active` as a helm value
* added `scripting.active` to the config struct and the helm chart
this array of strings will include the active script titles
* updated the `active` filed in the script struct
* go mod tidy
* update go ver to 1.21.1
Added both the `scripting` and `console` commands to the `proxy` command
Added a `scripting.console`, a boolean value indicating whether the `console`
functionality should be part of the `tap` and `proxy` commands
* Add cmd to copy pcaps from worker
* Update commands to merge pcaps
* Remove test img
* Remove usage of http endpoint in copy
* Unify commands
* Add copy flag
* Address review comments
* Update k8s config path processing
* Remove debug prints
* setting the pcapSrcDit to the name of the command
* Update values.yaml
* Remove the start,stop and copy flags
* Clean up the the code a bit
Changed the logic so it's either copy or start/stop.
Works well for a first version.
* Improved the logic
* Changed pcapdump enable flag to boolean
* Added helm value documentation
* minor default configuration changes
* Fix default val for enabled
* Final changes
Cleaned up the helm worker template
Improve the logic a bit
* Code cleanup
Changed instances of `enable` to `enabled` for purpose of consistency
Removed unused helm environment variables
* Enable merging all node files to a single file.
Before the outcome had been a merged file per node.
Now the outcome is a single merged file for all nodes.
* Committed for testing purpose
* Reduced the initial disk foot print to 10MB per node
---------
Co-authored-by: bogdan.balan1 <bogdanvalentin.balan@1nce.com>
Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
* Make the `scritps` command directly use the K8s API without requiring a connector to Hub
* Fix linter
* Fix linter
---------
Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
* Add hub to the list of containers in `pprof` command and add flags to `pprof` command
* Reduce duplication
---------
Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
* Add `X-Kubeshark-Capture: ignore` header to all of the HTTP requests
* Add `X-Kubeshark-Capture: ignore` header to WebSocket requests
* Reduce duplication