Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:ojkastl_buildservice:Branch_devel_kubic
kubeshark-cli
kubeshark-cli-52.3.82.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kubeshark-cli-52.3.82.obscpio of Package kubeshark-cli
07070100000000000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001E00000000kubeshark-cli-52.3.82/.github07070100000001000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002D00000000kubeshark-cli-52.3.82/.github/ISSUE_TEMPLATE07070100000002000081A400000000000000000000000166E627D70000042C000000000000000000000000000000000000003B00000000kubeshark-cli-52.3.82/.github/ISSUE_TEMPLATE/bug_report.md--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **Provide more information** Running on EKS, AKS, GKE, Minikube, Rancher, OpenShift? Number of Nodes? CNI? **To Reproduce** Steps to reproduce the behavior: 1. Run `kubeshark <command> ...` 2. Click on '...' 3. Scroll down to '...' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Logs** Upload logs: 1. Run the kubeshark command with `--set dump-logs=true` (e.g `kubeshark tap --set dump-logs=true`) 2. Try to reproduce the issue 3. <kbd>CTRL</kbd>+<kbd>C</kbd> on terminal tab which runs `kubeshark` 4. Upload the logs zip file from `~/.kubeshark/kubeshark_logs_**.zip` **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. macOS] - Web Browser: [e.g. Google Chrome] **Additional context** Add any other context about the problem here. 07070100000003000081A400000000000000000000000166E627D7000006F0000000000000000000000000000000000000004100000000kubeshark-cli-52.3.82/.github/ISSUE_TEMPLATE/feature_request.ymlname: Feature request description: Request a new feature or an improvement to an existing one title: "[Feature Request:]" labels: ["enhancement"] assignees: - alongir body: - type: markdown attributes: value: | Thanks for taking the time to request a new feature! - type: input id: contact attributes: label: Contact Details description: How can we get in touch with you if we need more info? placeholder: ex. email@example.com validations: required: false - type: textarea id: the-problem attributes: label: Is your feature request related to a problem? Please describe. description: Please describe the problem you are trying to solve validations: required: true - type: input id: original-thread attributes: label: Original Thread description: A link to the original discussion thread (e.g. Slack, Discord, Email, Verbal) validations: required: false - type: textarea id: the-solution attributes: label: Describe the solution you'd like to see description: A clear and concise description of what you want to happen. validations: required: false - type: textarea id: the-context attributes: label: Provide additional context description: Add any other context or screenshots about the feature request here. validations: required: false - type: checkboxes id: terms attributes: label: Code of Conduct description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/kubeshark/kubeshark/blob/master/docs/CODE_OF_CONDUCT.md) options: - label: I agree to follow this project's Code of Conduct required: true 07070100000004000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/.github/static07070100000005000081A400000000000000000000000166E627D70000051F000000000000000000000000000000000000003700000000kubeshark-cli-52.3.82/.github/static/kubeshark.rb.tmpl# 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 07070100000006000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002800000000kubeshark-cli-52.3.82/.github/workflows07070100000007000081A400000000000000000000000166E627D70000045C000000000000000000000000000000000000003100000000kubeshark-cli-52.3.82/.github/workflows/helm.ymlon: 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 jobs: release: # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token permissions: contents: write runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 - name: Configure Git run: | git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - name: Install Helm uses: azure/setup-helm@v3 - name: Run chart-releaser uses: helm/chart-releaser-action@v1.5.0 with: charts_dir: . charts_repo_url: https://kubeshark.github.io/kubeshark env: CR_TOKEN: "${{ secrets.HELM_TOKEN }}" 07070100000008000081A400000000000000000000000166E627D700000224000000000000000000000000000000000000003300000000kubeshark-cli-52.3.82/.github/workflows/linter.ymlon: push: branches: - master pull_request: branches: - master name: Linter permissions: contents: read jobs: golint: name: Golint runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 2 - name: Set up Go uses: actions/setup-go@v4 with: go-version-file: 'go.mod' - name: Go lint uses: golangci/golangci-lint-action@v3 with: version: latest args: --timeout=10m 07070100000009000081A400000000000000000000000166E627D700000747000000000000000000000000000000000000003400000000kubeshark-cli-52.3.82/.github/workflows/release.ymlon: push: # Sequence of patterns matched against refs/tags tags: - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 name: Release concurrency: group: kubeshark-publish-${{ github.ref }} cancel-in-progress: true 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 - name: Set up Go uses: actions/setup-go@v4 with: go-version-file: 'go.mod' - 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: Build run: make build-all VER='${{ steps.version.outputs.tag }}' BUILD_TIMESTAMP='${{ steps.version.outputs.build_timestamp }}' - name: Log the version into a .txt file shell: bash run: | echo '${{ steps.version.outputs.tag }}' >> bin/version.txt - name: Release uses: ncipollo/release-action@v1 with: token: ${{ secrets.GITHUB_TOKEN }} artifacts: "bin/*" tag: ${{ steps.version.outputs.tag }} prerelease: false bodyFile: 'bin/README.md' brew: name: Publish a new Homebrew formulae needs: [release] runs-on: ubuntu-latest steps: - name: Bump core homebrew formula uses: mislav/bump-homebrew-formula-action@v3 with: # A PR will be sent to github.com/Homebrew/homebrew-core to update this formula: formula-name: kubeshark push-to: kubeshark/homebrew-core env: COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }} 0707010000000A000081A400000000000000000000000166E627D70000023B000000000000000000000000000000000000003100000000kubeshark-cli-52.3.82/.github/workflows/test.ymlon: push: branches: - master pull_request: branches: - master name: Test jobs: run-unit-tests: name: Unit Tests runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Check out code into the Go module directory uses: actions/checkout@v3 with: fetch-depth: 2 - name: Set up Go uses: actions/setup-go@v4 with: go-version-file: 'go.mod' - name: Test run: make test - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 0707010000000B000081A400000000000000000000000166E627D70000035D000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/.gitignore# Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) # vendor/ .idea/ build # Mac OS .DS_Store .vscode/ # Ignore the scripts that are created for development *dev.* # Environment variables .env # pprof pprof/* # Database Files *.db *.gob # Nohup Files - https://man7.org/linux/man-pages/man1/nohup.1p.html nohup.* # Cypress tests cypress.env.json */cypress/downloads */cypress/fixtures */cypress/plugins */cypress/screenshots */cypress/videos */cypress/support # UI folders to ignore **/node_modules/** **/dist/** *.editorconfig # Ignore *.log files *.log # Object files *.o # Binaries bin # Scripts scripts/ # CWD config YAML kubeshark.yaml 0707010000000C000081A400000000000000000000000166E627D7000000DC000000000000000000000000000000000000002600000000kubeshark-cli-52.3.82/.goreleaser.ymlbrews: - name: kubeshark homepage: https://github.com/kubeshark/kubeshark tap: owner: kubeshark name: homebrew-kubeshark commit_author: name: mertyildiran email: me@mertyildiran.com 0707010000000D000081A400000000000000000000000166E627D700000D00000000000000000000000000000000000000002900000000kubeshark-cli-52.3.82/CODE_OF_CONDUCT.md# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq 0707010000000E000081A400000000000000000000000166E627D7000005C0000000000000000000000000000000000000002600000000kubeshark-cli-52.3.82/CONTRIBUTING.md![Kubeshark: The API Traffic Analyzer for Kubernetes](https://raw.githubusercontent.com/kubeshark/assets/master/svg/kubeshark-logo.svg) # Contributing to Kubeshark We welcome code contributions from the community. Please read and follow the guidelines below. ## Communication * Before starting work on a major feature, please reach out to us via [GitHub](https://github.com/kubeshark/kubeshark), [Discord](https://discord.gg/WkvRGMUcx7), [Slack](https://join.slack.com/t/kubeshark/shared_invite/zt-1k3sybpq9-uAhFkuPJiJftKniqrGHGhg), [email](mailto:info@kubeshark.co), etc. We will make sure no one else is already working on it. A _major feature_ is defined as any change that is > 100 LOC altered (not including tests), or changes any user-facing behavior * Small patches and bug fixes don't need prior communication. ## Contribution Requirements * Code style - most of the code is written in Go, please follow [these guidelines](https://golang.org/doc/effective_go) * Go-tools compatible (`go get`, `go test`, etc.) * Code coverage for unit tests must not decrease. * Code must be usefully commented. Not only for developers on the project, but also for external users of these packages * When reviewing PRs, you are encouraged to use Golang's [code review comments page](https://github.com/golang/go/wiki/CodeReviewComments) * Project follows [Google JSON Style Guide](https://google.github.io/styleguide/jsoncstyleguide.xml) for the REST APIs that are provided. 0707010000000F000081A400000000000000000000000166E627D700002A05000000000000000000000000000000000000001E00000000kubeshark-cli-52.3.82/LICENSE Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2022 Kubeshark Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 07070100000010000081A400000000000000000000000166E627D700001C07000000000000000000000000000000000000001F00000000kubeshark-cli-52.3.82/MakefileSHELL=/bin/bash .PHONY: help .DEFAULT_GOAL := build .ONESHELL: SUFFIX=$(GOOS)_$(GOARCH) 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.0 help: ## Print this help message. @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) build-debug: ## Build for debugging. export CGO_ENABLED=1 export GCLFAGS='-gcflags="all=-N -l"' ${MAKE} build-base build: ## Build. export CGO_ENABLED=0 export LDFLAGS_EXT='-extldflags=-static -s -w' ${MAKE} build-base build-race: ## Build with -race flag. export CGO_ENABLED=1 export GCLFAGS='-race' export LDFLAGS_EXT='-extldflags=-static -s -w' ${MAKE} build-base build-base: ## Build binary (select the platform via GOOS / GOARCH env variables). 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 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" && \ mkdir -p bin && sed s/_VER_/$(VER)/g RELEASE.md.TEMPLATE > bin/README.md && \ $(MAKE) build GOOS=linux GOARCH=amd64 && \ $(MAKE) build GOOS=linux GOARCH=arm64 && \ $(MAKE) build GOOS=darwin GOARCH=amd64 && \ $(MAKE) build GOOS=darwin GOARCH=arm64 && \ $(MAKE) build-windows-amd64 && \ echo "---------" && \ find ./bin -ls clean: ## Clean all build artifacts. go clean rm -rf ./bin/* test: ## Run cli tests. @go test ./... -coverpkg=./... -race -coverprofile=coverage.out -covermode=atomic lint: ## Lint the source code. golangci-lint run kubectl-view-all-resources: ## This command outputs all Kubernetes resources using YAML format and pipes it to VS Code ./kubectl.sh view-all-resources 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 && sed -i '1i # find a detailed description here: https://github.com/kubeshark/kubeshark/blob/master/helm-chart/README.md' 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-sniffer: export LOGS_POD_PREFIX=kubeshark-worker- export LOGS_CONTAINER='-c sniffer' export LOGS_FOLLOW= ${MAKE} logs logs-sniffer-follow: export LOGS_POD_PREFIX=kubeshark-worker- export LOGS_CONTAINER='-c sniffer' export LOGS_FOLLOW=--follow ${MAKE} logs logs-tracer: export LOGS_POD_PREFIX=kubeshark-worker- export LOGS_CONTAINER='-c tracer' export LOGS_FOLLOW= ${MAKE} logs logs-tracer-follow: export LOGS_POD_PREFIX=kubeshark-worker- export LOGS_CONTAINER='-c tracer' export LOGS_FOLLOW=--follow ${MAKE} logs logs-worker: logs-sniffer logs-worker-follow: logs-sniffer-follow 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_CONTAINER) $(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 . --set tap.docker.tag=$(TAG) && cd .. helm-install-debug: cd helm-chart && helm install kubeshark . --set tap.docker.tag=$(TAG) --set tap.debug=true && cd .. helm-install-profile: cd helm-chart && helm install kubeshark . --set tap.docker.tag=$(TAG) --set tap.pprof.enabled=true && cd .. helm-uninstall: helm uninstall kubeshark proxy: kubeshark proxy port-forward: kubectl port-forward $$(kubectl get pods | awk '$$1 ~ /^$(POD_PREFIX)/' | awk 'END {print $$1}') $(SRC_PORT):$(DST_PORT) 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 && git checkout master && git pull && 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 branch: @cd ../worker && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name) @cd ../hub && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name) @cd ../front && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name) switch-to-branch: @cd ../worker && git checkout $(name) @cd ../hub && git checkout $(name) @cd ../front && git checkout $(name) 07070100000011000081A400000000000000000000000166E627D700000C6D000000000000000000000000000000000000002000000000kubeshark-cli-52.3.82/README.md<p align="center"> <img src="https://raw.githubusercontent.com/kubeshark/assets/master/svg/kubeshark-logo.svg" alt="Kubeshark: Traffic analyzer for Kubernetes." height="128px"/> </p> <p align="center"> <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/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"> </a> <a href="https://discord.gg/WkvRGMUcx7"> <img alt="Discord" src="https://img.shields.io/discord/1042559155224973352?logo=Discord&style=flat-square&label=discord"> </a> <a href="https://join.slack.com/t/kubeshark/shared_invite/zt-1m90td3n7-VHxN_~V5kVp80SfQW3SfpA"> <img alt="Slack" src="https://img.shields.io/badge/slack-join_chat-green?logo=Slack&style=flat-square&label=slack"> </a> </p> <p align="center"> <b> Want to see Kubeshark in action, right now? Visit this <a href="https://demo.kubeshark.co/">live demo deployment</a> of Kubeshark. </b> </p> **Kubeshark** is an API Traffic Analyzer for [**Kubernetes**](https://kubernetes.io/) providing real-time, protocol-level visibility into Kubernetes’ internal network, capturing and monitoring all traffic and payloads going in, out and across containers, pods, nodes and clusters. ![Simple UI](https://github.com/kubeshark/assets/raw/master/png/kubeshark-ui.png) Think [TCPDump](https://en.wikipedia.org/wiki/Tcpdump) and [Wireshark](https://www.wireshark.org/) re-invented for Kubernetes ## Getting Started Download **Kubeshark**'s binary distribution [latest release](https://github.com/kubeshark/kubeshark/releases/latest) and run following one of these examples: ```shell kubeshark tap ``` ```shell kubeshark tap -n sock-shop "(catalo*|front-end*)" ``` Running any of the :point_up: above commands will open the [Web UI](https://docs.kubeshark.co/en/ui) in your browser which streams the traffic in your Kubernetes cluster in real-time. ### Homebrew [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__`. ## Documentation To learn more, read the [documentation](https://docs.kubeshark.co). ## Contributing We :heart: pull requests! See [CONTRIBUTING.md](CONTRIBUTING.md) for the contribution guide. ## Code of Conduct This project is for everyone. We ask that our users and contributors take a few minutes to review our [Code of Conduct](CODE_OF_CONDUCT.md). 07070100000012000081A400000000000000000000000166E627D7000003E8000000000000000000000000000000000000002A00000000kubeshark-cli-52.3.82/RELEASE.md.TEMPLATE# Kubeshark release _VER_ Release notes coming soon .. ## Download Kubeshark for your platform **Mac** (x86-64/Intel) ``` curl -Lo kubeshark https://github.com/kubeshark/kubeshark/releases/download/_VER_/kubeshark_darwin_amd64 && chmod 755 kubeshark ``` **Mac** (AArch64/Apple M1 silicon) ``` rm -f kubeshark && curl -Lo kubeshark https://github.com/kubeshark/kubeshark/releases/download/_VER_/kubeshark_darwin_arm64 && chmod 755 kubeshark ``` **Linux** (x86-64) ``` curl -Lo kubeshark https://github.com/kubeshark/kubeshark/releases/download/_VER_/kubeshark_linux_amd64 && chmod 755 kubeshark ``` **Linux** (AArch64) ``` curl -Lo kubeshark https://github.com/kubeshark/kubeshark/releases/download/_VER_/kubeshark_linux_arm64 && chmod 755 kubeshark ``` **Windows** (x86-64) ``` curl -LO https://github.com/kubeshark/kubeshark/releases/download/_VER_/kubeshark.exe ``` ### Checksums SHA256 checksums available for compiled binaries. Run `shasum -a 256 -c kubeshark_OS_ARCH.sha256` to verify. 07070100000013000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001A00000000kubeshark-cli-52.3.82/cmd07070100000014000081A400000000000000000000000166E627D700000453000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/cmd/clean.gopackage cmd 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" ) var cleanCmd = &cobra.Command{ Use: "clean", Short: fmt.Sprintf("Removes all %s resources", misc.Software), RunE: func(cmd *cobra.Command, args []string) error { 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 }, } func init() { rootCmd.AddCommand(cleanCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } cleanCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark") } 07070100000015000081A400000000000000000000000166E627D700001077000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/cmd/common.gopackage cmd import ( "context" "errors" "fmt" "path" "regexp" "time" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/errormessage" "github.com/kubeshark/kubeshark/internal/connect" "github.com/kubeshark/kubeshark/kubernetes" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/misc/fsUtils" "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.Release.Namespace, serviceName) if err != nil { log.Error(). Err(errormessage.FormatError(err)). Msg(fmt.Sprintf("Error occurred while running K8s proxy. Try setting different port using --%s", proxyPortLabel)) return } connector := connect.NewConnector(kubernetes.GetProxyOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout) if err := connector.TestConnection(healthCheck); err != nil { log.Warn(). Str("service", serviceName). Msg("Couldn't connect using proxy, stopping proxy and trying to create port-forward...") if err := httpServer.Shutdown(ctx); err != nil { log.Error(). Err(errormessage.FormatError(err)). Msg("Error occurred while stopping proxy.") } podRegex, _ := regexp.Compile(podName) 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)). Msg(fmt.Sprintf("Error occurred while running port forward. Try setting different port using --%s", proxyPortLabel)) return } connector = connect.NewConnector(kubernetes.GetProxyOnPort(srcPort), connect.DefaultRetries, connect.DefaultTimeout) if err := connector.TestConnection(healthCheck); err != nil { log.Error(). Str("service", serviceName). Err(errormessage.FormatError(err)). Msg("Couldn't connect to service.") return } } } func getKubernetesProviderForCli(silent bool, dontCheckVersion bool) (*kubernetes.Provider, error) { kubeConfigPath := config.Config.KubeConfigPath() kubernetesProvider, err := kubernetes.NewProvider(kubeConfigPath, config.Config.Kube.Context) if err != nil { handleKubernetesProviderError(err) return nil, err } if !silent { log.Info().Str("path", kubeConfigPath).Msg("Using kubeconfig:") } if err := kubernetesProvider.ValidateNotProxy(); err != nil { handleKubernetesProviderError(err) return nil, err } if !dontCheckVersion { kubernetesVersion, err := kubernetesProvider.GetKubernetesVersion() if err != nil { handleKubernetesProviderError(err) return nil, err } if err := kubernetes.ValidateKubernetesVersion(kubernetesVersion); err != nil { handleKubernetesProviderError(err) return nil, err } } return kubernetesProvider, nil } func handleKubernetesProviderError(err error) { var clusterBehindProxyErr *kubernetes.ClusterBehindProxyError if ok := errors.As(err, &clusterBehindProxyErr); ok { log.Error().Msg(fmt.Sprintf("Cannot establish http-proxy connection to the Kubernetes cluster. If you’re using Lens or similar tool, please run '%s' with regular kubectl config using --%v %v=$HOME/.kube/config flag", misc.Program, config.SetCommandName, config.KubeConfigPathConfigName)) } else { log.Error().Err(err).Send() } } func finishSelfExecution(kubernetesProvider *kubernetes.Provider) { removalCtx, cancel := context.WithTimeout(context.Background(), cleanupTimeout) defer cancel() dumpLogsIfNeeded(removalCtx, kubernetesProvider) } func dumpLogsIfNeeded(ctx context.Context, kubernetesProvider *kubernetes.Provider) { if !config.Config.DumpLogs { return } dotDir := misc.GetDotFolderPath() filePath := path.Join(dotDir, fmt.Sprintf("%s_logs_%s.zip", misc.Program, time.Now().Format("2006_01_02__15_04_05"))) if err := fsUtils.DumpLogs(ctx, kubernetesProvider, filePath, config.Config.Logs.Grep); err != nil { log.Error().Err(err).Msg("Failed to dump logs.") } } 07070100000016000081A400000000000000000000000166E627D70000067A000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/cmd/config.gopackage cmd import ( "fmt" "path" "github.com/creasty/defaults" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/utils" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) 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 { if config.Config.Config.Regenerate { 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(config.Config) if err != nil { log.Error().Err(err).Msg("Failed converting config with defaults to YAML.") return nil } log.Debug().Str("template", template).Msg("Printing template config...") fmt.Printf("%v", template) } return nil }, } func init() { rootCmd.AddCommand(configCmd) defaultConfig := config.CreateDefaultConfig() if err := defaults.Set(&defaultConfig); err != nil { log.Debug().Err(err).Send() } configCmd.Flags().BoolP(configStructs.RegenerateConfigName, "r", defaultConfig.Config.Regenerate, fmt.Sprintf("Regenerate the config file with default values to path %s", path.Join(misc.GetDotFolderPath(), "config.yaml"))) } 07070100000017000081A400000000000000000000000166E627D700000B9B000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/cmd/console.gopackage cmd import ( "fmt" "net/http" "net/url" "os" "os/signal" "strings" "time" "github.com/creasty/defaults" "github.com/gorilla/websocket" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/kubeshark/kubeshark/kubernetes" "github.com/kubeshark/kubeshark/utils" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var consoleCmd = &cobra.Command{ Use: "console", Short: "Stream the scripting console logs into shell", RunE: func(cmd *cobra.Command, args []string) error { runConsole() return nil }, } func init() { rootCmd.AddCommand(consoleCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } 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.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) } interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) 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/api", config.Config.Tap.Proxy.Host, config.Config.Tap.Proxy.Front.Port), Path: "/scripts/logs", } headers := http.Header{} headers.Set(utils.X_KUBESHARK_CAPTURE_HEADER_KEY, utils.X_KUBESHARK_CAPTURE_HEADER_IGNORE_VALUE) headers.Set("License-Key", config.Config.License) c, _, err := websocket.DefaultDialer.Dial(u.String(), headers) if err != nil { log.Error().Err(err).Send() return } defer c.Close() done := make(chan struct{}) go func() { defer close(done) for { _, message, err := c.ReadMessage() if err != nil { log.Error().Err(err).Send() return } msg := string(message) if strings.Contains(msg, ":ERROR]") { msg = fmt.Sprintf(utils.Red, msg) fmt.Fprintln(os.Stderr, msg) } else { fmt.Fprintln(os.Stdout, msg) } } }() ticker := time.NewTicker(time.Second) defer ticker.Stop() for { select { case <-done: return case <-interrupt: log.Warn().Msg(fmt.Sprintf(utils.Yellow, "Received interrupt, exiting...")) err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) if err != nil { log.Error().Err(err).Send() return } select { case <-done: case <-time.After(time.Second): } return } } } 07070100000018000081A400000000000000000000000166E627D7000006F7000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/cmd/export.gopackage 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) } 07070100000019000081A400000000000000000000000166E627D700000163000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/cmd/license.gopackage 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) } 0707010000001A000081A400000000000000000000000166E627D700000640000000000000000000000000000000000000002200000000kubeshark-cli-52.3.82/cmd/logs.gopackage cmd import ( "context" "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/kubeshark/kubeshark/misc/fsUtils" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var logsCmd = &cobra.Command{ Use: "logs", Short: "Create a ZIP file with logs for GitHub issues or troubleshooting", RunE: func(cmd *cobra.Command, args []string) error { kubernetesProvider, err := getKubernetesProviderForCli(false, false) if err != nil { return nil } ctx := context.Background() if validationErr := config.Config.Logs.Validate(); validationErr != nil { return errormessage.FormatError(validationErr) } log.Debug().Str("logs-path", config.Config.Logs.FilePath()).Msg("Using this logs path...") if dumpLogsErr := fsUtils.DumpLogs(ctx, kubernetesProvider, config.Config.Logs.FilePath(), config.Config.Logs.Grep); dumpLogsErr != nil { log.Error().Err(dumpLogsErr).Msg("Failed to dump logs.") } return nil }, } func init() { rootCmd.AddCommand(logsCmd) defaultLogsConfig := configStructs.LogsConfig{} if err := defaults.Set(&defaultLogsConfig); err != nil { log.Debug().Err(err).Send() } logsCmd.Flags().StringP(configStructs.FileLogsName, "f", defaultLogsConfig.FileStr, fmt.Sprintf("Path for zip file (default current <pwd>\\%s_logs.zip)", misc.Program)) logsCmd.Flags().StringP(configStructs.GrepLogsName, "g", defaultLogsConfig.Grep, "Regexp to do grepping on the logs") } 0707010000001B000081A400000000000000000000000166E627D7000004E9000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/cmd/pprof.gopackage cmd import ( "github.com/creasty/defaults" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var pprofCmd = &cobra.Command{ Use: "pprof", Short: "Select a Kubeshark container and open the pprof web UI in the browser", RunE: func(cmd *cobra.Command, args []string) error { runPprof() return nil }, } func init() { rootCmd.AddCommand(pprofCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } pprofCmd.Flags().Uint16(configStructs.ProxyFrontPortLabel, defaultTapConfig.Proxy.Front.Port, "Provide a custom port for the proxy/port-forward") pprofCmd.Flags().String(configStructs.ProxyHostLabel, defaultTapConfig.Proxy.Host, "Provide a custom host for the proxy/port-forward") pprofCmd.Flags().StringP(configStructs.ReleaseNamespaceLabel, "s", defaultTapConfig.Release.Namespace, "Release namespace of Kubeshark") pprofCmd.Flags().Uint16(configStructs.PprofPortLabel, defaultTapConfig.Pprof.Port, "Provide a custom port for the pprof server") pprofCmd.Flags().String(configStructs.PprofViewLabel, defaultTapConfig.Pprof.View, "Change the default view of the pprof web interface") } 0707010000001C000081A400000000000000000000000166E627D7000011F3000000000000000000000000000000000000002900000000kubeshark-cli-52.3.82/cmd/pprofRunner.gopackage cmd import ( "context" "fmt" "github.com/go-cmd/cmd" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/kubernetes" "github.com/kubeshark/kubeshark/utils" "github.com/rivo/tview" "github.com/rs/zerolog/log" v1 "k8s.io/api/core/v1" ) func runPprof() { runProxy(false, true) provider, err := getKubernetesProviderForCli(false, false) if err != nil { return } ctx, cancel := context.WithCancel(context.Background()) defer cancel() hubPods, err := provider.ListPodsByAppLabel(ctx, config.Config.Tap.Release.Namespace, map[string]string{kubernetes.AppLabelKey: "hub"}) if err != nil { log.Error(). Err(err). Msg("Failed to list hub pods!") cancel() return } workerPods, err := provider.ListPodsByAppLabel(ctx, config.Config.Tap.Release.Namespace, map[string]string{kubernetes.AppLabelKey: "worker"}) if err != nil { log.Error(). Err(err). Msg("Failed to list worker pods!") cancel() return } fullscreen := true app := tview.NewApplication() list := tview.NewList() var currentCmd *cmd.Cmd i := 48 for _, pod := range hubPods { for _, container := range pod.Spec.Containers { log.Info().Str("pod", pod.Name).Str("container", container.Name).Send() homeUrl := fmt.Sprintf("%s/debug/pprof/", kubernetes.GetHubUrl()) modal := buildNewModal( pod, container, homeUrl, app, list, fullscreen, currentCmd, ) list.AddItem(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name), pod.Spec.NodeName, rune(i), func() { app.SetRoot(modal, fullscreen) }) i++ } } for _, pod := range workerPods { for _, container := range pod.Spec.Containers { log.Info().Str("pod", pod.Name).Str("container", container.Name).Send() homeUrl := fmt.Sprintf("%s/pprof/%s/%s/", kubernetes.GetHubUrl(), pod.Status.HostIP, container.Name) modal := buildNewModal( pod, container, homeUrl, app, list, fullscreen, currentCmd, ) list.AddItem(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name), pod.Spec.NodeName, rune(i), func() { app.SetRoot(modal, fullscreen) }) i++ } } list.AddItem("Quit", "Press to exit", 'q', func() { if currentCmd != nil { err = currentCmd.Stop() if err != nil { log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!") } } app.Stop() }) if err := app.SetRoot(list, fullscreen).EnableMouse(true).Run(); err != nil { panic(err) } } func buildNewModal( pod v1.Pod, container v1.Container, homeUrl string, app *tview.Application, list *tview.List, fullscreen bool, currentCmd *cmd.Cmd, ) *tview.Modal { return tview.NewModal(). SetText(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name)). AddButtons([]string{ "Open Debug Home Page", "Profile: CPU", "Profile: Memory", "Profile: Goroutine", "Cancel", }). SetDoneFunc(func(buttonIndex int, buttonLabel string) { var err error port := fmt.Sprintf(":%d", config.Config.Tap.Pprof.Port) view := fmt.Sprintf("http://localhost%s/ui/%s", port, config.Config.Tap.Pprof.View) switch buttonLabel { case "Open Debug Home Page": utils.OpenBrowser(homeUrl) case "Profile: CPU": if currentCmd != nil { err = currentCmd.Stop() if err != nil { log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!") } } currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sprofile", homeUrl)) currentCmd.Start() utils.OpenBrowser(view) case "Profile: Memory": if currentCmd != nil { err = currentCmd.Stop() if err != nil { log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!") } } currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sheap", homeUrl)) currentCmd.Start() utils.OpenBrowser(view) case "Profile: Goroutine": if currentCmd != nil { err = currentCmd.Stop() if err != nil { log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!") } } currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sgoroutine", homeUrl)) currentCmd.Start() utils.OpenBrowser(view) case "Cancel": if currentCmd != nil { err = currentCmd.Stop() if err != nil { log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!") } } fallthrough default: app.SetRoot(list, fullscreen) } }) } 0707010000001D000081A400000000000000000000000166E627D7000003E4000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/cmd/proxy.gopackage cmd import ( "github.com/creasty/defaults" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var proxyCmd = &cobra.Command{ Use: "proxy", Short: "Open the web UI (front-end) in the browser via proxy/port-forward", RunE: func(cmd *cobra.Command, args []string) error { runProxy(true, false) return nil }, } func init() { rootCmd.AddCommand(proxyCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } 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") } 0707010000001E000081A400000000000000000000000166E627D700000B2F000000000000000000000000000000000000002900000000kubeshark-cli-52.3.82/cmd/proxyRunner.gopackage cmd import ( "context" "fmt" "net/http" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "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" ) func runProxy(block bool, noBrowser bool) { kubernetesProvider, err := getKubernetesProviderForCli(false, false) if err != nil { return } ctx, cancel := context.WithCancel(context.Background()) defer cancel() exists, err := kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.Release.Namespace, kubernetes.FrontServiceName) if err != nil { log.Error(). Str("service", kubernetes.FrontServiceName). Err(err). Msg("Failed to found service!") cancel() return } if !exists { log.Error(). Str("service", kubernetes.FrontServiceName). Str("command", fmt.Sprintf("%s %s", misc.Program, tapCmd.Use)). Msg("Service not found! You should run the command first:") cancel() return } exists, err = kubernetesProvider.DoesServiceExist(ctx, config.Config.Tap.Release.Namespace, kubernetes.HubServiceName) if err != nil { log.Error(). Str("service", kubernetes.HubServiceName). Err(err). Msg("Failed to found service!") cancel() return } if !exists { log.Error(). Str("service", kubernetes.HubServiceName). Str("command", fmt.Sprintf("%s %s", misc.Program, tapCmd.Use)). Msg("Service not found! You should run the command first:") cancel() return } var establishedProxy bool 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). Int("port", int(config.Config.Tap.Proxy.Front.Port)). Msg("Found a running service.") okToOpen("Kubeshark", frontUrl, noBrowser) } else { startProxyReportErrorIfAny( kubernetesProvider, ctx, kubernetes.FrontServiceName, kubernetes.FrontPodName, configStructs.ProxyFrontPortLabel, config.Config.Tap.Proxy.Front.Port, configStructs.ContainerPort, "", ) connector := connect.NewConnector(frontUrl, connect.DefaultRetries, connect.DefaultTimeout) if err := connector.TestConnection(""); err != nil { log.Error().Msg(fmt.Sprintf(utils.Red, "Couldn't connect to Front.")) return } establishedProxy = true okToOpen("Kubeshark", frontUrl, noBrowser) } if establishedProxy && block { utils.WaitForTermination(ctx, cancel) } } func okToOpen(name string, url string, noBrowser bool) { log.Info().Str("url", url).Msg(fmt.Sprintf(utils.Green, fmt.Sprintf("%s is available at:", name))) if !config.Config.HeadlessMode && !noBrowser { utils.OpenBrowser(url) } } 0707010000001F000081A400000000000000000000000166E627D7000004D9000000000000000000000000000000000000002200000000kubeshark-cli-52.3.82/cmd/root.gopackage cmd import ( "fmt" "github.com/creasty/defaults" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/misc" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var rootCmd = &cobra.Command{ Use: "kubeshark", Short: fmt.Sprintf("%s: %s", misc.Software, misc.Description), Long: fmt.Sprintf(`%s: %s An extensible Kubernetes-aware network sniffer and kernel tracer. For more info: %s`, misc.Software, misc.Description, misc.Website), PersistentPreRunE: func(cmd *cobra.Command, args []string) error { if err := config.InitConfig(cmd); err != nil { log.Fatal().Err(err).Send() } return nil }, } func init() { defaultConfig := config.CreateDefaultConfig() if err := defaults.Set(&defaultConfig); err != nil { log.Debug().Err(err).Send() } rootCmd.PersistentFlags().StringSlice(config.SetCommandName, []string{}, fmt.Sprintf("Override values using --%s", config.SetCommandName)) rootCmd.PersistentFlags().BoolP(config.DebugFlag, "d", false, "Enable debug mode") } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the tapCmd. func Execute() { cobra.CheckErr(rootCmd.Execute()) } 07070100000020000081A400000000000000000000000166E627D700000E5E000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/cmd/scripts.gopackage cmd import ( "context" "fmt" "net/http" "github.com/creasty/defaults" "github.com/fsnotify/fsnotify" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "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" "github.com/spf13/cobra" ) var scriptsCmd = &cobra.Command{ Use: "scripts", Short: "Watch the `scripting.source` directory for changes and update the scripts", RunE: func(cmd *cobra.Command, args []string) error { runScripts() return nil }, } func init() { rootCmd.AddCommand(scriptsCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } 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() { if config.Config.Scripting.Source == "" { log.Error().Msg("`scripting.source` field is empty.") return } 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.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout) watchScripts(true) } func watchScripts(block bool) { files := make(map[string]int64) scripts, err := config.Config.Scripting.GetScripts() if err != nil { log.Error().Err(err).Send() return } for _, script := range scripts { index, err := connector.PostScript(script) if err != nil { log.Error().Err(err).Send() return } files[script.Path] = index } watcher, err := fsnotify.NewWatcher() if err != nil { log.Error().Err(err).Send() return } if block { defer watcher.Close() } go func() { for { select { // watch for events case event := <-watcher.Events: switch event.Op { case fsnotify.Create: script, err := misc.ReadScriptFile(event.Name) if err != nil { log.Error().Err(err).Send() continue } index, err := connector.PostScript(script) if err != nil { log.Error().Err(err).Send() continue } files[script.Path] = index case fsnotify.Write: index := files[event.Name] script, err := misc.ReadScriptFile(event.Name) if err != nil { log.Error().Err(err).Send() continue } err = connector.PutScript(script, index) if err != nil { log.Error().Err(err).Send() continue } case fsnotify.Rename: index := files[event.Name] err := connector.DeleteScript(index) if err != nil { log.Error().Err(err).Send() continue } default: // pass } // watch for errors case err := <-watcher.Errors: log.Error().Err(err).Send() } } }() if err := watcher.Add(config.Config.Scripting.Source); err != nil { log.Error().Err(err).Send() } log.Info().Str("directory", config.Config.Scripting.Source).Msg("Watching scripts against changes:") if block { ctx, cancel := context.WithCancel(context.Background()) defer cancel() utils.WaitForTermination(ctx, cancel) } } 07070100000021000081A400000000000000000000000166E627D700000ECD000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/cmd/tap.gopackage cmd import ( "errors" "github.com/creasty/defaults" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/kubeshark/kubeshark/errormessage" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var tapCmd = &cobra.Command{ Use: "tap [POD REGEX]", Short: "Capture the network traffic in your Kubernetes cluster", RunE: func(cmd *cobra.Command, args []string) error { tap() return nil }, PreRunE: func(cmd *cobra.Command, args []string) error { if len(args) == 1 { config.Config.Tap.PodRegexStr = args[0] } else if len(args) > 1 { return errors.New("unexpected number of arguments") } if err := config.Config.Tap.Validate(); err != nil { return errormessage.FormatError(err) } return nil }, } func init() { rootCmd.AddCommand(tapCmd) defaultTapConfig := configStructs.TapConfig{} if err := defaults.Set(&defaultTapConfig); err != nil { log.Debug().Err(err).Send() } tapCmd.Flags().StringP(configStructs.DockerRegistryLabel, "r", defaultTapConfig.Docker.Registry, "The Docker registry that's hosting the images") 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 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().StringSliceP(configStructs.ExcludedNamespacesLabel, "e", defaultTapConfig.ExcludedNamespaces, "Excluded namespaces") 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().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.TelemetryEnabledLabel, defaultTapConfig.Telemetry.Enabled, "Enable/disable Telemetry") } 07070100000022000081A400000000000000000000000166E627D700003659000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/cmd/tapRunner.gopackage cmd import ( "context" "encoding/json" "fmt" "os" "regexp" "strings" "sync" "time" "github.com/kubeshark/kubeshark/internal/connect" "github.com/kubeshark/kubeshark/kubernetes/helm" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/utils" core "k8s.io/api/core/v1" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/kubeshark/kubeshark/errormessage" "github.com/kubeshark/kubeshark/kubernetes" "github.com/rs/zerolog/log" ) const cleanupTimeout = time.Minute type tapState struct { startTime time.Time targetNamespaces []string } var state tapState var connector *connect.Connector type Readiness struct { Hub bool Front bool Proxy bool sync.Mutex } var ready *Readiness func tap() { ready = &Readiness{} state.startTime = time.Now() 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.GetHubUrl(), connect.DefaultRetries, connect.DefaultTimeout) kubernetesProvider, err := getKubernetesProviderForCli(false, false) if err != nil { log.Error().Err(err).Send() return } ctx, cancel := context.WithCancel(context.Background()) defer cancel() // cancel will be called when this function exits state.targetNamespaces = kubernetesProvider.GetNamespaces() 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:") if err := printTargetedPodsPreview(ctx, kubernetesProvider, state.targetNamespaces); err != nil { log.Error().Err(errormessage.FormatError(err)).Msg("Error listing pods!") } if config.Config.Tap.DryRun { return } log.Info().Msg(fmt.Sprintf("Waiting for the creation of %s resources...", misc.Software)) 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) // block until exit signal or error utils.WaitForTermination(ctx, cancel) if !config.Config.Tap.Ingress.Enabled { printProxyCommandSuggestion() } } func printProxyCommandSuggestion() { log.Warn(). Str("command", fmt.Sprintf("%s proxy", misc.Program)). Msg(fmt.Sprintf(utils.Yellow, "To re-establish a proxy/port-forward, run:")) } func finishTapExecution(kubernetesProvider *kubernetes.Provider) { finishSelfExecution(kubernetesProvider) } /* This function is a bit problematic as it might be detached from the actual pods the Kubeshark that targets. The alternative would be to wait for Hub to be ready and then query it for the pods it listens to, this has the arguably worse drawback of taking a relatively very long time before the user sees which pods are targeted, if any. */ func printTargetedPodsPreview(ctx context.Context, kubernetesProvider *kubernetes.Provider, namespaces []string) error { if matchingPods, err := kubernetesProvider.ListAllRunningPodsMatchingRegex(ctx, config.Config.Tap.PodRegex(), namespaces); err != nil { return err } else { if len(matchingPods) == 0 { printNoPodsFoundSuggestion(namespaces) } for _, targetedPod := range matchingPods { log.Info().Msg(fmt.Sprintf("Targeted pod: %s", fmt.Sprintf(utils.Green, targetedPod.Name))) } return nil } } func printNoPodsFoundSuggestion(targetNamespaces []string) { var suggestionStr string if !utils.Contains(targetNamespaces, kubernetes.K8sAllNamespaces) { suggestionStr = ". You can also try selecting a different namespace with -n or target all namespaces with -A" } log.Warn().Msg(fmt.Sprintf("Did not find any currently running pods that match the regex argument, %s will automatically target matching pods if any are created later%s", misc.Software, suggestionStr)) } func watchHubPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) { podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s", kubernetes.HubPodName)) podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex) eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.Release.Namespace}, podWatchHelper) isPodReady := false timeAfter := time.After(120 * time.Second) for { select { case wEvent, ok := <-eventChan: if !ok { eventChan = nil continue } switch wEvent.Type { case kubernetes.EventAdded: log.Info().Str("pod", kubernetes.HubPodName).Msg("Added:") case kubernetes.EventDeleted: log.Info().Str("pod", kubernetes.HubPodName).Msg("Removed:") cancel() return case kubernetes.EventModified: modifiedPod, err := wEvent.ToPod() if err != nil { log.Error().Str("pod", kubernetes.HubPodName).Err(err).Msg("While watching pod.") cancel() continue } log.Debug(). Str("pod", kubernetes.HubPodName). Interface("phase", modifiedPod.Status.Phase). Interface("containers-statuses", modifiedPod.Status.ContainerStatuses). Msg("Watching pod.") if modifiedPod.Status.Phase == core.PodRunning && !isPodReady { isPodReady = true ready.Lock() ready.Hub = true ready.Unlock() log.Info().Str("pod", kubernetes.HubPodName).Msg("Ready.") } ready.Lock() proxyDone := ready.Proxy hubPodReady := ready.Hub frontPodReady := ready.Front ready.Unlock() if !proxyDone && hubPodReady && frontPodReady { ready.Lock() ready.Proxy = true ready.Unlock() postFrontStarted(ctx, kubernetesProvider, cancel) } case kubernetes.EventBookmark: break case kubernetes.EventError: break } case err, ok := <-errorChan: if !ok { errorChan = nil continue } log.Error(). Str("pod", kubernetes.HubPodName). Str("namespace", config.Config.Tap.Release.Namespace). Err(err). Msg("Failed creating pod.") cancel() case <-timeAfter: if !isPodReady { log.Error(). Str("pod", kubernetes.HubPodName). Msg("Pod was not ready in time.") cancel() } case <-ctx.Done(): log.Debug(). Str("pod", kubernetes.HubPodName). Msg("Watching pod, context done.") return } } } func watchFrontPod(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) { podExactRegex := regexp.MustCompile(fmt.Sprintf("^%s", kubernetes.FrontPodName)) podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex) eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.Tap.Release.Namespace}, podWatchHelper) isPodReady := false timeAfter := time.After(120 * time.Second) for { select { case wEvent, ok := <-eventChan: if !ok { eventChan = nil continue } switch wEvent.Type { case kubernetes.EventAdded: log.Info().Str("pod", kubernetes.FrontPodName).Msg("Added:") case kubernetes.EventDeleted: log.Info().Str("pod", kubernetes.FrontPodName).Msg("Removed:") cancel() return case kubernetes.EventModified: modifiedPod, err := wEvent.ToPod() if err != nil { log.Error().Str("pod", kubernetes.FrontPodName).Err(err).Msg("While watching pod.") cancel() continue } log.Debug(). Str("pod", kubernetes.FrontPodName). Interface("phase", modifiedPod.Status.Phase). Interface("containers-statuses", modifiedPod.Status.ContainerStatuses). Msg("Watching pod.") if modifiedPod.Status.Phase == core.PodRunning && !isPodReady { isPodReady = true ready.Lock() ready.Front = true ready.Unlock() log.Info().Str("pod", kubernetes.FrontPodName).Msg("Ready.") } ready.Lock() proxyDone := ready.Proxy hubPodReady := ready.Hub frontPodReady := ready.Front ready.Unlock() if !proxyDone && hubPodReady && frontPodReady { ready.Lock() ready.Proxy = true ready.Unlock() postFrontStarted(ctx, kubernetesProvider, cancel) } case kubernetes.EventBookmark: break case kubernetes.EventError: break } case err, ok := <-errorChan: if !ok { errorChan = nil continue } log.Error(). Str("pod", kubernetes.FrontPodName). Str("namespace", config.Config.Tap.Release.Namespace). Err(err). Msg("Failed creating pod.") case <-timeAfter: if !isPodReady { log.Error(). Str("pod", kubernetes.FrontPodName). Msg("Pod was not ready in time.") cancel() } case <-ctx.Done(): log.Debug(). Str("pod", kubernetes.FrontPodName). Msg("Watching pod, context done.") return } } } 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.Release.Namespace}, eventWatchHelper) for { select { case wEvent, ok := <-eventChan: if !ok { eventChan = nil continue } event, err := wEvent.ToEvent() if err != nil { log.Error(). Str("pod", kubernetes.HubPodName). Err(err). Msg("Parsing resource event.") continue } if state.startTime.After(event.CreationTimestamp.Time) { continue } log.Debug(). Str("pod", kubernetes.HubPodName). Str("event", event.Name). Time("time", event.CreationTimestamp.Time). Str("name", event.Regarding.Name). Str("kind", event.Regarding.Kind). Str("reason", event.Reason). Str("note", event.Note). Msg("Watching events.") switch event.Reason { case "FailedScheduling", "Failed": log.Error(). Str("pod", kubernetes.HubPodName). Str("event", event.Name). Time("time", event.CreationTimestamp.Time). Str("name", event.Regarding.Name). Str("kind", event.Regarding.Kind). Str("reason", event.Reason). Str("note", event.Note). Msg("Watching events.") cancel() } case err, ok := <-errorChan: if !ok { errorChan = nil continue } log.Error(). Str("pod", kubernetes.HubPodName). Err(err). Msg("While watching events.") case <-ctx.Done(): log.Debug(). Str("pod", kubernetes.HubPodName). Msg("Watching pod events, context done.") return } } } func postFrontStarted(ctx context.Context, kubernetesProvider *kubernetes.Provider, cancel context.CancelFunc) { startProxyReportErrorIfAny( kubernetesProvider, ctx, kubernetes.FrontServiceName, kubernetes.FrontPodName, configStructs.ProxyFrontPortLabel, config.Config.Tap.Proxy.Front.Port, configStructs.ContainerPort, "", ) var url string if config.Config.Tap.Ingress.Enabled { url = fmt.Sprintf("http://%s", config.Config.Tap.Ingress.Host) } else { 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, ",")) _, _ = kubernetes.SetConfig(kubernetesProvider, kubernetes.CONFIG_EXCLUDED_NAMESPACES, strings.Join(config.Config.Tap.ExcludedNamespaces, ",")) 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) } 07070100000023000081A400000000000000000000000166E627D7000002C2000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/cmd/version.gopackage cmd import ( "fmt" "strconv" "time" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/misc" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var versionCmd = &cobra.Command{ Use: "version", Short: "Print version info", RunE: func(cmd *cobra.Command, args []string) error { timeStampInt, _ := strconv.ParseInt(misc.BuildTimestamp, 10, 0) if config.DebugMode { log.Info(). Str("version", misc.Ver). Str("branch", misc.Branch). Str("commit-hash", misc.GitCommitHash). Time("build-time", time.Unix(timeStampInt, 0)). Send() } else { fmt.Println(misc.Ver) } return nil }, } func init() { rootCmd.AddCommand(versionCmd) } 07070100000024000081A400000000000000000000000166E627D700000074000000000000000000000000000000000000002200000000kubeshark-cli-52.3.82/codecov.ymlcoverage: status: project: default: threshold: 1% patch: default: enabled: no 07070100000025000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001D00000000kubeshark-cli-52.3.82/config07070100000026000081A400000000000000000000000166E627D700002A1A000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/config/config.gopackage config import ( "errors" "fmt" "io" "os" "path" "path/filepath" "reflect" "strconv" "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" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/pflag" ) const ( Separator = "=" SetCommandName = "set" FieldNameTag = "yaml" ReadonlyTag = "readonly" DebugFlag = "debug" ) var ( Config ConfigStruct DebugMode bool cmdName string ConfigFilePath string ) func InitConfig(cmd *cobra.Command) error { var err error DebugMode, err = cmd.Flags().GetBool(DebugFlag) if err != nil { log.Error().Err(err).Msg(fmt.Sprintf("Can't receive '%s' flag", DebugFlag)) } if DebugMode { zerolog.SetGlobalLevel(zerolog.DebugLevel) } if cmd.Use == "version" { return nil } if !utils.Contains([]string{ "console", "pro", "manifests", "license", }, cmd.Use) { go version.CheckNewerVersion() } Config = CreateDefaultConfig() Config.Tap.Debug = DebugMode cmdName = cmd.Name() if utils.Contains([]string{ "clean", "console", "pro", "proxy", "scripts", "pprof", }, cmdName) { cmdName = "tap" } if err := defaults.Set(&Config); err != nil { return err } 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"+ "you can regenerate the file by removing it (%v) and using `kubeshark config -r`", err, ConfigFilePath) } } cmd.Flags().Visit(initFlag) log.Debug().Interface("config", Config).Msg("Init config is finished.") return nil } func GetConfigWithDefaults() (*ConfigStruct, error) { defaultConf := ConfigStruct{} if err := defaults.Set(&defaultConf); err != nil { return nil, err } configElem := reflect.ValueOf(&defaultConf).Elem() setZeroForReadonlyFields(configElem) return &defaultConf, nil } func WriteConfig(config *ConfigStruct) error { template, err := utils.PrettyYaml(config) if err != nil { return fmt.Errorf("failed converting config to yaml, err: %v", err) } data := []byte(template) if _, err := os.Stat(ConfigFilePath); os.IsNotExist(err) { err = os.MkdirAll(filepath.Dir(ConfigFilePath), 0700) if err != nil { return fmt.Errorf("failed creating directories, err: %v", err) } } if err := os.WriteFile(ConfigFilePath, data, 0644); err != nil { return fmt.Errorf("failed writing config, err: %v", err) } return nil } func loadConfigFile(config *ConfigStruct, silent bool) error { cwd, err := os.Getwd() if err != nil { return err } cwdConfig := filepath.Join(cwd, fmt.Sprintf("%s.yaml", misc.Program)) reader, err := os.Open(cwdConfig) if err != nil { reader, err = os.Open(ConfigFilePath) if err != nil { return err } } else { ConfigFilePath = cwdConfig } defer reader.Close() buf, err := io.ReadAll(reader) if err != nil { return err } if err := yaml.Unmarshal(buf, config); err != nil { return err } if !silent { log.Info().Str("path", ConfigFilePath).Msg("Found config file!") } return nil } func initFlag(f *pflag.Flag) { configElemValue := reflect.ValueOf(&Config).Elem() var flagPath []string flagPath = append(flagPath, cmdName) flagPath = append(flagPath, strings.Split(f.Name, "-")...) sliceValue, isSliceValue := f.Value.(pflag.SliceValue) if !isSliceValue { if err := mergeFlagValue(configElemValue, flagPath, strings.Join(flagPath, "."), f.Value.String()); err != nil { log.Warn().Err(err).Send() } return } if f.Name == SetCommandName { if err := mergeSetFlag(configElemValue, sliceValue.GetSlice()); err != nil { log.Warn().Err(err).Send() } return } if err := mergeFlagValues(configElemValue, flagPath, strings.Join(flagPath, "."), sliceValue.GetSlice()); err != nil { log.Warn().Err(err).Send() } } func mergeSetFlag(configElemValue reflect.Value, setValues []string) error { var setErrors []string setMap := map[string][]string{} for _, setValue := range setValues { if !strings.Contains(setValue, Separator) { setErrors = append(setErrors, fmt.Sprintf("Ignoring set argument %s (set argument format: <flag name>=<flag value>)", setValue)) continue } split := strings.SplitN(setValue, Separator, 2) argumentKey, argumentValue := split[0], split[1] setMap[argumentKey] = append(setMap[argumentKey], argumentValue) } for argumentKey, argumentValues := range setMap { flagPath := strings.Split(argumentKey, ".") if len(argumentValues) > 1 { if err := mergeFlagValues(configElemValue, flagPath, argumentKey, argumentValues); err != nil { setErrors = append(setErrors, fmt.Sprintf("%v", err)) } } else { if err := mergeFlagValue(configElemValue, flagPath, argumentKey, argumentValues[0]); err != nil { setErrors = append(setErrors, fmt.Sprintf("%v", err)) } } } if len(setErrors) > 0 { return errors.New(strings.Join(setErrors, "\n")) } return nil } func mergeFlagValue(configElemValue reflect.Value, flagPath []string, fullFlagName string, flagValue string) error { mergeFunction := func(flagName string, currentFieldStruct reflect.StructField, currentFieldElemValue reflect.Value, currentElemValue reflect.Value) error { currentFieldKind := currentFieldStruct.Type.Kind() if currentFieldKind == reflect.Slice { return mergeFlagValues(currentElemValue, []string{flagName}, fullFlagName, []string{flagValue}) } parsedValue, err := getParsedValue(currentFieldKind, flagValue) if err != nil { return fmt.Errorf("invalid value %s for flag name %s, expected %s", flagValue, flagName, currentFieldKind) } currentFieldElemValue.Set(parsedValue) return nil } return mergeFlag(configElemValue, flagPath, fullFlagName, mergeFunction) } func mergeFlagValues(configElemValue reflect.Value, flagPath []string, fullFlagName string, flagValues []string) error { mergeFunction := func(flagName string, currentFieldStruct reflect.StructField, currentFieldElemValue reflect.Value, currentElemValue reflect.Value) error { currentFieldKind := currentFieldStruct.Type.Kind() if currentFieldKind != reflect.Slice { return fmt.Errorf("invalid values %s for flag name %s, expected %s", strings.Join(flagValues, ","), flagName, currentFieldKind) } flagValueKind := currentFieldStruct.Type.Elem().Kind() parsedValues := reflect.MakeSlice(reflect.SliceOf(currentFieldStruct.Type.Elem()), 0, 0) for _, flagValue := range flagValues { parsedValue, err := getParsedValue(flagValueKind, flagValue) if err != nil { return fmt.Errorf("invalid value %s for flag name %s, expected %s", flagValue, flagName, flagValueKind) } parsedValues = reflect.Append(parsedValues, parsedValue) } currentFieldElemValue.Set(parsedValues) return nil } return mergeFlag(configElemValue, flagPath, fullFlagName, mergeFunction) } func mergeFlag(currentElemValue reflect.Value, currentFlagPath []string, fullFlagName string, mergeFunction func(flagName string, currentFieldStruct reflect.StructField, currentFieldElemValue reflect.Value, currentElemValue reflect.Value) error) error { if len(currentFlagPath) == 0 { return fmt.Errorf("flag \"%s\" not found", fullFlagName) } for i := 0; i < currentElemValue.NumField(); i++ { currentFieldStruct := currentElemValue.Type().Field(i) currentFieldElemValue := currentElemValue.FieldByName(currentFieldStruct.Name) if currentFieldStruct.Type.Kind() == reflect.Struct && getFieldNameByTag(currentFieldStruct) == currentFlagPath[0] { return mergeFlag(currentFieldElemValue, currentFlagPath[1:], fullFlagName, mergeFunction) } if len(currentFlagPath) > 1 || getFieldNameByTag(currentFieldStruct) != currentFlagPath[0] { continue } return mergeFunction(currentFlagPath[0], currentFieldStruct, currentFieldElemValue, currentElemValue) } return fmt.Errorf("flag \"%s\" not found", fullFlagName) } func getFieldNameByTag(field reflect.StructField) string { return strings.Split(field.Tag.Get(FieldNameTag), ",")[0] } func getParsedValue(kind reflect.Kind, value string) (reflect.Value, error) { switch kind { case reflect.String: return reflect.ValueOf(value), nil case reflect.Bool: boolArgumentValue, err := strconv.ParseBool(value) if err != nil { break } return reflect.ValueOf(boolArgumentValue), nil case reflect.Int: intArgumentValue, err := strconv.ParseInt(value, 10, 64) if err != nil { break } return reflect.ValueOf(int(intArgumentValue)), nil case reflect.Int8: intArgumentValue, err := strconv.ParseInt(value, 10, 8) if err != nil { break } return reflect.ValueOf(int8(intArgumentValue)), nil case reflect.Int16: intArgumentValue, err := strconv.ParseInt(value, 10, 16) if err != nil { break } return reflect.ValueOf(int16(intArgumentValue)), nil case reflect.Int32: intArgumentValue, err := strconv.ParseInt(value, 10, 32) if err != nil { break } return reflect.ValueOf(int32(intArgumentValue)), nil case reflect.Int64: intArgumentValue, err := strconv.ParseInt(value, 10, 64) if err != nil { break } return reflect.ValueOf(intArgumentValue), nil case reflect.Uint: uintArgumentValue, err := strconv.ParseUint(value, 10, 64) if err != nil { break } return reflect.ValueOf(uint(uintArgumentValue)), nil case reflect.Uint8: uintArgumentValue, err := strconv.ParseUint(value, 10, 8) if err != nil { break } return reflect.ValueOf(uint8(uintArgumentValue)), nil case reflect.Uint16: uintArgumentValue, err := strconv.ParseUint(value, 10, 16) if err != nil { break } return reflect.ValueOf(uint16(uintArgumentValue)), nil case reflect.Uint32: uintArgumentValue, err := strconv.ParseUint(value, 10, 32) if err != nil { break } return reflect.ValueOf(uint32(uintArgumentValue)), nil case reflect.Uint64: uintArgumentValue, err := strconv.ParseUint(value, 10, 64) if err != nil { break } return reflect.ValueOf(uintArgumentValue), nil } return reflect.ValueOf(nil), errors.New("value to parse does not match type") } func setZeroForReadonlyFields(currentElem reflect.Value) { for i := 0; i < currentElem.NumField(); i++ { currentField := currentElem.Type().Field(i) currentFieldByName := currentElem.FieldByName(currentField.Name) if currentField.Type.Kind() == reflect.Struct { setZeroForReadonlyFields(currentFieldByName) continue } if _, ok := currentField.Tag.Lookup(ReadonlyTag); ok { currentFieldByName.Set(reflect.Zero(currentField.Type)) } } } 07070100000027000081A400000000000000000000000166E627D7000012EF000000000000000000000000000000000000002D00000000kubeshark-cli-52.3.82/config/configStruct.gopackage config import ( "os" "path/filepath" "github.com/kubeshark/kubeshark/config/configStructs" v1 "k8s.io/api/core/v1" "k8s.io/client-go/util/homedir" ) const ( KubeConfigPathConfigName = "kube-configPath" ) func CreateDefaultConfig() 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: "", CanDownloadPCAP: true, CanUseScripting: true, CanUpdateTargetedPods: true, CanStopTrafficCapturing: true, ShowAdminConsoleLink: true, }, }, }, }, EnabledDissectors: []string{ "amqp", "dns", "http", "icmp", "kafka", "redis", "sctp", "syscall", "tcp", "ws", }, }, } } type KubeConfig struct { ConfigPathStr string `yaml:"configPath" json:"configPath"` Context string `yaml:"context" json:"context"` } type ManifestsConfig struct { Dump bool `yaml:"dump" json:"dump"` } type ConfigStruct struct { 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:""` CloudLicenseEnabled bool `yaml:"cloudLicenseEnabled" json:"cloudLicenseEnabled" default:"true"` SupportChatEnabled bool `yaml:"supportChatEnabled" json:"supportChatEnabled" default:"true"` InternetConnectivity bool `yaml:"internetConnectivity" json:"internetConnectivity" default:"true"` DissectorsUpdatingEnabled bool `yaml:"dissectorsUpdatingEnabled" json:"dissectorsUpdatingEnabled" default:"true"` 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 { return v1.PullPolicy(config.Tap.Docker.ImagePullPolicy) } func (config *ConfigStruct) ImagePullSecrets() []v1.LocalObjectReference { var ref []v1.LocalObjectReference for _, name := range config.Tap.Docker.ImagePullSecrets { ref = append(ref, v1.LocalObjectReference{Name: name}) } return ref } func (config *ConfigStruct) KubeConfigPath() string { if config.Kube.ConfigPathStr != "" { return config.Kube.ConfigPathStr } envKubeConfigPath := os.Getenv("KUBECONFIG") if envKubeConfigPath != "" { return envKubeConfigPath } home := homedir.HomeDir() return filepath.Join(home, ".kube", "config") } 07070100000028000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/config/configStructs07070100000029000081A400000000000000000000000166E627D7000000CB000000000000000000000000000000000000003B00000000kubeshark-cli-52.3.82/config/configStructs/configConfig.gopackage configStructs const ( RegenerateConfigName = "regenerate" ) type ConfigConfig struct { Regenerate bool `yaml:"regenerate,omitempty" json:"regenerate,omitempty" default:"false" readonly:""` } 0707010000002A000081A400000000000000000000000166E627D7000002C4000000000000000000000000000000000000003900000000kubeshark-cli-52.3.82/config/configStructs/logsConfig.gopackage configStructs import ( "fmt" "os" "path" "github.com/kubeshark/kubeshark/misc" ) const ( FileLogsName = "file" GrepLogsName = "grep" ) type LogsConfig struct { FileStr string `yaml:"file" json:"file"` Grep string `yaml:"grep" json:"grep"` } func (config *LogsConfig) Validate() error { if config.FileStr == "" { _, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get PWD, %v (try using `%s logs -f <full path dest zip file>)`", err, misc.Program) } } return nil } func (config *LogsConfig) FilePath() string { if config.FileStr == "" { pwd, _ := os.Getwd() return path.Join(pwd, fmt.Sprintf("%s_logs.zip", misc.Program)) } return config.FileStr } 0707010000002B000081A400000000000000000000000166E627D7000003B1000000000000000000000000000000000000003E00000000kubeshark-cli-52.3.82/config/configStructs/scriptingConfig.gopackage configStructs import ( "io/fs" "os" "path/filepath" "github.com/kubeshark/kubeshark/misc" "github.com/rs/zerolog/log" ) type ScriptingConfig struct { 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) { if config.Source == "" { return } var files []fs.DirEntry files, err = os.ReadDir(config.Source) if err != nil { return } for _, f := range files { if f.IsDir() { continue } var script *misc.Script path := filepath.Join(config.Source, f.Name()) script, err = misc.ReadScriptFile(path) if err != nil { return } scripts = append(scripts, script) log.Debug().Str("path", path).Msg("Found script:") } return } 0707010000002C000081A400000000000000000000000166E627D700002FF5000000000000000000000000000000000000003800000000kubeshark-cli-52.3.82/config/configStructs/tapConfig.gopackage configStructs import ( "fmt" "regexp" v1 "k8s.io/api/core/v1" networking "k8s.io/api/networking/v1" ) 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" ExcludedNamespacesLabel = "excludedNamespaces" 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" PprofPortLabel = "pprof-port" PprofViewLabel = "pprof-view" DebugLabel = "debug" ContainerPort = 80 ContainerPortStr = "80" ) type ResourceLimitsHub struct { CPU string `yaml:"cpu" json:"cpu" default:"1000m"` Memory string `yaml:"memory" json:"memory" default:"1500Mi"` } type ResourceLimitsWorker struct { CPU string `yaml:"cpu" json:"cpu" default:"1200m"` Memory string `yaml:"memory" json:"memory" default:"2000Mi"` } type ResourceRequests struct { CPU string `yaml:"cpu" json:"cpu" default:"50m"` Memory string `yaml:"memory" json:"memory" default:"50Mi"` } type ResourceRequirementsHub struct { Limits ResourceLimitsHub `yaml:"limits" json:"limits"` Requests ResourceRequests `yaml:"requests" json:"requests"` } type ResourceRequirementsWorker struct { Limits ResourceLimitsHub `yaml:"limits" json:"limits"` Requests ResourceRequests `yaml:"requests" json:"requests"` } type WorkerConfig struct { SrvPort uint16 `yaml:"srvPort" json:"srvPort" default:"30001"` } type HubConfig struct { SrvPort uint16 `yaml:"srvPort" json:"srvPort" default:"8898"` } type FrontConfig struct { Port uint16 `yaml:"port" json:"port" default:"8899"` } type ProxyConfig struct { 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 OverrideTagConfig struct { Worker string `yaml:"worker" json:"worker"` Hub string `yaml:"hub" json:"hub"` Front string `yaml:"front" json:"front"` } type DockerConfig struct { Registry string `yaml:"registry" json:"registry" default:"docker.io/kubeshark"` Tag string `yaml:"tag" json:"tag" default:""` TagLocked bool `yaml:"tagLocked" json:"tagLocked" default:"true"` ImagePullPolicy string `yaml:"imagePullPolicy" json:"imagePullPolicy" default:"Always"` ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets"` OverrideTag OverrideTagConfig `yaml:"overrideTag" json:"overrideTag"` } type ResourcesConfig struct { Hub ResourceRequirementsHub `yaml:"hub" json:"hub"` Sniffer ResourceRequirementsWorker `yaml:"sniffer" json:"sniffer"` Tracer ResourceRequirementsWorker `yaml:"tracer" json:"tracer"` } type Role struct { Filter string `yaml:"filter" json:"filter" default:""` CanDownloadPCAP bool `yaml:"canDownloadPCAP" json:"canDownloadPCAP" default:"false"` CanUseScripting bool `yaml:"canUseScripting" json:"canUseScripting" default:"false"` CanUpdateTargetedPods bool `yaml:"canUpdateTargetedPods" json:"canUpdateTargetedPods" default:"false"` CanStopTrafficCapturing bool `yaml:"canStopTrafficCapturing" json:"canStopTrafficCapturing" 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 { 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" 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 SentryConfig struct { Enabled bool `yaml:"enabled" json:"enabled" default:"false"` Environment string `yaml:"environment" json:"environment" default:"production"` } 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:"false"` 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 PprofConfig struct { Enabled bool `yaml:"enabled" json:"enabled" default:"false"` Port uint16 `yaml:"port" json:"port" default:"8000"` View string `yaml:"view" json:"view" default:"flamegraph"` } 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"` ResolutionStrategy string `yaml:"resolutionStrategy" json:"resolutionStrategy" default:"auto"` DuplicateTimeframe string `yaml:"duplicateTimeframe" json:"duplicateTimeframe" default:"200ms"` DetectDuplicates bool `yaml:"detectDuplicates" json:"detectDuplicates" default:"false"` } type TapConfig struct { 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:"[]"` ExcludedNamespaces []string `yaml:"excludedNamespaces" json:"excludedNamespaces" default:"[]"` BpfOverride string `yaml:"bpfOverride" json:"bpfOverride" default:""` Stopped bool `yaml:"stopped" json:"stopped" default:"true"` 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:"5000Mi"` 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"` DisableTlsLog bool `yaml:"disableTlsLog" json:"disableTlsLog" default:"false"` 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"` Sentry SentryConfig `yaml:"sentry" json:"sentry"` DefaultFilter string `yaml:"defaultFilter" json:"defaultFilter" default:"!dns and !tcp"` ScriptingDisabled bool `yaml:"scriptingDisabled" json:"scriptingDisabled" default:"false"` TargetedPodsUpdateDisabled bool `yaml:"targetedPodsUpdateDisabled" json:"targetedPodsUpdateDisabled" default:"false"` RecordingDisabled bool `yaml:"recordingDisabled" json:"recordingDisabled" default:"false"` StopTrafficCapturingDisabled bool `yaml:"stopTrafficCapturingDisabled" json:"stopTrafficCapturingDisabled" default:"false"` Capabilities CapabilitiesConfig `yaml:"capabilities" json:"capabilities"` GlobalFilter string `yaml:"globalFilter" json:"globalFilter"` EnabledDissectors []string `yaml:"enabledDissectors" json:"enabledDissectors"` Metrics MetricsConfig `yaml:"metrics" json:"metrics"` Pprof PprofConfig `yaml:"pprof" json:"pprof"` Misc MiscConfig `yaml:"misc" json:"misc"` } func (config *TapConfig) PodRegex() *regexp.Regexp { podRegex, _ := regexp.Compile(config.PodRegexStr) return podRegex } func (config *TapConfig) Validate() error { _, compileErr := regexp.Compile(config.PodRegexStr) if compileErr != nil { return fmt.Errorf("%s is not a valid regex %s", config.PodRegexStr, compileErr) } return nil } 0707010000002D000081A400000000000000000000000166E627D7000040B1000000000000000000000000000000000000003500000000kubeshark-cli-52.3.82/config/config_internal_test.gopackage config import ( "fmt" "reflect" "testing" ) type ConfigMock struct { SectionMock SectionMock `yaml:"section"` Test string `yaml:"test"` StringField string `yaml:"string-field"` IntField int `yaml:"int-field"` BoolField bool `yaml:"bool-field"` UintField uint `yaml:"uint-field"` StringSliceField []string `yaml:"string-slice-field"` IntSliceField []int `yaml:"int-slice-field"` BoolSliceField []bool `yaml:"bool-slice-field"` UintSliceField []uint `yaml:"uint-slice-field"` } type SectionMock struct { Test string `yaml:"test"` } type FieldSetValues struct { SetValues []string FieldName string FieldValue interface{} } func TestMergeSetFlagNoSeparator(t *testing.T) { tests := []struct { Name string SetValues []string }{ {Name: "empty value", SetValues: []string{""}}, {Name: "single char", SetValues: []string{"t"}}, {Name: "combine empty value and single char", SetValues: []string{"", "t"}}, {Name: "two values without separator", SetValues: []string{"test", "test:true"}}, {Name: "four values without separator", SetValues: []string{"test", "test:true", "testing!", "true"}}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() err := mergeSetFlag(configMockElemValue, test.SetValues) if err == nil { t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues) return } for i := 0; i < configMockElemValue.NumField(); i++ { currentField := configMockElemValue.Type().Field(i) currentFieldByName := configMockElemValue.FieldByName(currentField.Name) if !currentFieldByName.IsZero() { t.Errorf("unexpected value with not default value - SetValues: %v", test.SetValues) } } }) } } func TestMergeSetFlagInvalidFlagName(t *testing.T) { tests := []struct { Name string SetValues []string }{ {Name: "invalid flag name", SetValues: []string{"invalid_flag=true"}}, {Name: "invalid flag name inside section struct", SetValues: []string{"section.invalid_flag=test"}}, {Name: "flag name is a struct", SetValues: []string{"section=test"}}, {Name: "empty flag name", SetValues: []string{"=true"}}, {Name: "four tests combined", SetValues: []string{"invalid_flag=true", "config.invalid_flag=test", "section=test", "=true"}}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() err := mergeSetFlag(configMockElemValue, test.SetValues) if err == nil { t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues) return } for i := 0; i < configMockElemValue.NumField(); i++ { currentField := configMockElemValue.Type().Field(i) currentFieldByName := configMockElemValue.FieldByName(currentField.Name) if !currentFieldByName.IsZero() { t.Errorf("unexpected case - SetValues: %v", test.SetValues) } } }) } } func TestMergeSetFlagInvalidFlagValue(t *testing.T) { tests := []struct { Name string SetValues []string }{ {Name: "bool value to int field", SetValues: []string{"int-field=true"}}, {Name: "int value to bool field", SetValues: []string{"bool-field:5"}}, {Name: "int value to uint field", SetValues: []string{"uint-field=-1"}}, {Name: "bool value to int slice field", SetValues: []string{"int-slice-field=true"}}, {Name: "int value to bool slice field", SetValues: []string{"bool-slice-field=5"}}, {Name: "int value to uint slice field", SetValues: []string{"uint-slice-field=-1"}}, {Name: "int slice value to int field", SetValues: []string{"int-field=6", "int-field=66"}}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() err := mergeSetFlag(configMockElemValue, test.SetValues) if err == nil { t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues) return } for i := 0; i < configMockElemValue.NumField(); i++ { currentField := configMockElemValue.Type().Field(i) currentFieldByName := configMockElemValue.FieldByName(currentField.Name) if !currentFieldByName.IsZero() { t.Errorf("unexpected case - SetValues: %v", test.SetValues) } } }) } } func TestMergeSetFlagNotSliceValues(t *testing.T) { tests := []struct { Name string FieldsSetValues []FieldSetValues }{ {Name: "string field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"}}}, {Name: "int field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6}}}, {Name: "bool field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true}}}, {Name: "uint field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)}}}, {Name: "four fields combined", FieldsSetValues: []FieldSetValues { {SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"}, {SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6}, {SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true}, {SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)}, }}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() var setValues []string for _, fieldSetValues := range test.FieldsSetValues { setValues = append(setValues, fieldSetValues.SetValues...) } err := mergeSetFlag(configMockElemValue, setValues) if err != nil { t.Errorf("unexpected error result - err: %v", err) return } for _, fieldSetValues := range test.FieldsSetValues { fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface() if fieldValue != fieldSetValues.FieldValue { t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue) } } }) } } func TestMergeSetFlagSliceValues(t *testing.T) { tests := []struct { Name string FieldsSetValues []FieldSetValues }{ {Name: "string slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}}}}, {Name: "int slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}}}}, {Name: "bool slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}}}}, {Name: "uint slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}}}}, {Name: "four single value fields combined", FieldsSetValues: []FieldSetValues{ {SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}}, {SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}}, {SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}}, {SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}}, }}, {Name: "string slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}}}}, {Name: "int slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}}}}, {Name: "bool slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}}}}, {Name: "uint slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}}}}, {Name: "four two values fields combined", FieldsSetValues: []FieldSetValues{ {SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}}, {SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}}, {SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}}, {SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}}, }}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() var setValues []string for _, fieldSetValues := range test.FieldsSetValues { setValues = append(setValues, fieldSetValues.SetValues...) } err := mergeSetFlag(configMockElemValue, setValues) if err != nil { t.Errorf("unexpected error result - err: %v", err) return } for _, fieldSetValues := range test.FieldsSetValues { fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface() if !reflect.DeepEqual(fieldValue, fieldSetValues.FieldValue) { t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue) } } }) } } func TestMergeSetFlagMixValues(t *testing.T) { tests := []struct { Name string FieldsSetValues []FieldSetValues }{ {Name: "single value all fields", FieldsSetValues: []FieldSetValues{ {SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}}, {SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}}, {SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}}, {SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}}, {SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"}, {SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6}, {SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true}, {SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)}, }}, {Name: "two values slice fields and single value fields", FieldsSetValues: []FieldSetValues{ {SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}}, {SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}}, {SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}}, {SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}}, {SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"}, {SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6}, {SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true}, {SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)}, }}, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { configMock := ConfigMock{} configMockElemValue := reflect.ValueOf(&configMock).Elem() var setValues []string for _, fieldSetValues := range test.FieldsSetValues { setValues = append(setValues, fieldSetValues.SetValues...) } err := mergeSetFlag(configMockElemValue, setValues) if err != nil { t.Errorf("unexpected error result - err: %v", err) return } for _, fieldSetValues := range test.FieldsSetValues { fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface() if !reflect.DeepEqual(fieldValue, fieldSetValues.FieldValue) { t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue) } } }) } } func TestGetParsedValueValidValue(t *testing.T) { tests := []struct { StringValue string Kind reflect.Kind ActualValue interface{} }{ {StringValue: "test", Kind: reflect.String, ActualValue: "test"}, {StringValue: "123", Kind: reflect.String, ActualValue: "123"}, {StringValue: "true", Kind: reflect.Bool, ActualValue: true}, {StringValue: "false", Kind: reflect.Bool, ActualValue: false}, {StringValue: "6", Kind: reflect.Int, ActualValue: 6}, {StringValue: "-6", Kind: reflect.Int, ActualValue: -6}, {StringValue: "6", Kind: reflect.Int8, ActualValue: int8(6)}, {StringValue: "-6", Kind: reflect.Int8, ActualValue: int8(-6)}, {StringValue: "6", Kind: reflect.Int16, ActualValue: int16(6)}, {StringValue: "-6", Kind: reflect.Int16, ActualValue: int16(-6)}, {StringValue: "6", Kind: reflect.Int32, ActualValue: int32(6)}, {StringValue: "-6", Kind: reflect.Int32, ActualValue: int32(-6)}, {StringValue: "6", Kind: reflect.Int64, ActualValue: int64(6)}, {StringValue: "-6", Kind: reflect.Int64, ActualValue: int64(-6)}, {StringValue: "6", Kind: reflect.Uint, ActualValue: uint(6)}, {StringValue: "66", Kind: reflect.Uint, ActualValue: uint(66)}, {StringValue: "6", Kind: reflect.Uint8, ActualValue: uint8(6)}, {StringValue: "66", Kind: reflect.Uint8, ActualValue: uint8(66)}, {StringValue: "6", Kind: reflect.Uint16, ActualValue: uint16(6)}, {StringValue: "66", Kind: reflect.Uint16, ActualValue: uint16(66)}, {StringValue: "6", Kind: reflect.Uint32, ActualValue: uint32(6)}, {StringValue: "66", Kind: reflect.Uint32, ActualValue: uint32(66)}, {StringValue: "6", Kind: reflect.Uint64, ActualValue: uint64(6)}, {StringValue: "66", Kind: reflect.Uint64, ActualValue: uint64(66)}, } for _, test := range tests { t.Run(fmt.Sprintf("%v %v", test.Kind, test.StringValue), func(t *testing.T) { parsedValue, err := getParsedValue(test.Kind, test.StringValue) if err != nil { t.Errorf("unexpected error result - err: %v", err) return } if parsedValue.Interface() != test.ActualValue { t.Errorf("unexpected result - expected: %v, actual: %v", test.ActualValue, parsedValue) } }) } } func TestGetParsedValueInvalidValue(t *testing.T) { tests := []struct { StringValue string Kind reflect.Kind }{ {StringValue: "test", Kind: reflect.Bool}, {StringValue: "123", Kind: reflect.Bool}, {StringValue: "test", Kind: reflect.Int}, {StringValue: "true", Kind: reflect.Int}, {StringValue: "test", Kind: reflect.Int8}, {StringValue: "true", Kind: reflect.Int8}, {StringValue: "test", Kind: reflect.Int16}, {StringValue: "true", Kind: reflect.Int16}, {StringValue: "test", Kind: reflect.Int32}, {StringValue: "true", Kind: reflect.Int32}, {StringValue: "test", Kind: reflect.Int64}, {StringValue: "true", Kind: reflect.Int64}, {StringValue: "test", Kind: reflect.Uint}, {StringValue: "-6", Kind: reflect.Uint}, {StringValue: "test", Kind: reflect.Uint8}, {StringValue: "-6", Kind: reflect.Uint8}, {StringValue: "test", Kind: reflect.Uint16}, {StringValue: "-6", Kind: reflect.Uint16}, {StringValue: "test", Kind: reflect.Uint32}, {StringValue: "-6", Kind: reflect.Uint32}, {StringValue: "test", Kind: reflect.Uint64}, {StringValue: "-6", Kind: reflect.Uint64}, } for _, test := range tests { t.Run(fmt.Sprintf("%v %v", test.Kind, test.StringValue), func(t *testing.T) { parsedValue, err := getParsedValue(test.Kind, test.StringValue) if err == nil { t.Errorf("unexpected unhandled error - stringValue: %v, Kind: %v", test.StringValue, test.Kind) return } if parsedValue != reflect.ValueOf(nil) { t.Errorf("unexpected parsed value - parsedValue: %v", parsedValue) } }) } } 0707010000002E000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001F00000000kubeshark-cli-52.3.82/debounce0707010000002F000081A400000000000000000000000166E627D7000003BC000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/debounce/debounce.gopackage debounce import ( "fmt" "time" ) func NewDebouncer(timeout time.Duration, callback func()) *Debouncer { var debouncer Debouncer debouncer.setTimeout(timeout) debouncer.setCallback(callback) return &debouncer } type Debouncer struct { callback func() running bool canceled bool timeout time.Duration timer *time.Timer } func (d *Debouncer) setTimeout(timeout time.Duration) { // TODO: Return err if d.running d.timeout = timeout } func (d *Debouncer) setCallback(callback func()) { callbackWrapped := func() { if !d.canceled { callback() } d.running = false } d.callback = callbackWrapped } func (d *Debouncer) Cancel() { d.canceled = true } func (d *Debouncer) SetOn() error { if d.canceled { return fmt.Errorf("debouncer cancelled") } if d.running { return nil } d.running = true d.timer = time.AfterFunc(d.timeout, d.callback) return nil } func (d *Debouncer) IsOn() bool { return d.running } 07070100000030000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/errormessage07070100000031000081A400000000000000000000000166E627D7000004F2000000000000000000000000000000000000003300000000kubeshark-cli-52.3.82/errormessage/errormessage.gopackage errormessage import ( "errors" "fmt" regexpsyntax "regexp/syntax" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/config/configStructs" "github.com/kubeshark/kubeshark/misc" k8serrors "k8s.io/apimachinery/pkg/api/errors" ) // formatError wraps error with a detailed message that is meant for the user. // While the errors are meant to be displayed, they are not meant to be exported as classes outsite of CLI. func FormatError(err error) error { var errorNew error if k8serrors.IsForbidden(err) { errorNew = fmt.Errorf("insufficient permissions: %w. "+ "supply the required permission or control %s's access to namespaces by setting %s "+ "in the config file or setting the targeted namespace with --%s %s=<NAMESPACE>", err, misc.Software, configStructs.ReleaseNamespaceLabel, config.SetCommandName, configStructs.ReleaseNamespaceLabel) } else if syntaxError, isSyntaxError := asRegexSyntaxError(err); isSyntaxError { errorNew = fmt.Errorf("regex %s is invalid: %w", syntaxError.Expr, err) } else { errorNew = err } return errorNew } func asRegexSyntaxError(err error) (*regexpsyntax.Error, bool) { var syntaxError *regexpsyntax.Error return syntaxError, errors.As(err, &syntaxError) } 07070100000032000081A400000000000000000000000166E627D700001E5D000000000000000000000000000000000000001D00000000kubeshark-cli-52.3.82/go.modmodule github.com/kubeshark/kubeshark go 1.20 require ( github.com/creasty/defaults v1.5.2 github.com/fsnotify/fsnotify v1.6.0 github.com/go-cmd/cmd v1.4.3 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/pkg/errors v0.9.1 github.com/rivo/tview v0.0.0-20240818110301-fd649dbf1223 github.com/robertkrimen/otto v0.2.1 github.com/rs/zerolog v1.28.0 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e 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 ( 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/BurntSushi/toml v1.2.1 // indirect github.com/MakeNowJust/heredoc v1.0.0 // 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/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // 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/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/fatih/color v1.13.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/tcell/v2 v2.7.1 // indirect github.com/go-errors/errors v1.4.2 // 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/validator/v10 v10.14.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // 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/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/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/klauspost/compress v1.16.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // 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.19 // indirect github.com/mattn/go-runewidth v0.0.15 // 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-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.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // 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/rivo/uniseg v0.4.7 // 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/stretchr/testify v1.8.3 // 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/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.17.0 // indirect golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.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/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 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 ) 07070100000033000081A400000000000000000000000166E627D70001A9FE000000000000000000000000000000000000001D00000000kubeshark-cli-52.3.82/go.sumcloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QPUqhJldz8= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/a8m/expect v1.0.0/go.mod h1:4IwSCMumY49ScypDnjNbYEjgVeqy1/U2cEs3Lat96eA= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg= github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creasty/defaults v1.5.2 h1:/VfB6uxpyp6h0fr7SPp7n8WJBoV8jfxQXPCnkVSjyls= github.com/creasty/defaults v1.5.2/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc= github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-cmd/cmd v1.4.3 h1:6y3G+3UqPerXvPcXvj+5QNPHT02BUw7p6PsqRxLNA7Y= github.com/go-cmd/cmd v1.4.3/go.mod h1:u3hxg/ry+D5kwh8WvUkHLAMe2zQCaXd00t35WfQaOFk= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.0.5 h1:PUjzYdYu3HBOh8LE+UUmRG2P0IRDak9XMeGNvaeq4Ow= github.com/go-gorp/gorp/v3 v3.0.5/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ= github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v37 v37.0.0 h1:rCspN8/6kB1BAJWZfuafvHhyfIo5fkAulaP/3bOQ/tM= github.com/google/go-github/v37 v37.0.0/go.mod h1:LM7in3NmXDrX58GbEHy7FtNLbI2JijX93RnMKvWG3m4= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rivo/tview v0.0.0-20240818110301-fd649dbf1223 h1:N+DggyldbUDqFlk0b8JeRjB9zGpmQ8wiKpq+VBbzRso= github.com/rivo/tview v0.0.0-20240818110301-fd649dbf1223/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0= github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e h1:+qDZ81UqxfZsWK6Vq9wET3AsdQxHGbViYOqkNxZ9FnU= github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e/go.mod h1:ANZlXE3vfRYCYnkojePl2hJODYmOeCVD+XahuhDdTbI= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= helm.sh/helm/v3 v3.12.0 h1:rOq2TPVzg5jt4q5ermAZGZFxNW2uQhKjRhBneAutMEM= helm.sh/helm/v3 v3.12.0/go.mod h1:8K/469yxjUMu6BaD2EagCitkPjELUL/l2AgCO142G94= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= k8s.io/apiextensions-apiserver v0.27.1 h1:Hp7B3KxKHBZ/FxmVFVpaDiXI6CCSr49P1OJjxKO6o4g= k8s.io/apiextensions-apiserver v0.27.1/go.mod h1:8jEvRDtKjVtWmdkhOqE84EcNWJt/uwF8PC4627UZghY= k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= k8s.io/apiserver v0.27.1 h1:phY+BtXjjzd+ta3a4kYbomC81azQSLa1K8jo9RBw7Lg= k8s.io/apiserver v0.27.1/go.mod h1:UGrOjLY2KsieA9Fw6lLiTObxTb8Z1xEba4uqSuMY0WU= k8s.io/cli-runtime v0.28.3 h1:lvuJYVkwCqHEvpS6KuTZsUVwPePFjBfSGvuaLl2SxzA= k8s.io/cli-runtime v0.28.3/go.mod h1:jeX37ZPjIcENVuXDDTskG3+FnVuZms5D9omDXS/2Jjc= k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= k8s.io/kubectl v0.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k= k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.2 h1:0E9tOHUfrNH7TCDk5KU0jVBEzCqbfdyuVfGmJ7ZeRPE= oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 07070100000034000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/helm-chart07070100000035000081A400000000000000000000000166E627D700000257000000000000000000000000000000000000002C00000000kubeshark-cli-52.3.82/helm-chart/Chart.yamlapiVersion: v2 name: kubeshark version: "52.3.82" description: The API Traffic Analyzer for Kubernetes home: https://kubeshark.co keywords: - kubeshark - packet capture - traffic capture - traffic analyzer - network sniffer - observability - devops - microservice - forensics - api kubeVersion: '>= 1.16.0-0' maintainers: - email: info@kubeshark.co name: Kubeshark url: https://kubeshark.co sources: - https://github.com/kubeshark/kubeshark/tree/master/helm-chart type: application icon: https://raw.githubusercontent.com/kubeshark/assets/master/logo/vector/logo.svg 07070100000036000081A400000000000000000000000166E627D700002A05000000000000000000000000000000000000002900000000kubeshark-cli-52.3.82/helm-chart/LICENSE Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2022 Kubeshark Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 07070100000037000081A400000000000000000000000166E627D700001456000000000000000000000000000000000000002C00000000kubeshark-cli-52.3.82/helm-chart/PF_RING.md# 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). 07070100000038000081A400000000000000000000000166E627D700004B22000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/helm-chart/README.md# Helm Chart of Kubeshark ## Official Add the Helm repo for Kubeshark: ```shell helm repo add kubeshark https://helm.kubeshark.co ``` then install Kubeshark: ```shell helm install kubeshark kubeshark/kubeshark ``` ## Local Clone the repo: ```shell git clone git@github.com:kubeshark/kubeshark.git --depth 1 cd kubeshark/helm-chart ``` In case you want to clone a specific tag of the repo (e.g. `v52.3.59`): ```shell git clone git@github.com:kubeshark/kubeshark.git --depth 1 --branch <tag> cd kubeshark/helm-chart ``` > See the list of available tags here: https://github.com/kubeshark/kubeshark/tags Render the templates ```shell helm template . ``` Install Kubeshark: ```shell helm install kubeshark . ``` Uninstall Kubeshark: ```shell helm uninstall kubeshark ``` ## Port-forward Do the port forwarding: ```shell kubectl port-forward service/kubeshark-front 8899:80 ``` Visit [localhost:8899](http://localhost:8899) ## 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.ipv6=false ``` ## 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.tagLocked` | Lock the Docker image tags to prevent automatic upgrades to the latest branch image version. | `true` | | `tap.docker.tagLocked` | If `false` - use latest minor tag | `true` | | `tap.docker.imagePullPolicy` | Kubernetes image pull policy | `Always` | | `tap.docker.imagePullSecrets` | Kubernetes secrets to pull the images | `[]` | | `tap.docker.overrideTag` | DANGER: Used to override specific images, when testing custom features from the Kubeshark team | `""` | | `tap.proxy.hub.srvPort` | Hub server port. Change if already occupied. | `8898` | | `tap.proxy.worker.srvPort` | Worker server port. Change if already occupied.| `30001` | | `tap.proxy.front.port` | Front service port. Change if already occupied.| `8899` | | `tap.proxy.host` | Change to 0.0.0.0 top open up to the world. | `127.0.0.1` | | `tap.regex` | Target (process traffic from) pods that match regex | `.*` | | `tap.namespaces` | Target pods in namespaces | `[]` | | `tap.excludedNamespaces` | Exclude pods in namespaces | `[]` | | `tap.bpfOverride` | When using AF_PACKET as a traffic capture backend, override any existing pod targeting rules and set explicit BPF expression (e.g. `net 0.0.0.0/0`). | `[]` | | `tap.stopped` | Set to `false` to have traffic processing start automatically. When set to `true`, traffic processing is stopped by default, resulting in almost no resource consumption (e.g. Kubeshark is dormant). This property can be dynamically control via the dashboard. | `true` | | `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.resources.hub.limits.cpu` | CPU limit for hub | `1000m` | | `tap.resources.hub.limits.memory` | Memory limit for hub | `1500Mi` | | `tap.resources.hub.requests.cpu` | CPU request for hub | `50m` | | `tap.resources.hub.requests.memory` | Memory request for hub | `50Mi` | | `tap.resources.sniffer.limits.cpu` | CPU limit for sniffer | `1000m` | | `tap.resources.sniffer.limits.memory` | Memory limit for sniffer | `1500Mi` | | `tap.resources.sniffer.requests.cpu` | CPU request for sniffer | `50m` | | `tap.resources.sniffer.requests.memory` | Memory request for sniffer | `50Mi` | | `tap.resources.tracer.limits.cpu` | CPU limit for tracer | `1000m` | | `tap.resources.tracer.limits.memory` | Memory limit for tracer | `1500Mi` | | `tap.resources.tracer.requests.cpu` | CPU request for tracer | `50m` | | `tap.resources.tracer.requests.memory` | Memory request for tracer | `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.disableTlsLog` | Suppress logging for TLS/eBPF | `false` | | `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,"canUpdateTargetedPods":true,"canUseScripting":true, "canStopTrafficCapturing":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)) | `false` | | `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.sentry.enabled` | Enable sending of error logs to Sentry | `false` | | `tap.sentry.environment` | Sentry environment to label error logs with | `production` | | `tap.defaultFilter` | Sets the default dashboard KFL filter (e.g. `http`). By default, this value is set to filter out DNS and TCP entries. The user can easily change this in the Dashboard. | `"!dns and !tcp"` | | `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. Another example `!dns` will not show any DNS traffic. | `""` | | `tap.metrics.port` | Pod port used to expose Prometheus metrics | `49100` | | `tap.enabledDissectors` | This is an array of strings representing the list of supported protocols. Remove or comment out redundant protocols (e.g., dns).| The default list includes: amqp, dns , http, icmp, kafka, redis,sctp, syscall, tcp, ws. | | `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` | | `timezone` | IANA time zone applied to time shown in the front-end | `""` (local time zone applies) | | `supportChatEnabled` | Enable real-time support chat channel based on Intercom | `true` | | `internetConnectivity` | Turns off API requests that are dependant on Internet connectivity such as `telemetry` and `online-support`. | `true` | | `dissectorsUpdatingEnabled` | Turns off UI for enabling/disabling dissectors | `true` | 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 -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----- ``` 07070100000039000081A400000000000000000000000166E627D700000939000000000000000000000000000000000000002C00000000kubeshark-cli-52.3.82/helm-chart/metrics.md# 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/). 0707010000003A000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/helm-chart/templates0707010000003B000081A400000000000000000000000166E627D700000143000000000000000000000000000000000000004300000000kubeshark-cli-52.3.82/helm-chart/templates/01-service-account.yaml--- apiVersion: v1 kind: ServiceAccount metadata: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} name: {{ include "kubeshark.serviceAccountName" . }} namespace: {{ .Release.Namespace }} 0707010000003C000081A400000000000000000000000166E627D7000004DC000000000000000000000000000000000000004000000000kubeshark-cli-52.3.82/helm-chart/templates/02-cluster-role.yaml--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: {{- 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 resources: - nodes - pods - services - endpoints - persistentvolumeclaims 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 0707010000003D000081A400000000000000000000000166E627D70000049A000000000000000000000000000000000000004800000000kubeshark-cli-52.3.82/helm-chart/templates/03-cluster-role-binding.yaml--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: {{- 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-{{ .Release.Namespace }} subjects: - kind: ServiceAccount 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 }} 0707010000003E000081A400000000000000000000000166E627D700000DB5000000000000000000000000000000000000004200000000kubeshark-cli-52.3.82/helm-chart/templates/04-hub-deployment.yaml--- 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: 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: SENTRY_ENABLED value: '{{ (include "sentry.enabled" .) }}' - name: SENTRY_ENVIRONMENT value: '{{ .Values.tap.sentry.environment }}' - name: KUBESHARK_CLOUD_API_URL value: 'https://api.kubeshark.co' - name: PROFILING_ENABLED value: '{{ .Values.tap.pprof.enabled }}' {{- if .Values.tap.docker.overrideTag.hub }} image: '{{ .Values.tap.docker.registry }}/hub:{{ .Values.tap.docker.overrideTag.hub }}' {{ else }} image: '{{ .Values.tap.docker.registry }}/hub:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (include "kubeshark.defaultVersion" .) }}' {{- end }} imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }} {{- if .Values.tap.docker.imagePullSecrets }} imagePullSecrets: {{- range .Values.tap.docker.imagePullSecrets }} - name: {{ . }} {{- end }} {{- end }} 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 0707010000003F000081A400000000000000000000000166E627D7000001C4000000000000000000000000000000000000003F00000000kubeshark-cli-52.3.82/helm-chart/templates/05-hub-service.yaml--- apiVersion: v1 kind: Service 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: kubeshark-hub namespace: {{ .Release.Namespace }} spec: ports: - name: kubeshark-hub port: 80 targetPort: 8080 selector: app.kubeshark.co/app: hub type: ClusterIP 07070100000040000081A400000000000000000000000166E627D7000013FC000000000000000000000000000000000000004400000000kubeshark-cli-52.3.82/helm-chart/templates/06-front-deployment.yamlapiVersion: 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: '{{- if or (and .Values.cloudLicenseEnabled (not (empty .Values.license))) (not .Values.internetConnectivity) -}} "false" {{- else -}} {{ .Values.cloudLicenseEnabled | ternary "true" .Values.tap.auth.enabled }} {{- end }}' - name: REACT_APP_AUTH_TYPE value: '{{ not (eq .Values.tap.auth.type "") | ternary (.Values.cloudLicenseEnabled | ternary "oidc" .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_SCRIPTING_DISABLED value: '{{ .Values.tap.scriptingDisabled }}' - name: REACT_APP_TARGETED_PODS_UPDATE_DISABLED value: '{{ .Values.tap.targetedPodsUpdateDisabled }}' - name: REACT_APP_BPF_OVERRIDE_DISABLED value: '{{ eq .Values.tap.packetCapture "ebpf" | ternary "true" "false" }}' - name: REACT_APP_RECORDING_DISABLED value: '{{ .Values.tap.recordingDisabled }}' - name: REACT_APP_STOP_TRAFFIC_CAPTURING_DISABLED value: '{{- if and .Values.tap.stopTrafficCapturingDisabled .Values.tap.stopped -}} false {{- else -}} {{ .Values.tap.stopTrafficCapturingDisabled | ternary "true" "false" }} {{- end -}}' - name: 'REACT_APP_CLOUD_LICENSE_ENABLED' value: '{{- if or (and .Values.cloudLicenseEnabled (not (empty .Values.license))) (not .Values.internetConnectivity) -}} "false" {{- else -}} {{ .Values.cloudLicenseEnabled }} {{- end }}' - name: REACT_APP_SUPPORT_CHAT_ENABLED value: '{{ and .Values.supportChatEnabled .Values.internetConnectivity | ternary "true" "false" }}' - name: REACT_APP_DISSECTORS_UPDATING_ENABLED value: '{{ .Values.dissectorsUpdatingEnabled | ternary "true" "false" }}' - name: REACT_APP_SENTRY_ENABLED value: '{{ (include "sentry.enabled" .) }}' - name: REACT_APP_SENTRY_ENVIRONMENT value: '{{ .Values.tap.sentry.environment }}' {{- if .Values.tap.docker.overrideTag.front }} image: '{{ .Values.tap.docker.registry }}/front:{{ .Values.tap.docker.overrideTag.front }}' {{ else }} image: '{{ .Values.tap.docker.registry }}/front:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (include "kubeshark.defaultVersion" .) }}' {{- end }} imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }} {{- if .Values.tap.docker.imagePullSecrets }} imagePullSecrets: {{- range .Values.tap.docker.imagePullSecrets }} - name: {{ . }} {{- end }} {{- end }} 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" . }} 07070100000041000081A400000000000000000000000166E627D7000001AC000000000000000000000000000000000000004100000000kubeshark-cli-52.3.82/helm-chart/templates/07-front-service.yaml--- apiVersion: v1 kind: Service metadata: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} name: kubeshark-front namespace: {{ .Release.Namespace }} spec: ports: - name: kubeshark-front port: 80 targetPort: 8080 selector: app.kubeshark.co/app: front type: ClusterIP 07070100000042000081A400000000000000000000000166E627D700000442000000000000000000000000000000000000004B00000000kubeshark-cli-52.3.82/helm-chart/templates/08-persistent-volume-claim.yaml--- {{- 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: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} name: kubeshark-persistent-volume-claim namespace: {{ .Release.Namespace }} spec: accessModes: - ReadWriteMany resources: requests: storage: {{ .Values.tap.storageLimit }} storageClassName: {{ .Values.tap.storageClass }} status: {} {{- end }} 07070100000043000081A400000000000000000000000166E627D700002843000000000000000000000000000000000000004500000000kubeshark-cli-52.3.82/helm-chart/templates/09-worker-daemon-set.yaml--- apiVersion: apps/v1 kind: DaemonSet metadata: labels: 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: {{ .Release.Namespace }} spec: selector: matchLabels: app.kubeshark.co/app: worker {{- include "kubeshark.selectorLabels" . | nindent 6 }} template: metadata: labels: 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 }} {{- if .Values.tap.docker.imagePullSecrets }} imagePullSecrets: {{- range .Values.tap.docker.imagePullSecrets }} - name: {{ . }} {{- end }} {{- end }} securityContext: capabilities: add: {{- range .Values.tap.capabilities.kernelModule }} {{ print "- " . }} {{- end }} drop: - ALL volumeMounts: - name: lib-modules mountPath: /lib/modules {{- end }} containers: - command: - ./worker - -i - any - -port - '{{ .Values.tap.proxy.worker.srvPort }}' - -metrics-port - '{{ .Values.tap.metrics.port }}' - -packet-capture - '{{ .Values.tap.packetCapture }}' - -unixsocket {{- if .Values.tap.serviceMesh }} - -servicemesh {{- end }} - -procfs - /hostproc {{- if .Values.tap.kernelModule.enabled }} - -kernel-module {{- end }} {{- if ne .Values.tap.packetCapture "ebpf" }} - -disable-ebpf {{- end }} - -resolution-strategy - '{{ .Values.tap.misc.resolutionStrategy }}' {{- if .Values.tap.debug }} - -debug {{- end }} {{- if .Values.tap.docker.overrideTag.worker }} image: '{{ .Values.tap.docker.registry }}/worker:{{ .Values.tap.docker.overrideTag.worker }}{{ include "kubeshark.dockerTagDebugVersion" . }}' {{ else }} image: '{{ .Values.tap.docker.registry }}/worker:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (include "kubeshark.defaultVersion" .) }}{{ include "kubeshark.dockerTagDebugVersion" . }}' {{- end }} imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }} {{- if .Values.tap.docker.imagePullSecrets }} imagePullSecrets: {{- range .Values.tap.docker.imagePullSecrets }} - name: {{ . }} {{- end }} {{- end }} name: sniffer ports: - 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' - name: PROFILING_ENABLED value: '{{ .Values.tap.pprof.enabled }}' - name: SENTRY_ENABLED value: '{{ (include "sentry.enabled" .) }}' - name: SENTRY_ENVIRONMENT value: '{{ .Values.tap.sentry.environment }}' resources: limits: cpu: {{ .Values.tap.resources.sniffer.limits.cpu }} memory: {{ .Values.tap.resources.sniffer.limits.memory }} requests: cpu: {{ .Values.tap.resources.sniffer.requests.cpu }} memory: {{ .Values.tap.resources.sniffer.requests.memory }} securityContext: capabilities: add: {{- 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 ne .Values.tap.packetCapture "ebpf" }} - -disable-ebpf {{- end }} {{- if .Values.tap.debug }} - -debug {{- end }} {{- if .Values.tap.disableTlsLog }} - -disable-tls-log {{- end }} {{- if .Values.tap.pprof.enabled }} - -port - '{{ add .Values.tap.proxy.worker.srvPort 1 }}' {{- end }} {{- if .Values.tap.docker.overrideTag.worker }} image: '{{ .Values.tap.docker.registry }}/worker:{{ .Values.tap.docker.overrideTag.worker }}{{ include "kubeshark.dockerTagDebugVersion" . }}' {{ else }} image: '{{ .Values.tap.docker.registry }}/worker:{{ not (eq .Values.tap.docker.tag "") | ternary .Values.tap.docker.tag (include "kubeshark.defaultVersion" .) }}{{ include "kubeshark.dockerTagDebugVersion" . }}' {{- end }} imagePullPolicy: {{ .Values.tap.docker.imagePullPolicy }} {{- if .Values.tap.docker.imagePullSecrets }} imagePullSecrets: {{- range .Values.tap.docker.imagePullSecrets }} - name: {{ . }} {{- end }} {{- end }} name: tracer env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: PROFILING_ENABLED value: '{{ .Values.tap.pprof.enabled }}' - name: SENTRY_ENABLED value: '{{ (include "sentry.enabled" .) }}' - name: SENTRY_ENVIRONMENT value: '{{ .Values.tap.sentry.environment }}' 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: - mountPath: /hostproc name: proc readOnly: true - mountPath: /sys name: sys readOnly: true - mountPath: /app/data name: data - mountPath: /etc/os-release name: os-release readOnly: true {{- end }} dnsPolicy: ClusterFirstWithHostNet hostNetwork: true 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 name: proc - hostPath: path: /sys name: sys - name: lib-modules hostPath: path: /lib/modules - hostPath: path: /etc/os-release name: os-release - name: data {{- if .Values.tap.persistentStorage }} persistentVolumeClaim: claimName: kubeshark-persistent-volume-claim {{- else }} emptyDir: sizeLimit: {{ .Values.tap.storageLimit }} {{- end }} 07070100000044000081A400000000000000000000000166E627D70000040C000000000000000000000000000000000000003B00000000kubeshark-cli-52.3.82/helm-chart/templates/10-ingress.yaml--- {{- 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 }} 07070100000045000081A400000000000000000000000166E627D7000006B1000000000000000000000000000000000000004400000000kubeshark-cli-52.3.82/helm-chart/templates/11-nginx-config-map.yaml--- 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; } } 07070100000046000081A400000000000000000000000166E627D700000CB7000000000000000000000000000000000000003E00000000kubeshark-cli-52.3.82/helm-chart/templates/12-config-map.yamlkind: 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) "" }}' EXCLUDED_NAMESPACES: '{{ gt (len .Values.tap.excludedNamespaces) 0 | ternary (join "," .Values.tap.excludedNamespaces) "" }}' BPF_OVERRIDE: '{{ .Values.tap.bpfOverride }}' STOPPED: '{{ .Values.tap.stopped | ternary "true" "false" }}' SCRIPTING_SCRIPTS: '{}' INGRESS_ENABLED: '{{ .Values.tap.ingress.enabled }}' INGRESS_HOST: '{{ .Values.tap.ingress.host }}' PROXY_FRONT_PORT: '{{ .Values.tap.proxy.front.port }}' AUTH_ENABLED: '{{- if and .Values.cloudLicenseEnabled (not (empty .Values.license)) -}} "false" {{- else -}} {{ .Values.cloudLicenseEnabled | ternary "true" (.Values.tap.auth.enabled | ternary "true" "") }} {{- end }}' AUTH_TYPE: '{{ .Values.cloudLicenseEnabled | ternary "oidc" (.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.internetConnectivity | ternary "true" (not .Values.tap.telemetry.enabled | ternary "true" "false") }}' SCRIPTING_DISABLED: '{{ .Values.tap.scriptingDisabled | ternary "true" "" }}' TARGETED_PODS_UPDATE_DISABLED: '{{ .Values.tap.targetedPodsUpdateDisabled | ternary "true" "" }}' RECORDING_DISABLED: '{{ .Values.tap.recordingDisabled | ternary "true" "" }}' STOP_TRAFFIC_CAPTURING_DISABLED: '{{- if and .Values.tap.stopTrafficCapturingDisabled .Values.tap.stopped -}} false {{- else -}} {{ .Values.tap.stopTrafficCapturingDisabled | ternary "true" "false" }} {{- end }}' 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 " " }}' CLOUD_LICENSE_ENABLED: '{{- if and .Values.cloudLicenseEnabled (not (empty .Values.license)) -}} false {{- else -}} {{ .Values.cloudLicenseEnabled }} {{- end }}' DUPLICATE_TIMEFRAME: '{{ .Values.tap.misc.duplicateTimeframe }}' ENABLED_DISSECTORS: '{{ gt (len .Values.tap.enabledDissectors) 0 | ternary (join "," .Values.tap.enabledDissectors) "" }}' DISSECTORS_UPDATING_ENABLED: '{{ .Values.dissectorsUpdatingEnabled | ternary "true" "false" }}' DETECT_DUPLICATES: '{{ .Values.tap.misc.detectDuplicates | ternary "true" "false" }}' 07070100000047000081A400000000000000000000000166E627D70000038B000000000000000000000000000000000000003A00000000kubeshark-cli-52.3.82/helm-chart/templates/13-secret.yamlkind: 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 }} --- 07070100000048000081A400000000000000000000000166E627D700000476000000000000000000000000000000000000005A00000000kubeshark-cli-52.3.82/helm-chart/templates/14-openshift-security-context-constraints.yaml{{- 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 - IPC_LOCK 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 }} 07070100000049000081A400000000000000000000000166E627D70000026C000000000000000000000000000000000000004A00000000kubeshark-cli-52.3.82/helm-chart/templates/15-worker-service-metrics.yaml--- kind: Service apiVersion: v1 metadata: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: prometheus.io/scrape: 'true' prometheus.io/port: '{{ .Values.tap.metrics.port }}' {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} name: kubeshark-worker-metrics namespace: {{ .Release.Namespace }} 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 }} 0707010000004A000081A400000000000000000000000166E627D70000068D000000000000000000000000000000000000004400000000kubeshark-cli-52.3.82/helm-chart/templates/16-network-policies.yamlapiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} 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: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} 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: labels: {{- include "kubeshark.labels" . | nindent 4 }} annotations: {{- if .Values.tap.annotations }} {{- toYaml .Values.tap.annotations | nindent 4 }} {{- end }} 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: - {} 0707010000004B000081A400000000000000000000000166E627D70000056D000000000000000000000000000000000000003500000000kubeshark-cli-52.3.82/helm-chart/templates/NOTES.txtThank 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) }} {{- if .Values.tap.docker.overrideTag.worker }} Overridden worker tag: {{ .Values.tap.docker.overrideTag.worker }} {{ end }} {{- if .Values.tap.docker.overrideTag.hub }} Overridden hub tag: {{ .Values.tap.docker.overrideTag.hub }} {{ end }} {{- if .Values.tap.docker.overrideTag.front }} Overridden front tag: {{ .Values.tap.docker.overrideTag.front }} {{ end }} 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 }} 0707010000004C000081A400000000000000000000000166E627D700000950000000000000000000000000000000000000003800000000kubeshark-cli-52.3.82/helm-chart/templates/_helpers.tpl{{/* 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 -}} {{/* Define debug docker tag suffix */}} {{- define "kubeshark.dockerTagDebugVersion" -}} {{- .Values.tap.pprof.enabled | ternary "-debug" "" }} {{- end -}} {{/* Create docker tag default version */}} {{- define "kubeshark.defaultVersion" -}} {{- $defaultVersion := (printf "v%s" .Chart.Version) -}} {{- if not .Values.tap.docker.tagLocked }} {{- $defaultVersion = regexReplaceAll "^([^.]+\\.[^.]+).*" $defaultVersion "$1" -}} {{- end }} {{- $defaultVersion }} {{- end -}} {{/* Set sentry based on internet connectivity and telemetry */}} {{- define "sentry.enabled" -}} {{- $sentryEnabledVal := .Values.tap.sentry.enabled -}} {{- if not .Values.internetConnectivity -}} {{- $sentryEnabledVal = false -}} {{- else if not .Values.tap.telemetry.enabled -}} {{- $sentryEnabledVal = false -}} {{- end -}} {{- $sentryEnabledVal -}} {{- end -}} 0707010000004D000081A400000000000000000000000166E627D700000CBD000000000000000000000000000000000000002D00000000kubeshark-cli-52.3.82/helm-chart/values.yaml# find a detailed description here: https://github.com/kubeshark/kubeshark/blob/master/helm-chart/README.md tap: docker: registry: docker.io/kubeshark tag: "" tagLocked: true imagePullPolicy: Always imagePullSecrets: [] overrideTag: worker: "" hub: "" front: "" proxy: worker: srvPort: 30001 hub: srvPort: 8898 front: port: 8899 host: 127.0.0.1 regex: .* namespaces: [] excludedNamespaces: [] bpfOverride: "" stopped: true release: repo: https://helm.kubeshark.co name: kubeshark namespace: default persistentStorage: false persistentStorageStatic: false efsFileSytemIdAndPath: "" storageLimit: 5000Mi storageClass: standard dryRun: false resources: hub: limits: cpu: 1000m memory: 1500Mi requests: cpu: 50m memory: 50Mi sniffer: limits: cpu: 1000m memory: 1500Mi requests: cpu: 50m memory: 50Mi tracer: limits: cpu: 1000m memory: 1500Mi requests: cpu: 50m memory: 50Mi serviceMesh: true tls: true disableTlsLog: false packetCapture: best ignoreTainted: false 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: "" canDownloadPCAP: true canUseScripting: true canUpdateTargetedPods: true canStopTrafficCapturing: true showAdminConsoleLink: true ingress: enabled: false className: "" host: ks.svc.cluster.local tls: [] annotations: {} ipv6: true debug: false kernelModule: enabled: false image: kubeshark/pf-ring-module:all unloadOnDestroy: false telemetry: enabled: true sentry: enabled: false environment: production defaultFilter: "!dns and !tcp" scriptingDisabled: false targetedPodsUpdateDisabled: false recordingDisabled: false stopTrafficCapturingDisabled: 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: "" enabledDissectors: - amqp - dns - http - icmp - kafka - redis - sctp - syscall - tcp - ws metrics: port: 49100 pprof: enabled: false port: 8000 view: flamegraph misc: jsonTTL: 5m pcapTTL: 10s pcapErrorTTL: 60s trafficSampleRate: 100 tcpStreamChannelTimeoutMs: 10000 tcpStreamChannelTimeoutShow: false resolutionStrategy: auto duplicateTimeframe: 200ms detectDuplicates: false logs: file: "" grep: "" kube: configPath: "" context: "" dumpLogs: false headless: false license: "" cloudLicenseEnabled: true supportChatEnabled: true internetConnectivity: true dissectorsUpdatingEnabled: true scripting: env: {} source: "" watchScripts: true timezone: "" 0707010000004E000081A400000000000000000000000166E627D700000BF2000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/install.sh#!/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" 0707010000004F000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001F00000000kubeshark-cli-52.3.82/internal07070100000050000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/internal/connect07070100000051000081A400000000000000000000000166E627D700001E02000000000000000000000000000000000000002E00000000kubeshark-cli-52.3.82/internal/connect/hub.gopackage connect import ( "bytes" "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" "github.com/rs/zerolog/log" v1 "k8s.io/api/core/v1" ) type Connector struct { url string retries int client *http.Client } const DefaultRetries = 3 const DefaultTimeout = 2 * time.Second const DefaultSleep = 1 * time.Second func NewConnector(url string, retries int, timeout time.Duration) *Connector { return &Connector{ url: url, retries: retries, client: &http.Client{ Timeout: timeout, }, } } func (connector *Connector) TestConnection(path string) error { retriesLeft := connector.retries for retriesLeft > 0 { if isReachable, err := connector.isReachable(path); err != nil || !isReachable { log.Debug().Str("url", connector.url).Err(err).Msg("Not ready yet!") } else { log.Debug().Str("url", connector.url).Msg("Connection test passed successfully.") break } retriesLeft -= 1 time.Sleep(5 * DefaultSleep) } if retriesLeft == 0 { return fmt.Errorf("Couldn't reach the URL: %s after %d retries!", connector.url, connector.retries) } return nil } func (connector *Connector) isReachable(path string) (bool, error) { targetUrl := fmt.Sprintf("%s%s", connector.url, path) if _, err := utils.Get(targetUrl, connector.client); err != nil { return false, err } else { return true, nil } } func (connector *Connector) PostWorkerPodToHub(pod *v1.Pod) { postWorkerUrl := fmt.Sprintf("%s/pods/worker", connector.url) if podMarshalled, err := json.Marshal(pod); err != nil { log.Error().Err(err).Msg("Failed to marshal the Worker pod:") } else { ok := false for !ok { var resp *http.Response 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 } log.Warn().Err(err).Msg("Failed sending the Worker pod to Hub. Retrying...") } else { log.Debug().Interface("worker-pod", pod).Msg("Reported worker pod to Hub:") return } time.Sleep(DefaultSleep) } } } type postLicenseRequest struct { License string `json:"license"` } func (connector *Connector) PostLicense(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 { ok := false for !ok { var resp *http.Response 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 } log.Warn().Err(err).Msg("Failed sending the license to Hub. Retrying...") } else { log.Debug().Str("license", license).Msg("Reported license 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(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, config.Config.License); err != nil || resp.StatusCode != http.StatusOK { if _, ok := err.(*url.Error); ok { break } log.Warn().Err(err).Msg("Failed creating script Hub:") } else { var j map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&j) if err != nil { return } val, ok := j["index"] if !ok { err = errors.New("Response does not contain `key` field!") return } index = int64(val.(float64)) log.Debug().Int("index", int(index)).Interface("script", script).Msg("Created script on Hub:") return } time.Sleep(DefaultSleep) } } return } func (connector *Connector) PutScript(script *misc.Script, index int64) (err error) { putScriptUrl := fmt.Sprintf("%s/scripts/%d", connector.url, index) var scriptMarshalled []byte if scriptMarshalled, err = json.Marshal(script); err != nil { log.Error().Err(err).Msg("Failed to marshal the script:") } else { ok := false for !ok { client := &http.Client{} var req *http.Request req, err = http.NewRequest(http.MethodPut, putScriptUrl, bytes.NewBuffer(scriptMarshalled)) if err != nil { log.Error().Err(err).Send() return } utils.AddIgnoreCaptureHeader(req) req.Header.Set("Content-Type", "application/json") req.Header.Set("License-Key", config.Config.License) var resp *http.Response resp, err = client.Do(req) if err != nil { log.Error().Err(err).Send() return } if resp.StatusCode != http.StatusOK { if _, ok := err.(*url.Error); ok { break } log.Warn().Err(err).Msg("Failed updating script on Hub:") } else { log.Debug().Int("index", int(index)).Interface("script", script).Msg("Updated script on Hub:") return } time.Sleep(DefaultSleep) } } return } func (connector *Connector) DeleteScript(index int64) (err error) { deleteScriptUrl := fmt.Sprintf("%s/scripts/%d", connector.url, index) ok := false for !ok { client := &http.Client{} var req *http.Request req, err = http.NewRequest(http.MethodDelete, deleteScriptUrl, nil) if err != nil { log.Error().Err(err).Send() return } utils.AddIgnoreCaptureHeader(req) req.Header.Set("Content-Type", "application/json") req.Header.Set("License-Key", config.Config.License) var resp *http.Response resp, err = client.Do(req) if err != nil { log.Error().Err(err).Send() return } if resp.StatusCode != http.StatusOK { if _, ok := err.(*url.Error); ok { break } log.Warn().Err(err).Msg("Failed deleting script on Hub:") } else { log.Debug().Int("index", int(index)).Msg("Deleted script on Hub:") return } time.Sleep(DefaultSleep) } return } func (connector *Connector) PostPcapsMerge(out *os.File) { postEnvUrl := fmt.Sprintf("%s/pcaps/merge", connector.url) 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 } time.Sleep(DefaultSleep) } } } 07070100000052000081ED00000000000000000000000166E627D700000265000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/kubectl.sh#!/bin/bash # Useful kubectl commands for Kubeshark development # This command outputs all Kubernetes resources using YAML format and pipes it to VS Code if [ $1 = "view-all-resources" ] ; then kubectl get $(kubectl api-resources | awk '{print $1}' | tail -n +2 | tr '\n' ',' | sed s/,\$//) -o yaml | code - fi # This command outputs all Kubernetes resources in "kubeshark" namespace using YAML format and pipes it to VS Code if [[ $1 = "view-kubeshark-resources" ]] ; then kubectl get $(kubectl api-resources | awk '{print $1}' | tail -n +2 | tr '\n' ',' | sed s/,\$//) -n kubeshark -o yaml | code - fi 07070100000053000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002100000000kubeshark-cli-52.3.82/kubernetes07070100000054000081A400000000000000000000000166E627D700000918000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/kubernetes/config.gopackage 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_EXCLUDED_NAMESPACES = "EXCLUDED_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 } 07070100000055000081A400000000000000000000000166E627D700000194000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/kubernetes/consts.gopackage kubernetes const ( SELF_RESOURCES_PREFIX = "kubeshark-" FrontPodName = SELF_RESOURCES_PREFIX + "front" FrontServiceName = FrontPodName HubPodName = SELF_RESOURCES_PREFIX + "hub" HubServiceName = HubPodName K8sAllNamespaces = "" MinKubernetesServerVersion = "1.16.0" AppLabelKey = "app.kubeshark.co/app" ) 07070100000056000081A400000000000000000000000166E627D700000F8E000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/kubernetes/cp.gopackage 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 } 07070100000057000081A400000000000000000000000166E627D7000002CD000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/kubernetes/errors.gopackage kubernetes type K8sTapManagerErrorReason string const ( TapManagerWorkerUpdateError K8sTapManagerErrorReason = "WORKER_UPDATE_ERROR" TapManagerPodWatchError K8sTapManagerErrorReason = "POD_WATCH_ERROR" TapManagerPodListError K8sTapManagerErrorReason = "POD_LIST_ERROR" ) type K8sTapManagerError struct { OriginalError error TapManagerReason K8sTapManagerErrorReason } // K8sTapManagerError implements the Error interface. func (e *K8sTapManagerError) Error() string { return e.OriginalError.Error() } type ClusterBehindProxyError struct{} // ClusterBehindProxyError implements the Error interface. func (e *ClusterBehindProxyError) Error() string { return "Cluster is behind proxy" } 07070100000058000081A400000000000000000000000166E627D7000004C6000000000000000000000000000000000000003500000000kubeshark-cli-52.3.82/kubernetes/eventWatchHelper.gopackage kubernetes import ( "context" "regexp" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" ) type EventWatchHelper struct { kubernetesProvider *Provider NameRegexFilter *regexp.Regexp Kind string } func NewEventWatchHelper(kubernetesProvider *Provider, NameRegexFilter *regexp.Regexp, kind string) *EventWatchHelper { return &EventWatchHelper{ kubernetesProvider: kubernetesProvider, NameRegexFilter: NameRegexFilter, Kind: kind, } } // Implements the EventFilterer Interface func (wh *EventWatchHelper) Filter(wEvent *WatchEvent) (bool, error) { event, err := wEvent.ToEvent() if err != nil { return false, nil } if !wh.NameRegexFilter.MatchString(event.Name) { return false, nil } if !strings.EqualFold(event.Regarding.Kind, wh.Kind) { return false, nil } return true, nil } // Implements the WatchCreator Interface func (wh *EventWatchHelper) NewWatcher(ctx context.Context, namespace string) (watch.Interface, error) { watcher, err := wh.kubernetesProvider.clientSet.EventsV1().Events(namespace).Watch(ctx, metav1.ListOptions{Watch: true}) if err != nil { return nil, err } return watcher, nil } 07070100000059000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002600000000kubeshark-cli-52.3.82/kubernetes/helm0707010000005A000081A400000000000000000000000166E627D700001233000000000000000000000000000000000000002E00000000kubeshark-cli-52.3.82/kubernetes/helm/helm.gopackage 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 } 0707010000005B000081A400000000000000000000000166E627D700000410000000000000000000000000000000000000003300000000kubeshark-cli-52.3.82/kubernetes/podWatchHelper.gopackage kubernetes import ( "context" "regexp" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" ) type PodWatchHelper struct { kubernetesProvider *Provider NameRegexFilter *regexp.Regexp } func NewPodWatchHelper(kubernetesProvider *Provider, NameRegexFilter *regexp.Regexp) *PodWatchHelper { return &PodWatchHelper{ kubernetesProvider: kubernetesProvider, NameRegexFilter: NameRegexFilter, } } // Implements the EventFilterer Interface func (wh *PodWatchHelper) Filter(wEvent *WatchEvent) (bool, error) { pod, err := wEvent.ToPod() if err != nil { return false, nil } if !wh.NameRegexFilter.MatchString(pod.Name) { return false, nil } return true, nil } // Implements the WatchCreator Interface func (wh *PodWatchHelper) NewWatcher(ctx context.Context, namespace string) (watch.Interface, error) { watcher, err := wh.kubernetesProvider.clientSet.CoreV1().Pods(namespace).Watch(ctx, metav1.ListOptions{Watch: true}) if err != nil { return nil, err } return watcher, nil } 0707010000005C000081A400000000000000000000000166E627D700002506000000000000000000000000000000000000002D00000000kubeshark-cli-52.3.82/kubernetes/provider.gopackage kubernetes import ( "bufio" "bytes" "context" "fmt" "io" "net/url" "path/filepath" "regexp" "strings" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/semver" "github.com/kubeshark/kubeshark/utils" "github.com/rs/zerolog/log" "github.com/tanqiangyes/grep-go/reader" core "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ) type Provider struct { clientSet *kubernetes.Clientset kubernetesConfig clientcmd.ClientConfig clientConfig rest.Config managedBy string createdBy string } func NewProvider(kubeConfigPath string, contextName string) (*Provider, error) { kubernetesConfig := loadKubernetesConfiguration(kubeConfigPath, contextName) restClientConfig, err := kubernetesConfig.ClientConfig() if err != nil { if clientcmd.IsEmptyConfig(err) { return nil, fmt.Errorf("couldn't find the kube config file, or file is empty (%s)\n"+ "you can set alternative kube config file path by adding the kube-config-path field to the %s config file, err: %w", kubeConfigPath, misc.Program, err) } if clientcmd.IsConfigurationInvalid(err) { return nil, fmt.Errorf("invalid kube config file (%s)\n"+ "you can set alternative kube config file path by adding the kube-config-path field to the %s config file, err: %w", kubeConfigPath, misc.Program, err) } return nil, fmt.Errorf("error while using kube config (%s)\n"+ "you can set alternative kube config file path by adding the kube-config-path field to the %s config file, err: %w", kubeConfigPath, misc.Program, err) } clientSet, err := getClientSet(restClientConfig) if err != nil { return nil, fmt.Errorf("error while using kube config (%s)\n"+ "you can set alternative kube config file path by adding the kube-config-path field to the %s config file, err: %w", kubeConfigPath, misc.Program, err) } log.Debug(). Str("host", restClientConfig.Host). Str("api-path", restClientConfig.APIPath). Str("user-agent", restClientConfig.UserAgent). Msg("K8s client config.") return &Provider{ clientSet: clientSet, kubernetesConfig: kubernetesConfig, clientConfig: *restClientConfig, managedBy: misc.Program, createdBy: misc.Program, }, nil } func (provider *Provider) DoesServiceExist(ctx context.Context, namespace string, name string) (bool, error) { serviceResource, err := provider.clientSet.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{}) return provider.doesResourceExist(serviceResource, err) } func (provider *Provider) doesResourceExist(resource interface{}, err error) (bool, error) { // Getting NotFound error is the expected behavior when a resource does not exist. if k8serrors.IsNotFound(err) { return false, nil } if err != nil { return false, err } return resource != nil, nil } func (provider *Provider) listPodsImpl(ctx context.Context, regex *regexp.Regexp, namespaces []string, listOptions metav1.ListOptions) ([]core.Pod, error) { var pods []core.Pod for _, namespace := range namespaces { namespacePods, err := provider.clientSet.CoreV1().Pods(namespace).List(ctx, listOptions) if err != nil { return nil, fmt.Errorf("failed to get pods in ns: [%s], %w", namespace, err) } pods = append(pods, namespacePods.Items...) } matchingPods := make([]core.Pod, 0) for _, pod := range pods { if regex.MatchString(pod.Name) { matchingPods = append(matchingPods, pod) } } return matchingPods, nil } func (provider *Provider) ListAllPodsMatchingRegex(ctx context.Context, regex *regexp.Regexp, namespaces []string) ([]core.Pod, error) { return provider.listPodsImpl(ctx, regex, namespaces, metav1.ListOptions{}) } func (provider *Provider) ListAllRunningPodsMatchingRegex(ctx context.Context, regex *regexp.Regexp, namespaces []string) ([]core.Pod, error) { pods, err := provider.ListAllPodsMatchingRegex(ctx, regex, namespaces) if err != nil { return nil, err } matchingPods := make([]core.Pod, 0) for _, pod := range pods { if IsPodRunning(&pod) { matchingPods = append(matchingPods, pod) } } return matchingPods, nil } func (provider *Provider) ListPodsByAppLabel(ctx context.Context, namespaces string, labels map[string]string) ([]core.Pod, error) { pods, err := provider.clientSet.CoreV1().Pods(namespaces).List(ctx, metav1.ListOptions{ LabelSelector: metav1.FormatLabelSelector( &metav1.LabelSelector{ MatchLabels: labels, }, ), }) if err != nil { return nil, err } return pods.Items, err } func (provider *Provider) GetPodLogs(ctx context.Context, namespace string, podName string, containerName string, grep string) (string, error) { podLogOpts := core.PodLogOptions{Container: containerName} req := provider.clientSet.CoreV1().Pods(namespace).GetLogs(podName, &podLogOpts) podLogs, err := req.Stream(ctx) if err != nil { return "", fmt.Errorf("error opening log stream on ns: %s, pod: %s, %w", namespace, podName, err) } defer podLogs.Close() buf := new(bytes.Buffer) if _, err = io.Copy(buf, podLogs); err != nil { return "", fmt.Errorf("error copy information from podLogs to buf, ns: %s, pod: %s, %w", namespace, podName, err) } if grep != "" { finder, err := reader.NewFinder(grep, true, true) if err != nil { panic(err) } read, err := reader.NewStdReader(bufio.NewReader(buf), []reader.Finder{finder}) if err != nil { panic(err) } read.Run() result := read.Result()[0] log.Info().Str("namespace", namespace).Str("pod", podName).Str("container", containerName).Int("lines", len(result.Lines)).Str("grep", grep).Send() return strings.Join(result.MatchString, "\n"), nil } else { log.Info().Str("namespace", namespace).Str("pod", podName).Str("container", containerName).Send() return buf.String(), nil } } func (provider *Provider) GetNamespaceEvents(ctx context.Context, namespace string) (string, error) { eventList, err := provider.clientSet.CoreV1().Events(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return "", fmt.Errorf("error getting events on ns: %s, %w", namespace, err) } return eventList.String(), nil } // ValidateNotProxy We added this after a customer tried to run kubeshark from lens, which used len's kube config, which have cluster server configuration, which points to len's local proxy. // The workaround was to use the user's local default kube config. // For now - we are blocking the option to run kubeshark through a proxy to k8s server func (provider *Provider) ValidateNotProxy() error { kubernetesUrl, err := url.Parse(provider.clientConfig.Host) if err != nil { log.Debug().Err(err).Msg("While parsing Kubernetes host!") return nil } restProxyClientConfig, _ := provider.kubernetesConfig.ClientConfig() restProxyClientConfig.Host = kubernetesUrl.Host clientProxySet, err := getClientSet(restProxyClientConfig) if err == nil { proxyServerVersion, err := clientProxySet.ServerVersion() if err != nil { return nil } if *proxyServerVersion == (version.Info{}) { return &ClusterBehindProxyError{} } } return nil } func (provider *Provider) GetKubernetesVersion() (*semver.SemVersion, error) { serverVersion, err := provider.clientSet.ServerVersion() if err != nil { log.Debug().Err(err).Msg("While getting Kubernetes server version!") return nil, err } serverVersionSemVer := semver.SemVersion(serverVersion.GitVersion) return &serverVersionSemVer, nil } func (provider *Provider) GetNamespaces() (namespaces []string) { if len(config.Config.Tap.Namespaces) > 0 { namespaces = utils.Unique(config.Config.Tap.Namespaces) } else { namespaceList, err := provider.clientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) if err != nil { log.Error().Err(err).Send() return } for _, ns := range namespaceList.Items { namespaces = append(namespaces, ns.Name) } } namespaces = utils.Diff(namespaces, config.Config.Tap.ExcludedNamespaces) return } func getClientSet(config *rest.Config) (*kubernetes.Clientset, error) { clientSet, err := kubernetes.NewForConfig(config) if err != nil { return nil, err } return clientSet, nil } func ValidateKubernetesVersion(serverVersionSemVer *semver.SemVersion) error { minKubernetesServerVersionSemVer := semver.SemVersion(MinKubernetesServerVersion) if minKubernetesServerVersionSemVer.GreaterThan(*serverVersionSemVer) { return fmt.Errorf("kubernetes server version %v is not supported, supporting only kubernetes server version of %v or higher", serverVersionSemVer, MinKubernetesServerVersion) } return nil } func loadKubernetesConfiguration(kubeConfigPath string, context string) clientcmd.ClientConfig { configPathList := filepath.SplitList(kubeConfigPath) configLoadingRules := &clientcmd.ClientConfigLoadingRules{} if len(configPathList) <= 1 { configLoadingRules.ExplicitPath = kubeConfigPath } else { configLoadingRules.Precedence = configPathList } contextName := context return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( configLoadingRules, &clientcmd.ConfigOverrides{ CurrentContext: contextName, }, ) } func IsPodRunning(pod *core.Pod) bool { return pod.Status.Phase == core.PodRunning } 0707010000005D000081A400000000000000000000000166E627D70000162A000000000000000000000000000000000000002A00000000kubeshark-cli-52.3.82/kubernetes/proxy.gopackage kubernetes import ( "bytes" "context" "fmt" "net" "net/http" "net/url" "regexp" "strings" "time" "github.com/kubeshark/kubeshark/config" "github.com/rs/zerolog/log" "k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/client-go/tools/portforward" "k8s.io/client-go/transport/spdy" "k8s.io/kubectl/pkg/proxy" ) const k8sProxyApiPrefix = "/" 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)). Msg("Starting proxy...") filter := &proxy.FilterServer{ AcceptPaths: proxy.MakeRegexpArrayOrDie(proxy.DefaultPathAcceptRE), RejectPaths: proxy.MakeRegexpArrayOrDie(proxy.DefaultPathRejectRE), AcceptHosts: proxy.MakeRegexpArrayOrDie("^.*"), RejectMethods: proxy.MakeRegexpArrayOrDie(proxy.DefaultMethodRejectRE), } proxyHandler, err := proxy.NewProxyHandler(k8sProxyApiPrefix, filter, &kubernetesProvider.clientConfig, time.Second*2, false) if err != nil { return nil, err } mux := http.NewServeMux() mux.Handle(k8sProxyApiPrefix, getRerouteHttpHandlerSelfAPI(proxyHandler, selfNamespace, selfServiceName)) mux.Handle("/static/", getRerouteHttpHandlerSelfStatic(proxyHandler, selfNamespace, selfServiceName)) l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", proxyHost, int(srcPort))) if err != nil { return nil, err } server := &http.Server{ Handler: mux, } go func() { if err := server.Serve(l); err != nil && err != http.ErrServerClosed { log.Error().Err(err).Msg("While creating proxy!") return } }() return server, nil } func getSelfHubProxiedHostAndPath(selfNamespace string, selfServiceName string) string { return fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%d/proxy", selfNamespace, selfServiceName, selfServicePort) } 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 { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Credentials", "true") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, x-session-token") w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusNoContent) return } proxiedPath := getSelfHubProxiedHostAndPath(selfNamespace, selfServiceName) //avoid redirecting several times if !strings.Contains(r.URL.Path, proxiedPath) { r.URL.Path = fmt.Sprintf("%s%s", getSelfHubProxiedHostAndPath(selfNamespace, selfServiceName), r.URL.Path) } proxyHandler.ServeHTTP(w, r) }) } func getRerouteHttpHandlerSelfStatic(proxyHandler http.Handler, selfNamespace string, selfServiceName string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.URL.Path = strings.Replace(r.URL.Path, "/static/", fmt.Sprintf("%s/static/", getSelfHubProxiedHostAndPath(selfNamespace, selfServiceName)), 1) proxyHandler.ServeHTTP(w, r) }) } func NewPortForward(kubernetesProvider *Provider, namespace string, podRegex *regexp.Regexp, srcPort uint16, dstPort uint16, ctx context.Context) (*portforward.PortForwarder, error) { pods, err := kubernetesProvider.ListPodsByAppLabel(ctx, namespace, map[string]string{AppLabelKey: "front"}) if err != nil { return nil, err } else if len(pods) == 0 { return nil, fmt.Errorf("didn't find pod to port-forward") } podName := pods[0].Name log.Info(). Str("namespace", namespace). Str("pod", podName). Int("src-port", int(srcPort)). Int("dst-port", int(dstPort)). Msg("Starting proxy using port-forward method...") dialer, err := getHttpDialer(kubernetesProvider, namespace, podName) if err != nil { return nil, err } stopChan, readyChan := make(chan struct{}, 1), make(chan struct{}, 1) out, errOut := new(bytes.Buffer), new(bytes.Buffer) forwarder, err := portforward.New(dialer, []string{fmt.Sprintf("%d:%d", srcPort, dstPort)}, stopChan, readyChan, out, errOut) if err != nil { return nil, err } go func() { if err = forwarder.ForwardPorts(); err != nil { log.Error().Err(err).Msg("While Kubernetes port-forwarding!") return } }() return forwarder, nil } func getHttpDialer(kubernetesProvider *Provider, namespace string, podName string) (httpstream.Dialer, error) { roundTripper, upgrader, err := spdy.RoundTripperFor(&kubernetesProvider.clientConfig) if err != nil { log.Error().Err(err).Msg("While creating HTTP dialer!") return nil, err } clientConfigHostUrl, err := url.Parse(kubernetesProvider.clientConfig.Host) if err != nil { return nil, fmt.Errorf("Failed parsing client config host URL %s, error %w", kubernetesProvider.clientConfig.Host, err) } path := fmt.Sprintf("%s/api/v1/namespaces/%s/pods/%s/portforward", clientConfigHostUrl.Path, namespace, podName) serverURL := url.URL{Scheme: "https", Path: path, Host: clientConfigHostUrl.Host} log.Debug(). Str("url", serverURL.String()). Msg("HTTP dialer URL:") return spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, &serverURL), nil } 0707010000005E000081A400000000000000000000000166E627D700000912000000000000000000000000000000000000002A00000000kubeshark-cli-52.3.82/kubernetes/watch.gopackage kubernetes import ( "context" "errors" "fmt" "sync" "time" "github.com/kubeshark/kubeshark/debounce" "github.com/rs/zerolog/log" "k8s.io/apimachinery/pkg/watch" ) type EventFilterer interface { Filter(*WatchEvent) (bool, error) } type WatchCreator interface { NewWatcher(ctx context.Context, namespace string) (watch.Interface, error) } func FilteredWatch(ctx context.Context, watcherCreator WatchCreator, targetNamespaces []string, filterer EventFilterer) (<-chan *WatchEvent, <-chan error) { eventChan := make(chan *WatchEvent) errorChan := make(chan error) var wg sync.WaitGroup for _, targetNamespace := range targetNamespaces { wg.Add(1) go func(targetNamespace string) { defer wg.Done() watchRestartDebouncer := debounce.NewDebouncer(1*time.Minute, func() {}) for { watcher, err := watcherCreator.NewWatcher(ctx, targetNamespace) if err != nil { errorChan <- fmt.Errorf("error in k8s watch: %v", err) break } err = startWatchLoop(ctx, watcher, filterer, eventChan) // blocking watcher.Stop() select { case <-ctx.Done(): return default: break } if err != nil { errorChan <- fmt.Errorf("error in k8s watch: %v", err) break } else { if !watchRestartDebouncer.IsOn() { if err := watchRestartDebouncer.SetOn(); err != nil { log.Error().Err(err).Send() } log.Warn().Msg("K8s watch channel closed, restarting watcher...") time.Sleep(time.Second * 5) continue } else { errorChan <- errors.New("K8s watch unstable, closes frequently") break } } } }(targetNamespace) } go func() { <-ctx.Done() wg.Wait() close(eventChan) close(errorChan) }() return eventChan, errorChan } func startWatchLoop(ctx context.Context, watcher watch.Interface, filterer EventFilterer, eventChan chan<- *WatchEvent) error { resultChan := watcher.ResultChan() for { select { case e, isChannelOpen := <-resultChan: if !isChannelOpen { return nil } wEvent := WatchEvent(e) if wEvent.Type == watch.Error { return wEvent.ToError() } if pass, err := filterer.Filter(&wEvent); err != nil { return err } else if !pass { continue } eventChan <- &wEvent case <-ctx.Done(): return nil } } } 0707010000005F000081A400000000000000000000000166E627D700000442000000000000000000000000000000000000002F00000000kubeshark-cli-52.3.82/kubernetes/watchEvent.gopackage kubernetes import ( "fmt" "reflect" corev1 "k8s.io/api/core/v1" eventsv1 "k8s.io/api/events/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/watch" ) const ( EventAdded = watch.Added EventModified = watch.Modified EventDeleted = watch.Deleted EventBookmark = watch.Bookmark EventError = watch.Error ) type InvalidObjectType struct { RequestedType reflect.Type } // Implements the error interface func (iot *InvalidObjectType) Error() string { return fmt.Sprintf("Cannot convert event to type %s", iot.RequestedType) } type WatchEvent watch.Event func (we *WatchEvent) ToPod() (*corev1.Pod, error) { pod, ok := we.Object.(*corev1.Pod) if !ok { return nil, &InvalidObjectType{RequestedType: reflect.TypeOf(pod)} } return pod, nil } func (we *WatchEvent) ToEvent() (*eventsv1.Event, error) { event, ok := we.Object.(*eventsv1.Event) if !ok { return nil, &InvalidObjectType{RequestedType: reflect.TypeOf(event)} } return event, nil } func (we *WatchEvent) ToError() error { return apierrors.FromObject(we.Object) } 07070100000060000081A400000000000000000000000166E627D70000026D000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/kubeshark.gopackage main import ( "os" "strconv" "time" "github.com/kubeshark/kubeshark/cmd" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) func main() { zerolog.SetGlobalLevel(zerolog.InfoLevel) // Short caller (file:line) zerolog.CallerMarshalFunc = func(pc uintptr, file string, line int) string { short := file for i := len(file) - 1; i > 0; i-- { if file[i] == '/' { short = file[i+1:] break } } file = short return file + ":" + strconv.Itoa(line) } log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Caller().Logger() cmd.Execute() } 07070100000061000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002000000000kubeshark-cli-52.3.82/manifests07070100000062000081A400000000000000000000000166E627D700000211000000000000000000000000000000000000002A00000000kubeshark-cli-52.3.82/manifests/README.md# Manifests ## Apply Clone the repo: ```shell git clone git@github.com:kubeshark/kubeshark.git --depth 1 cd kubeshark/manifests ``` To apply the manifests, run: ```shell kubectl apply -f . ``` To clean up: ```shell kubectl delete namespace kubeshark kubectl delete clusterrolebinding kubeshark-cluster-role-binding kubectl delete clusterrole kubeshark-cluster-role ``` ## Accessing Do the port forwarding: ```shell kubectl port-forward service/kubeshark-front 8899:80 ``` Visit [localhost:8899](http://localhost:8899) 07070100000063000081A400000000000000000000000166E627D700005A4F000000000000000000000000000000000000002E00000000kubeshark-cli-52.3.82/manifests/complete.yaml--- # Source: kubeshark/templates/16-network-policies.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm annotations: 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: labels: helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm annotations: 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: labels: helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm annotations: 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm data: POD_REGEX: '.*' NAMESPACES: '' EXCLUDED_NAMESPACES: '' BPF_OVERRIDE: '' STOPPED: 'true' SCRIPTING_SCRIPTS: '{}' INGRESS_ENABLED: 'false' INGRESS_HOST: 'ks.svc.cluster.local' PROXY_FRONT_PORT: '8899' AUTH_ENABLED: 'true' AUTH_TYPE: 'oidc' AUTH_SAML_IDP_METADATA_URL: '' AUTH_SAML_ROLE_ATTRIBUTE: 'role' AUTH_SAML_ROLES: '{"admin":{"canDownloadPCAP":true,"canStopTrafficCapturing":true,"canUpdateTargetedPods":true,"canUseScripting":true,"filter":"","showAdminConsoleLink":true}}' TELEMETRY_DISABLED: 'false' SCRIPTING_DISABLED: '' TARGETED_PODS_UPDATE_DISABLED: '' RECORDING_DISABLED: '' STOP_TRAFFIC_CAPTURING_DISABLED: 'false' GLOBAL_FILTER: "" TRAFFIC_SAMPLE_RATE: '100' JSON_TTL: '5m' PCAP_TTL: '10s' PCAP_ERROR_TTL: '60s' TIMEZONE: ' ' CLOUD_LICENSE_ENABLED: 'true' DUPLICATE_TIMEFRAME: '200ms' ENABLED_DISSECTORS: 'amqp,dns,http,icmp,kafka,redis,sctp,syscall,tcp,ws' DISSECTORS_UPDATING_ENABLED: 'true' DETECT_DUPLICATES: 'false' --- # Source: kubeshark/templates/02-cluster-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm annotations: name: kubeshark-cluster-role-default namespace: default rules: - apiGroups: - "" - extensions - apps resources: - nodes - 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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: labels: helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm annotations: prometheus.io/scrape: 'true' prometheus.io/port: '49100' name: kubeshark-worker-metrics namespace: default spec: selector: app.kubeshark.co/app: worker helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm name: kubeshark-worker-daemon-set namespace: kubeshark spec: containers: - command: - ./worker - -i - any - -port - '30001' - -metrics-port - '49100' - -packet-capture - 'best' - -unixsocket - -servicemesh - -procfs - /hostproc - -disable-ebpf - -resolution-strategy - 'auto' image: 'docker.io/kubeshark/worker:v52.3.82' 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' - name: PROFILING_ENABLED value: 'false' - name: SENTRY_ENABLED value: 'false' - name: SENTRY_ENVIRONMENT value: 'production' resources: limits: cpu: 1000m memory: 1500Mi 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 - -disable-ebpf image: 'docker.io/kubeshark/worker:v52.3.82' imagePullPolicy: Always name: tracer env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: PROFILING_ENABLED value: 'false' - name: SENTRY_ENABLED value: 'false' - name: SENTRY_ENVIRONMENT value: 'production' resources: limits: cpu: 1000m memory: 1500Mi 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 - mountPath: /etc/os-release name: os-release readOnly: true 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 - hostPath: path: /etc/os-release name: os-release - name: data emptyDir: sizeLimit: 5000Mi --- # Source: kubeshark/templates/04-hub-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubeshark.co/app: hub helm.sh/chart: kubeshark-52.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm spec: dnsPolicy: ClusterFirstWithHostNet serviceAccountName: kubeshark-service-account containers: - name: hub command: - ./hub - -port - "8080" env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: SENTRY_ENABLED value: 'false' - name: SENTRY_ENVIRONMENT value: 'production' - name: KUBESHARK_CLOUD_API_URL value: 'https://api.kubeshark.co' - name: PROFILING_ENABLED value: 'false' image: 'docker.io/kubeshark/hub:v52.3.82' 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: 1000m memory: 1500Mi 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" 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.3.82 app.kubernetes.io/name: kubeshark app.kubernetes.io/instance: kubeshark app.kubernetes.io/version: "52.3.82" app.kubernetes.io/managed-by: Helm spec: containers: - env: - name: REACT_APP_DEFAULT_FILTER value: '!dns and !tcp' - name: REACT_APP_AUTH_ENABLED value: 'true' - name: REACT_APP_AUTH_TYPE value: 'oidc' - name: REACT_APP_AUTH_SAML_IDP_METADATA_URL value: ' ' - name: REACT_APP_TIMEZONE value: ' ' - name: REACT_APP_SCRIPTING_DISABLED value: 'false' - name: REACT_APP_TARGETED_PODS_UPDATE_DISABLED value: 'false' - name: REACT_APP_BPF_OVERRIDE_DISABLED value: 'false' - name: REACT_APP_RECORDING_DISABLED value: 'false' - name: REACT_APP_STOP_TRAFFIC_CAPTURING_DISABLED value: 'false' - name: 'REACT_APP_CLOUD_LICENSE_ENABLED' value: 'true' - name: REACT_APP_SUPPORT_CHAT_ENABLED value: 'true' - name: REACT_APP_DISSECTORS_UPDATING_ENABLED value: 'true' - name: REACT_APP_SENTRY_ENABLED value: 'false' - name: REACT_APP_SENTRY_ENVIRONMENT value: 'production' image: 'docker.io/kubeshark/front:v52.3.82' 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 07070100000064000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/manifests/prometheus07070100000065000081A400000000000000000000000166E627D70000036F000000000000000000000000000000000000004600000000kubeshark-cli-52.3.82/manifests/prometheus/kube_prometheus_stack.yamlgrafana: 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_(.+) 07070100000066000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/manifests/tls07070100000067000081A400000000000000000000000166E627D7000000EE000000000000000000000000000000000000003500000000kubeshark-cli-52.3.82/manifests/tls/certificate.yamlapiVersion: cert-manager.io/v1 kind: Certificate metadata: name: kubeshark-tls namespace: default spec: issuerRef: name: letsencrypt-prod kind: ClusterIssuer secretName: cert-kubeshark dnsNames: - ks.svc.cluster.local 07070100000068000081A400000000000000000000000166E627D70000014B000000000000000000000000000000000000003800000000kubeshark-cli-52.3.82/manifests/tls/cluster-issuer.yamlapiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: info@kubeshark.co privateKeySecretRef: name: letsencrypt-prod-key solvers: - http01: ingress: class: kubeshark-ingress-class 07070100000069000081ED00000000000000000000000166E627D7000001C1000000000000000000000000000000000000002B00000000kubeshark-cli-52.3.82/manifests/tls/run.sh#!/bin/bash __dir="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" helm repo add jetstack https://charts.jetstack.io helm repo update kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.9.1 kubectl apply -f ${__dir}/cluster-issuer.yaml kubectl apply -f ${__dir}/certificate.yaml 0707010000006A000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001B00000000kubeshark-cli-52.3.82/misc0707010000006B000081A400000000000000000000000166E627D7000002B3000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/misc/consts.gopackage misc import ( "fmt" "os" "path" ) var ( Software = "Kubeshark" Program = "kubeshark" Description = "The API Traffic Analyzer for Kubernetes" Website = "https://kubeshark.co" Email = "info@kubeshark.co" 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" Platform = "" ) func GetDotFolderPath() string { home, homeDirErr := os.UserHomeDir() if homeDirErr != nil { return "" } return path.Join(home, fmt.Sprintf(".%s", Program)) } 0707010000006C000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/misc/fsUtils0707010000006D000081A400000000000000000000000166E627D70000019C000000000000000000000000000000000000002F00000000kubeshark-cli-52.3.82/misc/fsUtils/dirUtils.gopackage fsUtils import ( "fmt" "os" ) func EnsureDir(dirName string) error { err := os.Mkdir(dirName, 0700) if err == nil { return nil } if os.IsExist(err) { // check that the existing path is a directory info, err := os.Stat(dirName) if err != nil { return err } if !info.IsDir() { return fmt.Errorf("path exists but is not a directory: %s", dirName) } return nil } return err } 0707010000006E000081A400000000000000000000000166E627D700000153000000000000000000000000000000000000003000000000kubeshark-cli-52.3.82/misc/fsUtils/globUtils.gopackage fsUtils import ( "fmt" "os" "path/filepath" ) func RemoveFilesByExtension(dirPath string, ext string) error { files, err := filepath.Glob(filepath.Join(dirPath, fmt.Sprintf("/*.%s", ext))) if err != nil { return err } for _, f := range files { if err := os.Remove(f); err != nil { return err } } return nil } 0707010000006F000081A400000000000000000000000166E627D700000A2A000000000000000000000000000000000000003900000000kubeshark-cli-52.3.82/misc/fsUtils/kubesharkLogsUtils.gopackage fsUtils import ( "archive/zip" "context" "fmt" "os" "regexp" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/kubernetes" "github.com/kubeshark/kubeshark/misc" "github.com/rs/zerolog/log" ) func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath string, grep string) error { 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.Release.Namespace) } newZipFile, err := os.Create(filePath) if err != nil { return err } defer newZipFile.Close() zipWriter := zip.NewWriter(newZipFile) defer zipWriter.Close() for _, pod := range pods { for _, container := range pod.Spec.Containers { logs, err := provider.GetPodLogs(ctx, pod.Namespace, pod.Name, container.Name, grep) if err != nil { log.Error().Err(err).Msg("Failed to get logs!") continue } else { log.Debug(). Int("length", len(logs)). Str("namespace", pod.Namespace). Str("pod", pod.Name). Str("container", container.Name). Msg("Successfully read log length.") } if err := AddStrToZip(zipWriter, logs, fmt.Sprintf("%s.%s.%s.log", pod.Namespace, pod.Name, container.Name)); err != nil { log.Error().Err(err).Msg("Failed write logs!") } else { log.Debug(). Int("length", len(logs)). Str("namespace", pod.Namespace). Str("pod", pod.Name). Str("container", container.Name). Msg("Successfully added log length.") } } } 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.Release.Namespace).Msg("Successfully read events.") } 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.Release.Namespace).Msg("Successfully added events.") } if err := AddFileToZip(zipWriter, config.ConfigFilePath); err != nil { log.Error().Err(err).Msg("Failed write file!") } else { log.Debug().Str("file-path", config.ConfigFilePath).Msg("Successfully added file.") } log.Info().Str("path", filePath).Msg("You can find the ZIP file with all logs at:") return nil } 07070100000070000081A400000000000000000000000166E627D700000ABA000000000000000000000000000000000000002F00000000kubeshark-cli-52.3.82/misc/fsUtils/zipUtils.gopackage fsUtils import ( "archive/zip" "fmt" "io" "os" "path/filepath" "strings" "github.com/rs/zerolog/log" ) func AddFileToZip(zipWriter *zip.Writer, filename string) error { fileToZip, err := os.Open(filename) if err != nil { return fmt.Errorf("failed to open file %s, %w", filename, err) } defer fileToZip.Close() // Get the file information info, err := fileToZip.Stat() if err != nil { return fmt.Errorf("failed to get file information %s, %w", filename, err) } header, err := zip.FileInfoHeader(info) if err != nil { return err } // Using FileInfoHeader() above only uses the basename of the file. If we want // to preserve the folder structure we can overwrite this with the full path. header.Name = filepath.Base(filename) // Change to deflate to gain better compression // see http://golang.org/pkg/archive/zip/#pkg-constants header.Method = zip.Deflate writer, err := zipWriter.CreateHeader(header) if err != nil { return fmt.Errorf("failed to create header in zip for %s, %w", filename, err) } _, err = io.Copy(writer, fileToZip) return err } func AddStrToZip(writer *zip.Writer, logs string, fileName string) error { if zipFile, err := writer.Create(fileName); err != nil { return fmt.Errorf("couldn't create a log file inside zip for %s, %w", fileName, err) } else { if _, err = zipFile.Write([]byte(logs)); err != nil { return fmt.Errorf("couldn't write logs to zip file: %s, %w", fileName, err) } } return nil } func Unzip(reader *zip.Reader, dest string) error { dest, _ = filepath.Abs(dest) _ = os.MkdirAll(dest, os.ModePerm) // Closure to address file descriptors issue with all the deferred .Close() methods extractAndWriteFile := func(f *zip.File) error { rc, err := f.Open() if err != nil { return err } defer func() { if err := rc.Close(); err != nil { panic(err) } }() path := filepath.Join(dest, f.Name) // Check for ZipSlip (Directory traversal) if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { return fmt.Errorf("illegal file path: %s", path) } if f.FileInfo().IsDir() { _ = os.MkdirAll(path, f.Mode()) } else { _ = os.MkdirAll(filepath.Dir(path), f.Mode()) log.Info().Str("path", path).Msg("Writing HAR file...") f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } defer func() { if err := f.Close(); err != nil { panic(err) } log.Info().Str("path", path).Msg("HAR file at:") }() _, err = io.Copy(f, rc) if err != nil { return err } } return nil } for _, f := range reader.File { err := extractAndWriteFile(f) if err != nil { return err } } return nil } 07070100000071000081A400000000000000000000000166E627D7000003C1000000000000000000000000000000000000002800000000kubeshark-cli-52.3.82/misc/scripting.gopackage misc import ( "os" "path/filepath" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/parser" ) type Script struct { Path string `json:"path"` Title string `json:"title"` Code string `json:"code"` } func ReadScriptFile(path string) (script *Script, err error) { filename := filepath.Base(path) var body []byte body, err = os.ReadFile(path) if err != nil { return } content := string(body) var program *ast.Program program, err = parser.ParseFile(nil, filename, content, parser.StoreComments) if err != nil { return } var title string var titleIsSet bool code := content var idx0 file.Idx for node, comments := range program.Comments { if (titleIsSet && node.Idx0() > idx0) || len(comments) == 0 { continue } idx0 = node.Idx0() title = comments[0].Text titleIsSet = true } script = &Script{ Path: path, Title: title, Code: code, } return } 07070100000072000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000002300000000kubeshark-cli-52.3.82/misc/version07070100000073000081A400000000000000000000000166E627D7000005B8000000000000000000000000000000000000003300000000kubeshark-cli-52.3.82/misc/version/versionCheck.gopackage version import ( "context" "fmt" "os" "runtime" "strings" "time" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/utils" "github.com/rs/zerolog/log" "github.com/google/go-github/v37/github" ) func CheckNewerVersion() { if os.Getenv(fmt.Sprintf("%s_DISABLE_VERSION_CHECK", strings.ToUpper(misc.Program))) != "" { return } log.Info().Msg("Checking for a newer version...") start := time.Now() client := github.NewClient(nil) latestRelease, _, err := client.Repositories.GetLatestRelease(context.Background(), misc.Program, misc.Program) if err != nil { log.Error().Msg("Failed to get the latest release.") return } latestVersion := *latestRelease.TagName log.Debug(). Str("upstream-version", latestVersion). Str("local-version", misc.Ver). Dur("elapsed-time", time.Since(start)). Msg("Fetched the latest release:") if misc.Ver != latestVersion { var downloadCommand string if runtime.GOOS == "windows" { downloadCommand = fmt.Sprintf("curl -LO %v/%s.exe", strings.Replace(*latestRelease.HTMLURL, "tag", "download", 1), misc.Program) } else { downloadCommand = fmt.Sprintf("sh <(curl -Ls %s/install)", misc.Website) } msg := fmt.Sprintf("There is a new release! %v -> %v Please upgrade to the latest release, as new releases are not always backward compatible. Run:", misc.Ver, latestVersion) log.Warn().Str("command", downloadCommand).Msg(fmt.Sprintf(utils.Yellow, msg)) } } 07070100000074000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001D00000000kubeshark-cli-52.3.82/semver07070100000075000081A400000000000000000000000166E627D7000003C4000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/semver/semver.gopackage semver import ( "regexp" ) type SemVersion string func (v SemVersion) IsValid() bool { re := regexp.MustCompile(`\d+`) breakdown := re.FindAllString(string(v), 3) return len(breakdown) == 3 } func (v SemVersion) Breakdown() (string, string, string) { re := regexp.MustCompile(`\d+`) breakdown := re.FindAllString(string(v), 3) return breakdown[0], breakdown[1], breakdown[2] } func (v SemVersion) Major() string { major, _, _ := v.Breakdown() return major } func (v SemVersion) Minor() string { _, minor, _ := v.Breakdown() return minor } func (v SemVersion) Patch() string { _, _, patch := v.Breakdown() return patch } func (v SemVersion) GreaterThan(v2 SemVersion) bool { if v.Major() > v2.Major() { return true } else if v.Major() < v2.Major() { return false } if v.Minor() > v2.Minor() { return true } else if v.Minor() < v2.Minor() { return false } if v.Patch() > v2.Patch() { return true } return false } 07070100000076000041ED00000000000000000000000266E627D700000000000000000000000000000000000000000000001C00000000kubeshark-cli-52.3.82/utils07070100000077000081A400000000000000000000000166E627D7000001FD000000000000000000000000000000000000002700000000kubeshark-cli-52.3.82/utils/browser.gopackage utils import ( "fmt" "os/exec" "runtime" "github.com/rs/zerolog/log" ) func OpenBrowser(url string) { var err error switch runtime.GOOS { case "linux": err = exec.Command("xdg-open", url).Start() case "windows": err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() case "darwin": err = exec.Command("open", url).Start() default: err = fmt.Errorf("unsupported platform") } if err != nil { log.Error().Err(err).Msg("While trying to open a browser") } } 07070100000078000081A400000000000000000000000166E627D700000121000000000000000000000000000000000000002600000000kubeshark-cli-52.3.82/utils/colors.gopackage utils const ( Black = "\033[1;30m%s\033[0m" Red = "\033[1;31m%s\033[0m" Green = "\033[1;32m%s\033[0m" Yellow = "\033[1;33m%s\033[0m" Blue = "\033[1;34m%s\033[0m" Magenta = "\033[1;35m%s\033[0m" Cyan = "\033[1;36m%s\033[0m" White = "\033[1;37m%s\033[0m" ) 07070100000079000081A400000000000000000000000166E627D700000836000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/utils/http.gopackage utils import ( "bytes" "fmt" "io" "net/http" "strings" ) const ( X_KUBESHARK_CAPTURE_HEADER_KEY = "X-Kubeshark-Capture" X_KUBESHARK_CAPTURE_HEADER_IGNORE_VALUE = "ignore" ) // Get - When err is nil, resp always contains a non-nil resp.Body. // Caller should close resp.Body when done reading from it. func Get(url string, client *http.Client) (*http.Response, error) { req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err } AddIgnoreCaptureHeader(req) return checkError(client.Do(req)) } // Post - When err is nil, resp always contains a non-nil resp.Body. // Caller should close resp.Body when done reading from it. func Post(url, contentType string, body io.Reader, client *http.Client, licenseKey string) (*http.Response, error) { req, err := http.NewRequest(http.MethodPost, url, body) if err != nil { return nil, err } AddIgnoreCaptureHeader(req) req.Header.Set("Content-Type", "application/json") req.Header.Set("License-Key", licenseKey) return checkError(client.Do(req)) } // Do - When err is nil, resp always contains a non-nil resp.Body. // Caller should close resp.Body when done reading from it. func Do(req *http.Request, client *http.Client) (*http.Response, error) { return checkError(client.Do(req)) } func checkError(response *http.Response, errInOperation error) (*http.Response, error) { if errInOperation != nil { return response, errInOperation // Check only if status != 200 (and not status >= 300). Hub return only 200 on success. } else if response.StatusCode != http.StatusOK { body, err := io.ReadAll(response.Body) response.Body.Close() response.Body = io.NopCloser(bytes.NewBuffer(body)) // rewind if err != nil { return response, err } errorMsg := strings.ReplaceAll(string(body), "\n", ";") return response, fmt.Errorf("got response with status code: %d, body: %s", response.StatusCode, errorMsg) } return response, nil } func AddIgnoreCaptureHeader(req *http.Request) { req.Header.Set(X_KUBESHARK_CAPTURE_HEADER_KEY, X_KUBESHARK_CAPTURE_HEADER_IGNORE_VALUE) } 0707010000007A000081A400000000000000000000000166E627D700000123000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/utils/json.gopackage utils import ( "strconv" "strings" "github.com/rs/zerolog/log" ) func UnescapeUnicodeCharacters(raw string) string { str, err := strconv.Unquote(strings.Replace(strconv.Quote(raw), `\\u`, `\u`, -1)) if err != nil { log.Error().Err(err).Send() return raw } return str } 0707010000007B000081A400000000000000000000000166E627D70000012F000000000000000000000000000000000000002600000000kubeshark-cli-52.3.82/utils/pretty.gopackage utils import ( "bytes" "github.com/goccy/go-yaml" ) func PrettyYaml(data interface{}) (result string, err error) { buffer := new(bytes.Buffer) encoder := yaml.NewEncoder(buffer, yaml.Indent(2)) err = encoder.Encode(data) if err != nil { return } result = buffer.String() return } 0707010000007C000081A400000000000000000000000166E627D7000003A8000000000000000000000000000000000000002500000000kubeshark-cli-52.3.82/utils/slice.gopackage utils func Contains(slice []string, containsValue string) bool { for _, sliceValue := range slice { if sliceValue == containsValue { return true } } return false } func Unique(slice []string) []string { keys := make(map[string]bool) var list []string for _, entry := range slice { if _, value := keys[entry]; !value { keys[entry] = true list = append(list, entry) } } return list } func EqualStringSlices(slice1 []string, slice2 []string) bool { if len(slice1) != len(slice2) { return false } for _, v := range slice1 { if !Contains(slice2, v) { return false } } return true } // Diff returns the elements in `a` that aren't in `b`. func Diff(a, b []string) []string { mb := make(map[string]struct{}, len(b)) for _, x := range b { mb[x] = struct{}{} } var diff []string for _, x := range a { if _, found := mb[x]; !found { diff = append(diff, x) } } return diff } 0707010000007D000081A400000000000000000000000166E627D70000023B000000000000000000000000000000000000002400000000kubeshark-cli-52.3.82/utils/wait.gopackage utils import ( "context" "os" "os/signal" "syscall" "github.com/rs/zerolog/log" ) func WaitForTermination(ctx context.Context, cancel context.CancelFunc) { log.Debug().Msg("Waiting to finish...") sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) // block until ctx cancel is called or termination signal is received select { case <-ctx.Done(): log.Debug().Msg("Context done.") break case <-sigChan: log.Debug().Msg("Got a termination signal, canceling execution...") cancel() } } 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!847 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor