From 78c5b49b5af342278559b240e570dde51060ba01 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 09:49:50 +0300 Subject: [PATCH 01/37] create image only for original repo --- .github/workflows/build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 480a3f5d..f6e0f111 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,6 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build + if: ${{GITHUB_REPOSITORY == 'armosec/kubescape'}} runs-on: ubuntu-latest steps: From 8c55dfbcf6fa824d44024e262fe9d9e7f16a8ea3 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 09:52:26 +0300 Subject: [PATCH 02/37] fix workflow --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f6e0f111..b28deb65 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{GITHUB_REPOSITORY == 'armosec/kubescape'}} + if: ${{env.GITHUB_REPOSITORY == 'armosec/kubescape'}} runs-on: ubuntu-latest steps: From 6a96d9f8b5e25c9df5ed9ab60c581af68d983f97 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 09:59:03 +0300 Subject: [PATCH 03/37] fix build --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b28deb65..e3d4c4b0 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{env.GITHUB_REPOSITORY == 'armosec/kubescape'}} + if: ${{ env.GITHUB_REPOSITORY == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From 050976d7a357056f7472ba93e99a410d9a4b4578 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:05:58 +0300 Subject: [PATCH 04/37] fix build again --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e3d4c4b0..9958e737 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ env.GITHUB_REPOSITORY == 'armosec/kubescape' }} + if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From 5cbb7d940d4d4e9b4ddbacf88dc0e674f6bca565 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:12:42 +0300 Subject: [PATCH 05/37] Revert "fix build again" This reverts commit 050976d7a357056f7472ba93e99a410d9a4b4578. --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9958e737..e3d4c4b0 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ github.workflow == 'armosec/kubescape' }} + if: ${{ env.GITHUB_REPOSITORY == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From 09879e00ba2eca647dce867a711c8758fe1a3691 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:14:42 +0300 Subject: [PATCH 06/37] build image only for original repo --- .github/workflows/build.yaml | 2 +- .github/workflows/build_dev.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e3d4c4b0..9958e737 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ env.GITHUB_REPOSITORY == 'armosec/kubescape' }} + if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: diff --git a/.github/workflows/build_dev.yaml b/.github/workflows/build_dev.yaml index 6ccac1a5..347f2c9f 100644 --- a/.github/workflows/build_dev.yaml +++ b/.github/workflows/build_dev.yaml @@ -40,6 +40,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build + if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From 9c65aadcc70223d616e7249c6de726043c8fa7e3 Mon Sep 17 00:00:00 2001 From: Rotem Refael <48656234+rotemamsa@users.noreply.github.com> Date: Mon, 18 Oct 2021 10:26:59 +0300 Subject: [PATCH 07/37] Delete backendconnectormethods.go --- cautils/apis/backendconnectormethods.go | 128 ------------------------ 1 file changed, 128 deletions(-) delete mode 100644 cautils/apis/backendconnectormethods.go diff --git a/cautils/apis/backendconnectormethods.go b/cautils/apis/backendconnectormethods.go deleted file mode 100644 index bc05456e..00000000 --- a/cautils/apis/backendconnectormethods.go +++ /dev/null @@ -1,128 +0,0 @@ -package apis - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "strings" -) - -func MakeBackendConnector(client *http.Client, baseURL string, loginDetails *CustomerLoginDetails) (*BackendConnector, error) { - if err := ValidateBEConnectorMakerInput(client, baseURL, loginDetails); err != nil { - return nil, err - } - conn := &BackendConnector{BaseURL: baseURL, Credentials: loginDetails, HTTPClient: client} - err := conn.Login() - - return conn, err -} - -func ValidateBEConnectorMakerInput(client *http.Client, baseURL string, loginDetails *CustomerLoginDetails) error { - if client == nil { - return fmt.Errorf("You must provide an initialized httpclient") - } - if len(baseURL) == 0 { - return fmt.Errorf("you must provide a valid backend url") - } - - if loginDetails == nil || (len(loginDetails.Email) == 0 && len(loginDetails.Password) == 0) { - return fmt.Errorf("you must provide valid login details") - } - return nil - -} - -func (r *BackendConnector) Login() error { - if !r.IsExpired() { - return nil - } - - loginInfoBytes, err := json.Marshal(r.Credentials) - if err != nil { - return fmt.Errorf("unable to marshal credentials properly") - } - - beURL := fmt.Sprintf("%v/%v", r.BaseURL, "login") - - req, err := http.NewRequest("POST", beURL, bytes.NewReader(loginInfoBytes)) - if err != nil { - return err - } - - req.Header.Set("Referer", strings.Replace(beURL, "dashbe", "cpanel", 1)) - resp, err := r.HTTPClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("unable to read login response") - } - - loginS := &BELoginResponse{} - json.Unmarshal(body, &loginS) - - loginS.Cookies = resp.Cookies() - r.BELoginResponse = loginS - - return nil -} - -func (r *BackendConnector) IsExpired() bool { - return r.BELoginResponse == nil || r.BELoginResponse.ToLoginObject().IsExpired() -} - -func (r *BackendConnector) GetBaseURL() string { - return r.BaseURL -} -func (r *BackendConnector) GetLoginObj() *LoginObject { - return r.BELoginResponse.ToLoginObject() -} -func (r *BackendConnector) GetClient() *http.Client { - return r.HTTPClient -} - -func (r *BackendConnector) HTTPSend(httpverb string, - endpoint string, - payload []byte, - f HTTPReqFunc, - qryData interface{}) ([]byte, error) { - - beURL := fmt.Sprintf("%v/%v", r.GetBaseURL(), endpoint) - req, err := http.NewRequest(httpverb, beURL, bytes.NewReader(payload)) - if err != nil { - return nil, err - } - - if r.IsExpired() { - r.Login() - } - - loginobj := r.GetLoginObj() - req.Header.Set("Authorization", loginobj.Authorization) - f(req, qryData) - q := req.URL.Query() - q.Set("customerGUID", loginobj.GUID) - req.URL.RawQuery = q.Encode() - - for _, cookie := range loginobj.Cookies { - req.AddCookie(cookie) - } - resp, err := r.GetClient().Do(req) - if err != nil { - return nil, err - } - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - fmt.Printf("req:\n%v\nresp:%v\n", req, resp) - return nil, fmt.Errorf("Error #%v Due to: %v", resp.StatusCode, resp.Status) - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return body, nil -} From 7c8da4a4b9f699c6a44b02ef278deb8953c27dc0 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:49:53 +0300 Subject: [PATCH 08/37] check env var output --- .github/workflows/build_dev.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_dev.yaml b/.github/workflows/build_dev.yaml index 347f2c9f..0c1a7d2f 100644 --- a/.github/workflows/build_dev.yaml +++ b/.github/workflows/build_dev.yaml @@ -40,6 +40,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build + run: echo "$github.workflow" if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest From 2649cb75f67f9c664a0925646d25503625521545 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:51:28 +0300 Subject: [PATCH 09/37] Revert "check env var output" This reverts commit 7c8da4a4b9f699c6a44b02ef278deb8953c27dc0. --- .github/workflows/build_dev.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_dev.yaml b/.github/workflows/build_dev.yaml index 0c1a7d2f..347f2c9f 100644 --- a/.github/workflows/build_dev.yaml +++ b/.github/workflows/build_dev.yaml @@ -40,7 +40,6 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - run: echo "$github.workflow" if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest From d948353b995d4dba2556a287e836529ad07730e2 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:51:50 +0300 Subject: [PATCH 10/37] test env var output for build --- .github/workflows/build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9958e737..02e2bdc2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,6 +62,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build + run: echo "$github.workflow" if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest From c2d99163a64787a1b8004bf528b0ab4d12dfde62 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:55:13 +0300 Subject: [PATCH 11/37] test output for workflow --- .github/workflows/build.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 02e2bdc2..85d63182 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,7 +29,8 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v1 - + - name: Set up Go + run: echo "$github.workflow" - name: Set up Go uses: actions/setup-go@v2 with: @@ -62,7 +63,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - run: echo "$github.workflow" + if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest From 37791ff391ab63837bc8ce13dbb67c98fe2e0f31 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:57:04 +0300 Subject: [PATCH 12/37] testing workflow output --- .github/workflows/build.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 85d63182..fab7f5a9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,7 +29,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v1 - - name: Set up Go + - name: TestWorkflow run: echo "$github.workflow" - name: Set up Go uses: actions/setup-go@v2 @@ -63,7 +63,6 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ github.workflow == 'armosec/kubescape' }} runs-on: ubuntu-latest From b5fe456b0d48ab49e428da349076d284b3339abb Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 10:59:41 +0300 Subject: [PATCH 13/37] fix test --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index fab7f5a9..782a5d15 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -30,7 +30,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: TestWorkflow - run: echo "$github.workflow" + run: echo $github.workflow - name: Set up Go uses: actions/setup-go@v2 with: From 61440502127cd7a8dbe20a195f016e74ccf1a1c6 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 11:02:54 +0300 Subject: [PATCH 14/37] echo repo --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 782a5d15..142f9e3b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -30,7 +30,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: TestWorkflow - run: echo $github.workflow + run: echo $GITHUB_REPOSITORY - name: Set up Go uses: actions/setup-go@v2 with: From d756b9bfe485f798975da0404cfdb888f4846329 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 11:04:57 +0300 Subject: [PATCH 15/37] check repo name --- .github/workflows/build.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 142f9e3b..38c025b6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,8 +29,6 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v1 - - name: TestWorkflow - run: echo $GITHUB_REPOSITORY - name: Set up Go uses: actions/setup-go@v2 with: @@ -63,7 +61,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ github.workflow == 'armosec/kubescape' }} + if: ${{ github.repository == 'Daniel-GrunbergerCA/kubescape' }} runs-on: ubuntu-latest steps: From d44c0821344c890fea7d18abea3736476866c21a Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 11:11:32 +0300 Subject: [PATCH 16/37] fix env var name --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 38c025b6..081f3939 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -61,7 +61,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ github.repository == 'Daniel-GrunbergerCA/kubescape' }} + if: ${{ github.repository == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From 0bd164c69ea51c2a2ccfc9fe8184151b8504a826 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 11:15:55 +0300 Subject: [PATCH 17/37] fix workflow for dev --- .github/workflows/build_dev.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_dev.yaml b/.github/workflows/build_dev.yaml index 347f2c9f..9bbd45a5 100644 --- a/.github/workflows/build_dev.yaml +++ b/.github/workflows/build_dev.yaml @@ -40,7 +40,7 @@ jobs: build-docker: name: Build docker container, tag and upload to registry needs: build - if: ${{ github.workflow == 'armosec/kubescape' }} + if: ${{ github.repository == 'armosec/kubescape' }} runs-on: ubuntu-latest steps: From d948e2068202ebc12cdb44d1daab0e5917945bec Mon Sep 17 00:00:00 2001 From: Rotem Refael Date: Mon, 18 Oct 2021 14:12:57 +0300 Subject: [PATCH 18/37] Change readme text --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b82689a..63d26e8b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,11 @@ [![build](https://github.com/armosec/kubescape/actions/workflows/build.yaml/badge.svg)](https://github.com/armosec/kubescape/actions/workflows/build.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/armosec/kubescape)](https://goreportcard.com/report/github.com/armosec/kubescape) -Kubescape is the first tool for testing if Kubernetes is deployed securely as defined in [Kubernetes Hardening Guidance by NSA and CISA](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) +Kubescape is the first open-source tool for testing if Kubernetes is deployed securely according to multiple frameworks: +regulatory, customized company policies and DevSecOps best practices, such as the [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo) and the [MITRE ATT&CKĀ®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) . +Kubescape scans K8s clusters, YAML files, and HELM charts, and detect misconfigurations and software vulnerabilities at early stages of the CI/CD pipeline and provides a risk score instantly and risk trends over time. +Kubescape integrates natively with other DevOps tools, including Jenkins, CircleCI and Github workflows. + Use Kubescape to test clusters or scan single YAML files and integrate it to your processes. From 6ed8287b01be05dff03431d5bb48618df1ef8337 Mon Sep 17 00:00:00 2001 From: Rotem Refael <48656234+rotemamsa@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:15:45 +0300 Subject: [PATCH 19/37] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 63d26e8b..0d611779 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ Kubescape scans K8s clusters, YAML files, and HELM charts, and detect misconfigu Kubescape integrates natively with other DevOps tools, including Jenkins, CircleCI and Github workflows. -Use Kubescape to test clusters or scan single YAML files and integrate it to your processes. From 6f9d6b4af3ba40de2585125ff41fe319d14e27cc Mon Sep 17 00:00:00 2001 From: Rotem Refael <48656234+rotemamsa@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:16:29 +0300 Subject: [PATCH 20/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d611779..6b0da00c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ regulatory, customized company policies and DevSecOps best practices, such as th Kubescape scans K8s clusters, YAML files, and HELM charts, and detect misconfigurations and software vulnerabilities at early stages of the CI/CD pipeline and provides a risk score instantly and risk trends over time. Kubescape integrates natively with other DevOps tools, including Jenkins, CircleCI and Github workflows. - +
From 63367f4f31fae302f41d3fc328feb97592f66eeb Mon Sep 17 00:00:00 2001 From: moshep Date: Mon, 18 Oct 2021 14:29:44 +0300 Subject: [PATCH 21/37] support yamls from repo --- policyhandler/repositoryscanner.go | 155 +++++++++++++++++++++++++++++ policyhandler/urlloader.go | 11 +- 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 policyhandler/repositoryscanner.go diff --git a/policyhandler/repositoryscanner.go b/policyhandler/repositoryscanner.go new file mode 100644 index 00000000..a568e8c5 --- /dev/null +++ b/policyhandler/repositoryscanner.go @@ -0,0 +1,155 @@ +package policyhandler + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/armosec/kubescape/cautils/getter" +) + +type IRepository interface { + setBranch(string) error + setTree() error + getYamlFromTree() []string +} + +type innerTree struct { + Path string `json:"path"` +} +type tree struct { + InnerTrees []innerTree `json:"tree"` +} + +type GitHubRepository struct { + host string + name string // / + branch string + tree tree +} +type githubDefaultBranchAPI struct { + DefaultBranch string `json:"default_branch"` +} + +func NewGitHubRepository(rep string) *GitHubRepository { + return &GitHubRepository{ + host: "github", + name: rep, + } +} + +func ScanRepository(command string, branchOptional string) ([]string, error) { + repo, err := getRepository(command) + if err != nil { + return nil, err + } + + err = repo.setBranch(branchOptional) + if err != nil { + return nil, err + } + + err = repo.setTree() + if err != nil { + return nil, err + } + + // get all paths that are of the yaml type, and build them into a valid url + return repo.getYamlFromTree(), nil +} + +func getHostAndRepoName(url string) (string, string, error) { + splitUrl := strings.Split(url, "/") + + if len(splitUrl) != 5 { + return "", "", fmt.Errorf("failed to pars url: %s", url) + } + + hostUrl := splitUrl[2] // github.com, gitlab.com, etc. + repository := splitUrl[3] + "/" + strings.Split(splitUrl[4], ".")[0] // user/reposetory + + return hostUrl, repository, nil +} + +func getRepository(url string) (IRepository, error) { + hostUrl, repoName, err := getHostAndRepoName(url) + if err != nil { + return nil, err + } + + var repo IRepository + switch repoHost := strings.Split(hostUrl, ".")[0]; repoHost { + case "github": + repo = NewGitHubRepository(repoName) + default: + return nil, fmt.Errorf("unknown repository host: %s", repoHost) + } + + // Returns the host-url, and the part of the user and repository from the url + return repo, nil +} + +func (g *GitHubRepository) setBranch(branchOptional string) error { + // Checks whether the repository type is a master or another type. + // By default it is "master", unless the branchOptional came with a value + if branchOptional == "" { + + body, err := getter.HttpGetter(&http.Client{}, g.defaultBranchAPI()) + if err != nil { + return err + } + + var data githubDefaultBranchAPI + err = json.Unmarshal([]byte(body), &data) + if err != nil { + return err + } + g.branch = data.DefaultBranch + } else { + g.branch = branchOptional + } + return nil +} + +func (g *GitHubRepository) defaultBranchAPI() string { + return fmt.Sprintf("https://api.github.com/repos/%s", g.name) +} + +func (g *GitHubRepository) setTree() error { + body, err := getter.HttpGetter(&http.Client{}, g.treeAPI()) + if err != nil { + return err + } + + // press all tree to json + var tree tree + err = json.Unmarshal([]byte(body), &tree) + if err != nil { + return fmt.Errorf("failed to unmarshal response body from '%s', reason: %s", g.treeAPI(), err.Error()) + // fmt.Printf("failed to unmarshal response body from '%s', reason: %s", urlCommand, err.Error()) + // return nil + } + g.tree = tree + + return nil +} + +func (g *GitHubRepository) treeAPI() string { + return fmt.Sprintf("https://api.github.com/repos/%s/git/trees/%s?recursive=1", g.name, g.branch) +} + +// return a list of yaml for a given repository tree +func (g *GitHubRepository) getYamlFromTree() []string { + var urls []string + for _, path := range g.tree.InnerTrees { + if strings.HasSuffix(path.Path, ".yaml") { + urls = append(urls, fmt.Sprintf("%s/%s", g.rowYamlUrl(), path.Path)) + } + } + return urls +} + +func (g *GitHubRepository) rowYamlUrl() string { + return fmt.Sprintf("https://raw.githubusercontent.com/%s/%s", g.name, g.branch) +} diff --git a/policyhandler/urlloader.go b/policyhandler/urlloader.go index 151aeaa5..faa8f634 100644 --- a/policyhandler/urlloader.go +++ b/policyhandler/urlloader.go @@ -28,9 +28,18 @@ func listUrls(patterns []string) []string { urls := []string{} for i := range patterns { if strings.HasPrefix(patterns[i], "http") { - urls = append(urls, patterns[i]) + if !isYaml(patterns[i]) || !isJson(patterns[i]) { // if url of repo + if yamls, err := ScanRepository(patterns[i], ""); err == nil { // TODO - support branch + urls = append(urls, yamls...) + } else { + fmt.Print(err) // TODO - handle errors + } + } else { // url of single file + urls = append(urls, patterns[i]) + } } } + return urls } From 7d12552932ac06a33c87e6f175b731612175289c Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Mon, 18 Oct 2021 17:39:35 +0300 Subject: [PATCH 22/37] add option to run single control --- cautils/getter/loadpolicy.go | 15 ++ cautils/scaninfo.go | 16 ++ {cmd => clihandler/cmd}/cluster.go | 0 {cmd => clihandler/cmd}/cluster_get.go | 3 +- {cmd => clihandler/cmd}/cluster_set.go | 0 {cmd => clihandler/cmd}/config.go | 0 clihandler/cmd/control.go | 51 ++++++ {cmd => clihandler/cmd}/download.go | 3 +- clihandler/cmd/framework.go | 90 +++++++++++ {cmd => clihandler/cmd}/local.go | 0 {cmd => clihandler/cmd}/local_get.go | 0 {cmd => clihandler/cmd}/local_set.go | 0 {cmd => clihandler/cmd}/root.go | 0 clihandler/cmd/scan.go | 30 ++++ {cmd => clihandler/cmd}/version.go | 0 clihandler/initcli.go | 101 ++++++++++++ cmd/framework.go | 197 ------------------------ cmd/scan.go | 18 --- main.go | 2 +- nsa.json | 1 + policyhandler/handlenotification.go | 10 +- policyhandler/handlepullpolicies.go | 59 ++++++- resultshandling/printer/printresults.go | 3 +- resultshandling/results.go | 7 +- 24 files changed, 382 insertions(+), 224 deletions(-) rename {cmd => clihandler/cmd}/cluster.go (100%) rename {cmd => clihandler/cmd}/cluster_get.go (93%) rename {cmd => clihandler/cmd}/cluster_set.go (100%) rename {cmd => clihandler/cmd}/config.go (100%) create mode 100644 clihandler/cmd/control.go rename {cmd => clihandler/cmd}/download.go (92%) create mode 100644 clihandler/cmd/framework.go rename {cmd => clihandler/cmd}/local.go (100%) rename {cmd => clihandler/cmd}/local_get.go (100%) rename {cmd => clihandler/cmd}/local_set.go (100%) rename {cmd => clihandler/cmd}/root.go (100%) create mode 100644 clihandler/cmd/scan.go rename {cmd => clihandler/cmd}/version.go (100%) create mode 100644 clihandler/initcli.go delete mode 100644 cmd/framework.go delete mode 100644 cmd/scan.go create mode 100644 nsa.json diff --git a/cautils/getter/loadpolicy.go b/cautils/getter/loadpolicy.go index 47a9bfc2..3c7054f0 100644 --- a/cautils/getter/loadpolicy.go +++ b/cautils/getter/loadpolicy.go @@ -26,6 +26,21 @@ func NewLoadPolicy(filePath string) *LoadPolicy { } } +func (lp *LoadPolicy) GetControl(controlName string, controlPath string) (*reporthandling.Control, error) { + + control := &reporthandling.Control{} + f, err := os.ReadFile(controlPath) + if err != nil { + return nil, err + } + + err = json.Unmarshal(f, control) + if controlName != "" && !strings.EqualFold(controlName, control.Name) { + return nil, fmt.Errorf("control from file not matching") + } + return control, err +} + func (lp *LoadPolicy) GetFramework(frameworkName string) (*reporthandling.Framework, error) { framework := &reporthandling.Framework{} diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index f1838bff..a0e58b62 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -3,6 +3,7 @@ package cautils import ( "path/filepath" + "github.com/armosec/k8s-interface/k8sinterface" "github.com/armosec/kubescape/cautils/getter" "github.com/armosec/opa-utils/reporthandling" ) @@ -22,6 +23,7 @@ type ScanInfo struct { Submit bool // Submit results to Armo BE Local bool // Do not submit results Account string // account ID + FrameworkScan bool // false if scanning control } type Getters struct { @@ -84,6 +86,20 @@ func (scanInfo *ScanInfo) ScanRunningCluster() bool { return len(scanInfo.InputPatterns) == 0 } +func (scanInfo *ScanInfo) SetClusterConfig() (IClusterConfig, *k8sinterface.KubernetesApi) { + var clusterConfig IClusterConfig + var k8s *k8sinterface.KubernetesApi + if !scanInfo.ScanRunningCluster() { + k8sinterface.ConnectedToCluster = false + clusterConfig = NewEmptyConfig() + } else { + k8s = k8sinterface.NewKubernetesApi() + // setup cluster config + clusterConfig = ClusterConfigSetup(scanInfo, k8s, getter.GetArmoAPIConnector()) + } + return clusterConfig, k8s +} + // func (scanInfo *ScanInfo) ConnectedToCluster(k8s k8sinterface.) bool { // _, err := k8s.KubernetesClient.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{}) // return err == nil diff --git a/cmd/cluster.go b/clihandler/cmd/cluster.go similarity index 100% rename from cmd/cluster.go rename to clihandler/cmd/cluster.go diff --git a/cmd/cluster_get.go b/clihandler/cmd/cluster_get.go similarity index 93% rename from cmd/cluster_get.go rename to clihandler/cmd/cluster_get.go index 6203473e..0c0740df 100644 --- a/cmd/cluster_get.go +++ b/clihandler/cmd/cluster_get.go @@ -7,6 +7,7 @@ import ( "github.com/armosec/k8s-interface/k8sinterface" "github.com/armosec/kubescape/cautils" "github.com/armosec/kubescape/cautils/getter" + "github.com/armosec/kubescape/clihandler" "github.com/spf13/cobra" ) @@ -14,7 +15,7 @@ var getCmd = &cobra.Command{ Use: "get ", Short: "Get configuration in cluster", Long: ``, - ValidArgs: supportedFrameworks, + ValidArgs: clihandler.SupportedFrameworks, Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 || len(args) > 1 { return fmt.Errorf("requires one argument") diff --git a/cmd/cluster_set.go b/clihandler/cmd/cluster_set.go similarity index 100% rename from cmd/cluster_set.go rename to clihandler/cmd/cluster_set.go diff --git a/cmd/config.go b/clihandler/cmd/config.go similarity index 100% rename from cmd/config.go rename to clihandler/cmd/config.go diff --git a/clihandler/cmd/control.go b/clihandler/cmd/control.go new file mode 100644 index 00000000..dd018a46 --- /dev/null +++ b/clihandler/cmd/control.go @@ -0,0 +1,51 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/armosec/kubescape/cautils" + "github.com/armosec/kubescape/clihandler" + "github.com/armosec/opa-utils/reporthandling" + "github.com/spf13/cobra" +) + +// controlCmd represents the control command +var controlCmd = &cobra.Command{ + Use: fmt.Sprint("control "), + Short: fmt.Sprintf("The control you wish to use for scan. It must be present in at least one of the folloiwng frameworks: %s", clihandler.ValidFrameworks), + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("requires one argument") + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + flagValidationControl() + scanInfo.FrameworkScan = false + scanInfo.PolicyIdentifier = reporthandling.PolicyIdentifier{} + scanInfo.PolicyIdentifier.Kind = reporthandling.KindControl + scanInfo.PolicyIdentifier.Name = args[0] + scanInfo.Init() + cautils.SetSilentMode(scanInfo.Silent) + err := clihandler.CliSetup(scanInfo) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + return nil + }, +} + +func init() { + scanInfo = cautils.ScanInfo{} + scanCmd.AddCommand(controlCmd) +} + +func flagValidationControl() { + if 100 < scanInfo.FailThreshold { + fmt.Println("bad argument: out of range threshold") + os.Exit(1) + } +} diff --git a/cmd/download.go b/clihandler/cmd/download.go similarity index 92% rename from cmd/download.go rename to clihandler/cmd/download.go index 550c42f8..24c01669 100644 --- a/cmd/download.go +++ b/clihandler/cmd/download.go @@ -5,13 +5,14 @@ import ( "github.com/armosec/kubescape/cautils" "github.com/armosec/kubescape/cautils/getter" + "github.com/armosec/kubescape/clihandler" "github.com/spf13/cobra" ) var downloadInfo cautils.DownloadInfo var downloadCmd = &cobra.Command{ - Use: fmt.Sprintf("download framework [flags]\nSupported frameworks: %s", validFrameworks), + Use: fmt.Sprintf("download framework [flags]\nSupported frameworks: %s", clihandler.ValidFrameworks), Short: "Download framework controls", Long: ``, Args: func(cmd *cobra.Command, args []string) error { diff --git a/clihandler/cmd/framework.go b/clihandler/cmd/framework.go new file mode 100644 index 00000000..bd0bbfe6 --- /dev/null +++ b/clihandler/cmd/framework.go @@ -0,0 +1,90 @@ +package cmd + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/armosec/kubescape/cautils" + "github.com/armosec/kubescape/clihandler" + "github.com/armosec/opa-utils/reporthandling" + + "github.com/spf13/cobra" +) + +var frameworkCmd = &cobra.Command{ + + Use: fmt.Sprintf("framework [``/`-`] [flags]\nSupported frameworks: %s", clihandler.ValidFrameworks), + Short: fmt.Sprintf("The framework you wish to use. Supported frameworks: %s", strings.Join(clihandler.SupportedFrameworks, ", ")), + Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin", + ValidArgs: clihandler.SupportedFrameworks, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 && !(cmd.Flags().Lookup("use-from").Changed) { + return fmt.Errorf("requires at least one argument") + } else if len(args) > 0 { + if !isValidFramework(strings.ToLower(args[0])) { + return fmt.Errorf(fmt.Sprintf("supported frameworks: %s", strings.Join(clihandler.SupportedFrameworks, ", "))) + } + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + scanInfo.PolicyIdentifier = reporthandling.PolicyIdentifier{} + scanInfo.PolicyIdentifier.Kind = reporthandling.KindFramework + flagValidationFramework() + if !(cmd.Flags().Lookup("use-from").Changed) { + scanInfo.PolicyIdentifier.Name = strings.ToLower(args[0]) + } + if len(args) > 0 { + if len(args[1:]) == 0 || args[1] != "-" { + scanInfo.InputPatterns = args[1:] + } else { // store stout to file + tempFile, err := os.CreateTemp(".", "tmp-kubescape*.yaml") + if err != nil { + return err + } + defer os.Remove(tempFile.Name()) + + if _, err := io.Copy(tempFile, os.Stdin); err != nil { + return err + } + scanInfo.InputPatterns = []string{tempFile.Name()} + } + } + scanInfo.Init() + cautils.SetSilentMode(scanInfo.Silent) + err := clihandler.CliSetup(scanInfo) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } + return nil + }, +} + +func isValidFramework(framework string) bool { + return cautils.StringInSlice(clihandler.SupportedFrameworks, framework) != cautils.ValueNotFound +} + +func init() { + scanCmd.AddCommand(frameworkCmd) + scanInfo = cautils.ScanInfo{} + scanInfo.FrameworkScan = true + frameworkCmd.Flags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to Armo management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted") + frameworkCmd.Flags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to Armo backend. Use this flag if you ran with the '--submit' flag in the past and you do not want to submit your current scan results") + frameworkCmd.Flags().StringVarP(&scanInfo.Account, "account", "", "", "Armo portal account ID. Default will load account ID from configMap or config file") + +} + +func flagValidationFramework() { + + if scanInfo.Submit && scanInfo.Local { + fmt.Println("You can use `keep-local` or `submit`, but not both") + os.Exit(1) + } + if 100 < scanInfo.FailThreshold { + fmt.Println("bad argument: out of range threshold") + os.Exit(1) + } +} diff --git a/cmd/local.go b/clihandler/cmd/local.go similarity index 100% rename from cmd/local.go rename to clihandler/cmd/local.go diff --git a/cmd/local_get.go b/clihandler/cmd/local_get.go similarity index 100% rename from cmd/local_get.go rename to clihandler/cmd/local_get.go diff --git a/cmd/local_set.go b/clihandler/cmd/local_set.go similarity index 100% rename from cmd/local_set.go rename to clihandler/cmd/local_set.go diff --git a/cmd/root.go b/clihandler/cmd/root.go similarity index 100% rename from cmd/root.go rename to clihandler/cmd/root.go diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go new file mode 100644 index 00000000..dd4345e3 --- /dev/null +++ b/clihandler/cmd/scan.go @@ -0,0 +1,30 @@ +package cmd + +import ( + "github.com/armosec/kubescape/cautils" + "github.com/spf13/cobra" +) + +var scanInfo cautils.ScanInfo + +// scanCmd represents the scan command +var scanCmd = &cobra.Command{ + Use: "scan", + Short: "Scan the current running cluster or yaml files", + Long: `The action you want to perform`, + Run: func(cmd *cobra.Command, args []string) { + }, +} + +func init() { + rootCmd.AddCommand(scanCmd) + + scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system, kube-public") + scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer"/"json"/"junit"`) + scanCmd.PersistentFlags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout") + scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages") + scanCmd.PersistentFlags().Uint16VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 0, "Failure threshold is the percent bellow which the command fails and returns exit code 1") + scanCmd.PersistentFlags().StringVar(&scanInfo.UseFrom, "use-from", "", "Load local framework object from specified path. If not used will download latest") + scanCmd.PersistentFlags().BoolVar(&scanInfo.UseDefault, "use-default", false, "Load local framework object from default path. If not used will download latest") + scanCmd.PersistentFlags().StringVar(&scanInfo.UseExceptions, "exceptions", "", "Path to an exceptions obj. If not set will download exceptions from Armo management portal") +} diff --git a/cmd/version.go b/clihandler/cmd/version.go similarity index 100% rename from cmd/version.go rename to clihandler/cmd/version.go diff --git a/clihandler/initcli.go b/clihandler/initcli.go new file mode 100644 index 00000000..eddee079 --- /dev/null +++ b/clihandler/initcli.go @@ -0,0 +1,101 @@ +package clihandler + +import ( + "fmt" + "os" + "strings" + + "github.com/armosec/armoapi-go/armotypes" + "github.com/armosec/k8s-interface/k8sinterface" + "github.com/armosec/kubescape/cautils" + "github.com/armosec/kubescape/opaprocessor" + "github.com/armosec/kubescape/policyhandler" + "github.com/armosec/kubescape/resultshandling" + "github.com/armosec/kubescape/resultshandling/printer" + "github.com/armosec/kubescape/resultshandling/reporter" + "github.com/armosec/opa-utils/reporthandling" +) + +type CLIHandler struct { + policyHandler *policyhandler.PolicyHandler + scanInfo *cautils.ScanInfo +} + +var SupportedFrameworks = []string{"nsa", "mitre"} +var ValidFrameworks = strings.Join(SupportedFrameworks, ", ") + +func CliSetup(scanInfo cautils.ScanInfo) error { + + clusterConfig, k8s := scanInfo.SetClusterConfig() + + processNotification := make(chan *cautils.OPASessionObj) + reportResults := make(chan *cautils.OPASessionObj) + + // policy handler setup + policyHandler := policyhandler.NewPolicyHandler(&processNotification, k8s) + + if err := clusterConfig.SetCustomerGUID(scanInfo.Account); err != nil { + fmt.Println(err) + } + + cautils.CustomerGUID = clusterConfig.GetCustomerGUID() + cautils.ClusterName = k8sinterface.GetClusterName() + + // cli handler setup + go func() { + cli := NewCLIHandler(policyHandler, scanInfo) + if err := cli.Scan(); err != nil { + fmt.Println(err) + os.Exit(1) + } + }() + + // processor setup - rego run + go func() { + opaprocessorObj := opaprocessor.NewOPAProcessorHandler(&processNotification, &reportResults) + opaprocessorObj.ProcessRulesListenner() + }() + + resultsHandling := resultshandling.NewResultsHandler(&reportResults, reporter.NewReportEventReceiver(), printer.NewPrinter(scanInfo.Format, scanInfo.Output)) + score := resultsHandling.HandleResults(scanInfo) + + // print report url + if scanInfo.FrameworkScan { + clusterConfig.GenerateURL() + } + + adjustedFailThreshold := float32(scanInfo.FailThreshold) / 100 + if score < adjustedFailThreshold { + return fmt.Errorf("Scan score is bellow threshold") + } + + return nil +} + +func NewCLIHandler(policyHandler *policyhandler.PolicyHandler, scanInfo cautils.ScanInfo) *CLIHandler { + return &CLIHandler{ + scanInfo: &scanInfo, + policyHandler: policyHandler, + } +} + +func (clihandler *CLIHandler) Scan() error { + cautils.ScanStartDisplay() + policyNotification := &reporthandling.PolicyNotification{ + NotificationType: reporthandling.TypeExecPostureScan, + Rules: []reporthandling.PolicyIdentifier{ + clihandler.scanInfo.PolicyIdentifier, + }, + Designators: armotypes.PortalDesignator{}, + } + switch policyNotification.NotificationType { + case reporthandling.TypeExecPostureScan: + if err := clihandler.policyHandler.HandleNotificationRequest(policyNotification, clihandler.scanInfo); err != nil { + return err + } + + default: + return fmt.Errorf("notification type '%s' Unknown", policyNotification.NotificationType) + } + return nil +} diff --git a/cmd/framework.go b/cmd/framework.go deleted file mode 100644 index c24a4fdf..00000000 --- a/cmd/framework.go +++ /dev/null @@ -1,197 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "os" - "strings" - - "github.com/armosec/armoapi-go/armotypes" - "github.com/armosec/k8s-interface/k8sinterface" - "github.com/armosec/kubescape/cautils" - "github.com/armosec/kubescape/cautils/getter" - "github.com/armosec/kubescape/opaprocessor" - "github.com/armosec/kubescape/policyhandler" - "github.com/armosec/kubescape/resultshandling" - "github.com/armosec/kubescape/resultshandling/printer" - "github.com/armosec/kubescape/resultshandling/reporter" - "github.com/armosec/opa-utils/reporthandling" - - "github.com/spf13/cobra" -) - -var scanInfo cautils.ScanInfo -var supportedFrameworks = []string{"nsa", "mitre"} -var validFrameworks = strings.Join(supportedFrameworks, ", ") - -type CLIHandler struct { - policyHandler *policyhandler.PolicyHandler - scanInfo *cautils.ScanInfo -} - -var frameworkCmd = &cobra.Command{ - - Use: fmt.Sprintf("framework [``/`-`] [flags]\nSupported frameworks: %s", validFrameworks), - Short: fmt.Sprintf("The framework you wish to use. Supported frameworks: %s", strings.Join(supportedFrameworks, ", ")), - Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin", - ValidArgs: supportedFrameworks, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 && !(cmd.Flags().Lookup("use-from").Changed) { - return fmt.Errorf("requires at least one argument") - } else if len(args) > 0 { - if !isValidFramework(strings.ToLower(args[0])) { - return fmt.Errorf(fmt.Sprintf("supported frameworks: %s", strings.Join(supportedFrameworks, ", "))) - } - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - scanInfo.PolicyIdentifier = reporthandling.PolicyIdentifier{} - scanInfo.PolicyIdentifier.Kind = reporthandling.KindFramework - - if !(cmd.Flags().Lookup("use-from").Changed) { - scanInfo.PolicyIdentifier.Name = strings.ToLower(args[0]) - } - if len(args) > 0 { - if len(args[1:]) == 0 || args[1] != "-" { - scanInfo.InputPatterns = args[1:] - } else { // store stout to file - tempFile, err := os.CreateTemp(".", "tmp-kubescape*.yaml") - if err != nil { - return err - } - defer os.Remove(tempFile.Name()) - - if _, err := io.Copy(tempFile, os.Stdin); err != nil { - return err - } - scanInfo.InputPatterns = []string{tempFile.Name()} - } - } - scanInfo.Init() - cautils.SetSilentMode(scanInfo.Silent) - err := CliSetup() - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - return nil - }, -} - -func isValidFramework(framework string) bool { - return cautils.StringInSlice(supportedFrameworks, framework) != cautils.ValueNotFound -} - -func init() { - scanCmd.AddCommand(frameworkCmd) - scanInfo = cautils.ScanInfo{} - frameworkCmd.Flags().StringVar(&scanInfo.UseFrom, "use-from", "", "Load local framework object from specified path. If not used will download latest") - frameworkCmd.Flags().BoolVar(&scanInfo.UseDefault, "use-default", false, "Load local framework object from default path. If not used will download latest") - frameworkCmd.Flags().StringVar(&scanInfo.UseExceptions, "exceptions", "", "Path to an exceptions obj. If not set will download exceptions from Armo management portal") - frameworkCmd.Flags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system, kube-public") - frameworkCmd.Flags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer"/"json"/"junit"`) - frameworkCmd.Flags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout") - frameworkCmd.Flags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages") - frameworkCmd.Flags().Uint16VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 0, "Failure threshold is the percent bellow which the command fails and returns exit code 1") - frameworkCmd.Flags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to Armo management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted") - frameworkCmd.Flags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to Armo backend. Use this flag if you ran with the '--submit' flag in the past and you do not want to submit your current scan results") - frameworkCmd.Flags().StringVarP(&scanInfo.Account, "account", "", "", "Armo portal account ID. Default will load account ID from configMap or config file") - -} - -func CliSetup() error { - flagValidation() - - var k8s *k8sinterface.KubernetesApi - var clusterConfig cautils.IClusterConfig - if !scanInfo.ScanRunningCluster() { - k8sinterface.ConnectedToCluster = false - clusterConfig = cautils.NewEmptyConfig() - } else { - k8s = k8sinterface.NewKubernetesApi() - // setup cluster config - clusterConfig = cautils.ClusterConfigSetup(&scanInfo, k8s, getter.GetArmoAPIConnector()) - } - - processNotification := make(chan *cautils.OPASessionObj) - reportResults := make(chan *cautils.OPASessionObj) - - // policy handler setup - policyHandler := policyhandler.NewPolicyHandler(&processNotification, k8s) - - if err := clusterConfig.SetCustomerGUID(scanInfo.Account); err != nil { - fmt.Println(err) - } - - cautils.CustomerGUID = clusterConfig.GetCustomerGUID() - cautils.ClusterName = k8sinterface.GetClusterName() - - // cli handler setup - go func() { - cli := NewCLIHandler(policyHandler) - if err := cli.Scan(); err != nil { - fmt.Println(err) - os.Exit(1) - } - }() - - // processor setup - rego run - go func() { - opaprocessorObj := opaprocessor.NewOPAProcessorHandler(&processNotification, &reportResults) - opaprocessorObj.ProcessRulesListenner() - }() - - resultsHandling := resultshandling.NewResultsHandler(&reportResults, reporter.NewReportEventReceiver(), printer.NewPrinter(scanInfo.Format, scanInfo.Output)) - score := resultsHandling.HandleResults() - - // print report url - clusterConfig.GenerateURL() - - adjustedFailThreshold := float32(scanInfo.FailThreshold) / 100 - if score < adjustedFailThreshold { - return fmt.Errorf("Scan score is bellow threshold") - } - - return nil -} - -func NewCLIHandler(policyHandler *policyhandler.PolicyHandler) *CLIHandler { - return &CLIHandler{ - scanInfo: &scanInfo, - policyHandler: policyHandler, - } -} - -func (clihandler *CLIHandler) Scan() error { - cautils.ScanStartDisplay() - policyNotification := &reporthandling.PolicyNotification{ - NotificationType: reporthandling.TypeExecPostureScan, - Rules: []reporthandling.PolicyIdentifier{ - clihandler.scanInfo.PolicyIdentifier, - }, - Designators: armotypes.PortalDesignator{}, - } - switch policyNotification.NotificationType { - case reporthandling.TypeExecPostureScan: - // - if err := clihandler.policyHandler.HandleNotificationRequest(policyNotification, clihandler.scanInfo); err != nil { - return err - } - default: - return fmt.Errorf("notification type '%s' Unknown", policyNotification.NotificationType) - } - return nil -} - -func flagValidation() { - - if scanInfo.Submit && scanInfo.Local { - fmt.Println("You can use `keep-local` or `submit`, but not both") - os.Exit(1) - } - if 100 < scanInfo.FailThreshold { - fmt.Println("bad argument: out of range threshold") - os.Exit(1) - } -} diff --git a/cmd/scan.go b/cmd/scan.go deleted file mode 100644 index e421f852..00000000 --- a/cmd/scan.go +++ /dev/null @@ -1,18 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -// scanCmd represents the scan command -var scanCmd = &cobra.Command{ - Use: "scan", - Short: "Scan the current running cluster or yaml files", - Long: `The action you want to perform`, - Run: func(cmd *cobra.Command, args []string) { - }, -} - -func init() { - rootCmd.AddCommand(scanCmd) -} diff --git a/main.go b/main.go index 114f855c..956b6622 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/armosec/kubescape/cmd" + "github.com/armosec/kubescape/clihandler/cmd" ) func main() { diff --git a/nsa.json b/nsa.json new file mode 100644 index 00000000..b8e70c21 --- /dev/null +++ b/nsa.json @@ -0,0 +1 @@ +{"guid":"","name":"NSA","attributes":{"armoBuiltin":true},"creationTime":"","description":"Implement NSA security advices for K8s ","controls":[{"guid":"","name":"Control plane hardening","attributes":{"armoBuiltin":true},"id":"C-0005","controlID":"C-0005","creationTime":"","description":"Kubernetes control plane API is running with non-secure port enabled which allows attackers to gain unprotected access to the cluster.","remediation":"Set the insecure-port flag of the API server to zero.","rules":[{"guid":"","name":"insecure-port-flag","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\nimport data.cautils as cautils\n\n# Fails if pod has insecure-port flag enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n container := pod.spec.containers[_]\n\tisInsecurePortFlag(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The API server container: %v has insecure-port flag enabled\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has insecure-port flag enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isInsecurePortFlag(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The API server container: %v has insecure-port flag enabled\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\t\nisInsecurePortFlag(container){\n cautils.list_contains(container.command, \"--insecure-port=1\")\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if the api server has insecure-port enabled","remediation":"Make sure that the insecure-port flag of the api server is set to 0","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Host PID/IPC privileges","attributes":{"armoBuiltin":true},"id":"C-0038","controlID":"C-0038","creationTime":"","description":"Containers should be as isolated as possible from the host machine. The hostPID and hostIPC fields in Kubernetes may excessively expose the host to potentially malicious actions.","remediation":"Remove hostPID and hostIPC privileges unless they are absolutely necessary.","rules":[{"guid":"","name":"host-pid-ipc-privileges","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has hostPID enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tisHostPID(pod.spec)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has hostPID enabled\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if pod has hostIPC enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tisHostIPC(pod.spec)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has hostIPC enabled\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has hostPID enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostPID(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod with hostPID enabled\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has hostIPC enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostIPC(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod with hostIPC enabled\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has hostPID enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostPID(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod with hostPID enabled\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has hostIPC enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostIPC(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod with hostIPC enabled\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Check that hostPID and hostIPC are set to false. Default is false. Only in pod spec\n\n\nisHostPID(podspec){\n podspec.hostPID == true\n}\n\nisHostIPC(podspec){\n podspec.hostIPC == true\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"Containers should be as isolated as possible from the host machine. The hostPID and hostIPC fields in Kubernetes may excessively expose the host to potentially malicious actions.","remediation":"Make sure that the fields hostIPC and hostPID in the pod spec are not set to true (set to false or not present)","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Immutable container filesystem","attributes":{"armoBuiltin":true},"id":"C-0017","controlID":"C-0017","creationTime":"","description":"Mutable container filesystem can be abused to inject malicious code or data into containers. Use immutable (read-only) filesystem to limit potential attacks.","remediation":"Set the filesystem of the container to read-only when possible (POD securityContext, readOnlyRootFilesystem: true). If containers application needs to write into the filesystem, it is recommended to mount secondary filesystems for specific directories where application require write access.","rules":[{"guid":"","name":"immutable-container-filesystem","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pods has container with mutable filesystem\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v has mutable filesystem\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has container with mutable filesystem \ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v has mutable filesystem\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has container with mutable filesystem \ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tisMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v has mutable filesystem\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Default of readOnlyRootFilesystem is false. This field is only in container spec and not pod spec\nisMutableFilesystem(container){\n not container.securityContext.readOnlyRootFilesystem\n }","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has mutable filesystem","remediation":"Make sure that the securityContext.readOnlyRootFilesystem field in the container/pod spec is set to true","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Non-root containers","attributes":{"armoBuiltin":true},"id":"C-0013","controlID":"C-0013","creationTime":"","description":"Potential attackers may gain access to a container and leverage its existing privileges to conduct an attack. Therefore, it is not recommended to deploy containers with root privileges unless it is absolutely necessary. This contol identifies all the Pods running as root or can escalate to root.","remediation":"If your application does not need root privileges, make sure to define the runAsUser or runAsGroup under the PodSecurityContext and use user ID 1000 or higher. Do not turn on allowPrivlegeEscalation bit and make sure runAsNonRoot is true.","rules":[{"guid":"","name":"non-root-containers","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container configured to run as root\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isRootContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v may run as root\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if pod has container configured to run as root\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isRootPod(pod, container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v may run as root\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isRootContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isRootPod(wl.spec.template, container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has a container configured to run as root\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\t isRootContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n \twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isRootPod(wl.spec.jobTemplate.spec.template, container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\nisRootPod(pod, container) {\n not container.securityContext.runAsUser\n pod.spec.securityContext.runAsUser == 0\n}\n\nisRootPod(pod, container) {\n not container.securityContext.runAsUser\n\tnot container.securityContext.runAsGroup\n\tnot container.securityContext.runAsNonRoot\n not pod.spec.securityContext.runAsUser\n\tnot pod.spec.securityContext.runAsGroup\n pod.spec.securityContext.runAsNonRoot == false\n}\n\nisRootPod(pod, container) {\n not container.securityContext.runAsGroup\n pod.spec.securityContext.runAsGroup == 0\n}\n\nisRootPod(pod, container) {\n\tnot pod.spec.securityContext.runAsGroup\n\tnot pod.spec.securityContext.runAsUser\n \tcontainer.securityContext.runAsNonRoot == false\n}\n\nisRootContainer(container) {\n container.securityContext.runAsUser == 0\n}\n\nisRootContainer(container) {\n container.securityContext.runAsGroup == 0\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container can run as root","remediation":"Make sure that the user/group in the securityContext of pod/container is set to an id less than 1000, or the runAsNonRoot flag is set to true. Also make sure that the allowPrivilegeEscalation field is set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Privileged container","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Privilege escalation"]},"id":"C-0057","controlID":"C-0057","creationTime":"","description":"Potential attackers may gain access to privileged containers and inherit access to the host resources. Therefore, it is not recommended to deploy privileged containers unless it is absolutely necessary. This control identifies all the privileged Pods.","remediation":"Remove privileged capabilities by setting the securityContext.privileged to false. If you must deploy a Pod as privileged, add other restriction to it, such as network policy, Seccomp etc and still remove all unnecessary capabilities. Use the exception mechanism to remove unnecessary notifocations.","rules":[{"guid":"","name":"rule-privilege-escalation","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::privileged container","mitre":"Privilege Escalation","mitreCode":"TA0004"},"creationTime":"","rule":"package armo_builtins\n# Deny mutating action unless user is in group owning the resource\n\n\n#privileged pods\ndeny[msga] {\n\n\tpod := input[_]\n\tpod.kind == \"Pod\"\n\tcontainers := pod.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following pods are defined as privileged: %v\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n }\n}\n\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainers := wl.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v is defined as privileged:\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n#handles cronjob\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainers := wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following cronjobs are defined as privileged: %v\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"determines if pods/deployments defined as privileged true","remediation":"avoid defining pods as privilleged","ruleQuery":""}]},{"guid":"","name":"Allowed hostPath","attributes":{"armoBuiltin":true},"id":"C-0006","controlID":"C-0006","creationTime":"","description":"Mounting host directory to the container can be abused to get access to sensitive data and gain persistence on the host machine.","remediation":"Refrain from using host path mount.","rules":[{"guid":"","name":"alert-rw-hostpath","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Persistance::Writable hostPath mount, Lateral Movement::Writable volume mounts on the host"},"creationTime":"","rule":"package armo_builtins\n\n# input: pod\n# apiversion: v1\n# does: returns hostPath volumes\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n volumes := pod.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := pod.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n podname := pod.metadata.name\n\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod: %v has: %v as hostPath volume\", [podname, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n volumes := wl.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := wl.spec.template.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t\n\t}\n}\n\n#handles CronJobs\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n volumes := wl.spec.jobTemplate.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n \n\tmsga := {\n\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\"packagename\": \"armo_builtins\",\n\t\"alertScore\": 7,\n\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisRWMount(mount) {\n not mount.readOnly\n}\nisRWMount(mount) {\n mount.readOnly == false\n} ","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod"]}],"ruleDependencies":[{"packageName":"cautils"},{"packageName":"kubernetes.api.client"}],"description":"determines if any workload contains a hostPath volume with rw permissions","remediation":"Set the readOnly field of the mount to true","ruleQuery":""}]},{"guid":"","name":"Automatic mapping of service account","attributes":{"armoBuiltin":true},"id":"C-0034","controlID":"C-0034","creationTime":"","description":"Potential attacker may gain access to a POD and steal its service account token. Therefore, it is recommended to disable automatic mapping of the service account tokens in service account configuration and enable it only for PODs that need to use them.","remediation":"Disable automatic mounting of service account tokens to PODs either at the service account level or at the individual POD level, by specifying the automountServiceAccountToken: false. Note that POD level takes precedence.","rules":[{"guid":"","name":"automount-service-account","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n# Fails if user account mount tokens in pod by default.\ndeny [msga]{\n serviceaccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == \"ServiceAccount\"]\n serviceaccount := serviceaccounts[_]\n isAutoMount(serviceaccount)\n\n msga := {\n\t \"alertMessage\": sprintf(\"the following service account: %v in the following namespace: %v mounts service account tokens in pods by default\", [serviceaccount.metadata.name, serviceaccount.metadata.namespace]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [serviceaccount]\n\t\t}\n\t}\n} \n\nisAutoMount(serviceaccount) {\n\tnot serviceaccount.automountServiceAccountToken == false\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Serviceaccount"]}],"ruleDependencies":[],"description":"fails if service account automountServiceAccountToken enabled","remediation":"Make sure that the automountServiceAccountToken field on the service account spec if set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"hostNetwork access","attributes":{"armoBuiltin":true},"id":"C-0041","controlID":"C-0041","creationTime":"","description":"Potential attackers may gain access to a POD and inherit access to the entire host network. For example, in AWS case, they will have access to the entire VPC. This control identifies all the PODs with host network access enabled.","remediation":"Only connect PODs to host network when it is necessary. If not, set the hostNetwork field of the pod spec to false, or completely remove it (false is the default). Whitelist only those PODs that must have access to host network by design.","rules":[{"guid":"","name":"host-network-access","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n# Fails if pod has hostNetwork enabled\ndeny[msga] {\n pods := [ pod | pod = input[_] ; pod.kind == \"Pod\"]\n pod := pods[_]\n\n isHostNetwork(pod.spec)\n\n \tmsga := {\n\t\"alertMessage\": sprintf(\"Pod: %v is connected to the host network\", [pod.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has hostNetwork enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostNetwork(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod connected to the host network\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has hostNetwork enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostNetwork(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod connected to the host network\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisHostNetwork(podspec) {\n podspec.hostNetwork == true\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if pod has hostNetwork enabled","remediation":"Make sure that the hostNetwork field of the pod spec is not set to true (set to false or not present)","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Resource policies","attributes":{"armoBuiltin":true},"id":"C-0009","controlID":"C-0009","creationTime":"","description":"CPU and memory resources should have a limit set for every container to prevent resource exhaustion. This control identifies all the Pods without resource limit definition.","remediation":"Define LimitRange and ResourceQuota policies to limit resource usage for namespaces or nodes.","rules":[{"guid":"","name":"resource-policies","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Check if container has limits\ndeny[msga] {\n \tpods := [pod | pod = input[_]; pod.kind == \"Pod\"]\n pod := pods[_]\n\tcontainer := pod.spec.containers[_]\n\tnot container.resources.limits\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Check if container has limits - for workloads\n# If there is no limits specified in the workload, we check the namespace, since if limits are only specified for namespace\n# and not in workload, it won't be on the yaml\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n\tnot container.resources.limits\n\tisNamespaceWithLimits(wl.metadata.namespace)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n\t\n}\n\n# Check if container has limits - for cronjobs\n# If there is no limits specified in the cronjob, we check the namespace, since if limits are only specified for namespace\n# and not in cronjob, it won't be on the yaml\ndeny [msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tnot container.resources.limits\n\tisNamespaceWithLimits(wl.metadata.namespace)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if LimitRange exists but it does not define maximum usage of resources\ndeny[msga] {\n\n limitRanges := [limitRange | limitRange = input[_]; limitRange.kind == \"LimitRange\"]\n limitRange := limitRanges[_]\n\n\tlimits := limitRange.spec.limits[_]\n not limits.max\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following LimitRange: %v does not define a maximum field for resources\", [limitRange.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [limitRange]\n\t\t}\n\t}\n}\n\n# Fails if ResourQuota exists but it does not define maximum usage of resources\ndeny[msga] {\n resourceQuotas := [resourceQuota | resourceQuota = input[_]; resourceQuota.kind == \"ResourceQuota\"]\n resourceQuota := resourceQuotas[_]\n\n not resourceQuota.spec.hard\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following ResourQuota: %v does not define a hard field\", [resourceQuota.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [resourceQuota]\n\t\t}\n\t}\n}\n\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}\n\n\n# Check only LimitRange. For ResourceQuota limits need to be specified. \nisNamespaceWithLimits(namespace) {\n limitRanges := [policy.metadata.namespace | policy = input[_]; policy.kind == \"LimitRange\"]\n not list_contains(limitRanges, namespace)\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod","LimitRange","ResourceQuota"]}],"ruleDependencies":[],"description":"fails if namespace has no resource policies defined","remediation":"Make sure that you definy resource policies (LimitRange or ResourceQuota) which limit the usage of resources for all the namespaces","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Exposed dashboard","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Initial Access"]},"id":"C-0047","controlID":"C-0047","creationTime":"","description":"Kubernetes dashboard versions before v2.0.1 do not support user authentication. If exposed externally, it will allow unauthenticated remote management of the cluster. This control checks presence of the kubernetes-dashboard deployment and its version number.","remediation":"Update dashboard version to v2.0.1 and above.","rules":[{"guid":"","name":"rule-exposed-dashboard","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Initial Access::Exposed Dashboard"},"creationTime":"","rule":"package armo_builtins\n\n# input: pods\n# apiversion: v1\n# fails if dashboard exists and is exposed\n\ndeny[msga] {\n\tdeployment := input[_]\n startswith(deployment.metadata.name, \"kubernetes-dashboard\")\n container := deployment.spec.template.spec.containers[_]\n version := trim_prefix(container.image, \"kubernetesui/dashboard:v\")\n to_number(replace(version, \".\", \"\")) \u003c 201\n \n\tservice := input[_]\n\tservice.kind == \"Service\"\n\tisNodePortLbService(service)\n count({x | service.spec.selector[x]; deployment.metadata.labels[x]}) == count(service.spec.selector)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"dashboard exists and is exposed %s\", [container.image]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [deployment]\n\t\t}\n }\n}\n\n\n\nisNodePortLbService(service) {\n\tservice.spec.type == \"NodePort\"\n}\n\nisNodePortLbService(service) {\n\tservice.spec.type == \"LoadBalancer\"\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","Service"]}],"ruleDependencies":[],"description":"fails if dashboard exists and is exposed","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Allow privilege escalation","attributes":{"armoBuiltin":true},"id":"C-0016","controlID":"C-0016","creationTime":"","description":"Attackers may gain access to a container and uplift its privilege to enable excessive capabilities.","remediation":"If your application does not need it, make sure the allowPrivilegeEscalation field of the securityContext is set to false.","rules":[{"guid":"","name":"rule-allow-privilege-escalation","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container that allow privilege escalation\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isAllowPrivilegeEscalationContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v allow privilege escalation\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has a container that allow privilege escalation\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isAllowPrivilegeEscalationContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v allow privilege escalation\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has a container that allow privilege escalation\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tisAllowPrivilegeEscalationContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v allow privilege escalation\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\nisAllowPrivilegeEscalationContainer(container) {\n container.securityContext.allowPrivilegeEscalation == true\n}\n\nisAllowPrivilegeEscalationContainer(container) {\n sysAdminCap := \"SYS_ADMIN\"\n contains(container.securityContext.capabilities.add[_], sysAdminCap)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container allows privilege escalation","remediation":"Make sure that the allowPrivilegeEscalation field in the securityContext of pod/container is set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Applications credentials in configuration files","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Credential access","Lateral Movement"]},"id":"C-0012","controlID":"C-0012","creationTime":"","description":"Attackers who have access to configuration files can steal the stored secrets and use them. This control checks if ConfigMaps or pod specifications have sensitive information in their configuration.","remediation":"Use Kubernetes secrets or Key Management Systems to store credentials.","rules":[{"guid":"","name":"rule-credentials-in-env-var","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Credential access::Applications credentials in configuration files, Lateral Movement::Applications credentials in configuration files"},"creationTime":"","rule":"package armo_builtins\n# import data.cautils as cautils\n# import data.kubernetes.api.client as client\n\ndeny[msga] {\n\tpod := input[_]\n pod.kind == \"Pod\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n container := pod.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has sensitive information in environment variables\", [pod.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n }\n}\n\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n container := wl.spec.template.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has sensitive information in environment variables\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Cronjob: %v has sensitive information in environment variables\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n\n\nisNotReference(env)\n{\n\tnot env.valueFrom.secretKeyRef\n\tnot env.valueFrom.configMapKeyRef\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if Pods have sensitive information in configuration","remediation":"","ruleQuery":"armo_builtins"},{"guid":"","name":"rule-credentials-configmap","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Credential access::Applications credentials in configuration files, Lateral Movement::Applications credentials in configuration files"},"creationTime":"","rule":"package armo_builtins\n# import data.cautils as cautils\n# import data.kubernetes.api.client as client\n\n# fails if config map has keys with suspicious name\ndeny[msga] {\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"pass\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n map_secret := configmap.data[map_key]\n contains(lower(map_key), key_name)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}\n\n# fails if config map has values with suspicious content - not base 64\ndeny[msga] {\n sensitive_values := {\"BEGIN\", \"PRIVATE KEY\", \"eyJhbGciO\"}\n value := sensitive_values[_]\n\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n map_secret := configmap.data[map_key]\n contains(map_secret, value)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}\n\n# fails if config map has values with suspicious content - base 64\ndeny[msga] {\n sensitive_values := {\"BEGIN\", \"PRIVATE KEY\", \"eyJhbGciO\"}\n value := sensitive_values[_]\n\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n map_secret := configmap.data[map_key]\n decoded_secret := base64.decode(map_secret)\n contains(decoded_secret, value)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["ConfigMap"]}],"ruleDependencies":[],"description":"fails if ConfigMaps have sensitive information in configuration","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Cluster-admin binding","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Privilege escalation"]},"id":"C-0035","controlID":"C-0035","creationTime":"","description":"Attackers who have cluster admin permissions (can perform any action on any resource), can take advantage of their privileges for malicious activities. This control determines which subjects have cluster admin permissions.","remediation":"You should apply least privilege principle. Make sure cluster admin permissions are granted only when it is absolutely necessary. Don't use subjects with such high permissions for daily operations.","rules":[{"guid":"","name":"rule-list-all-cluster-admins","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::Cluster-admin binding"},"creationTime":"","rule":"package armo_builtins\nimport data.cautils as cautils\n\n# input: roles\n# apiversion: v1\n# does: returns roles+ related subjects in rolebinding\n\ndeny[msga] {\n\troles := [role | role= input[_]; role.kind == \"Role\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"Role\"\n\trolebinding.roleRef.name == role.metadata.name\n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n }\n}\n\n# input: ClusterRole\n# apiversion: v1\n# does: returns clusterroles+ related subjects in rolebinding\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n \n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n }\n}\n\n# input: ClusterRole\n# apiversion: v1\n# does:\treturns clusterroles+ related subjects in clusterrolebinding\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"ClusterRoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n\ncanCreate(rule) {\n\tcautils.list_contains(rule.verbs,\"*\")\n}\ncanCreateResources(rule){\n\tcautils.list_contains(rule.resources,\"*\")\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Role","ClusterRole","ClusterRoleBinding","RoleBinding"]}],"ruleDependencies":[{"packageName":"cautils"}],"description":"determines which users have cluster admin permissions","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Exec into container","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Execution"]},"id":"C-0002","controlID":"C-0002","creationTime":"","description":"Attackers with relevant permissions can run malicious commands in the context of legitimate containers in the cluster using ā€œkubectl execā€ command. This control determines which subjects have permissions to use this command.","remediation":"It is recommended to prohibit ā€œkubectl execā€ command in production environments. It is also recommended not to use subjects with this permission for daily cluster operations.","rules":[{"guid":"","name":"exec-into-container","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::Exec into container"},"creationTime":"","rule":"\npackage armo_builtins\nimport data.cautils as cautils\n\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n\t roles := [role | role= input[_]; role.kind == \"Role\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"Role\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"ClusterRoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\ncanExecToPodVerb(rule) {\n\tcautils.list_contains(rule.verbs, \"create\")\n}\ncanExecToPodVerb(rule) {\n\tcautils.list_contains(rule.verbs, \"*\")\n}\n\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"pods/exec\")\n}\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"pods/*\")\n}\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"*\")\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Role","ClusterRole","ClusterRoleBinding","RoleBinding"]}],"ruleDependencies":[{"packageName":"cautils"}],"description":"determines which users have permissions to exec into pods","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Dangerous capabilities","attributes":{"armoBuiltin":true},"id":"C-0028","controlID":"C-0028","creationTime":"","description":"Giving dangerous and unnecessary LINUX capabilities to a container can increase the impact of the container compromise. This control identifies all the PODs with dangerous capabilities such as SYS_ADMIN and others.","remediation":"Check and remove all unnecessary capabilities from the POD security context of the containers and use the exception mechanism to remove warnings where these capabilities are necessary.","rules":[{"guid":"","name":"dangerous-capabilities","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v have dangerous capabilities\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in workload: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in cronjob: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisDangerousCapabilities(container){\n dangerousCapabilities := [\"ALL\", \"SYS_ADMIN\", \"NET_ADMIN\", \"SYS_PTRACE\"]\n dangerousCapabilitie := dangerousCapabilities[_]\n contains(container.securityContext.capabilities.add[_], dangerousCapabilitie)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has dangrous capabilities","remediation":"Remove all dangerous capabilities which aren’t necessary for the container.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Insecure capabilities","attributes":{"armoBuiltin":true},"id":"C-0046","controlID":"C-0046","creationTime":"","description":"Giving insecure or excsessive capabilities to a container can increase the impact of the container compromise. This control identifies all the PODs with dangerous capabilities (see documentation pages for details).","remediation":"Remove all insecure capabilities which aren’t necessary for the container.","rules":[{"guid":"","name":"insecure-capabilities","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v have dangerous capabilities\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in workload: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in cronjob: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisDangerousCapabilities(container){\n insecureCapabilities := [\"CHOWN\", \"DAC_OVERRIDE\", \"FSETID\", \"FOWNER\", \"MKNOD\", \"NET_RAW\", \"SETGID\", \"SETUID\", \"SETFCAP\", \"NET_BIND_SERVICE\",\"SYS_CHROOT\",\"KILL\",\"AUDIT_WRITE\"]\n insecureCapabilitie := insecureCapabilities[_]\n contains(container.securityContext.capabilities.add[_], insecureCapabilitie)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has insecure capabilities","remediation":"Remove all insecure capabilities which aren’t necessary for the container.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Linux hardening","attributes":{"armoBuiltin":true},"id":"C-0055","controlID":"C-0055","creationTime":"","description":"Containers may be given more privileges than they actually need. This can increase the potential impact of a container compromise.","remediation":"You can use AppArmor, Seccomp, SELinux and Linux Capabilities mechanisms to restrict containers abilities to utilize unwanted privileges.","rules":[{"guid":"","name":"linux-hardening","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod does not define linux security hardening \ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n isUnsafePod(pod)\n container := pod.spec.containers[_]\n isUnsafeContainer(container)\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not define any linux security hardening\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload does not define linux security hardening \ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n isUnsafeWorkload(wl)\n container := wl.spec.template.spec.containers[_]\n isUnsafeContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Workload: %v does not define any linux security hardening\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if pod does not define linux security hardening \ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n isUnsafeCronJob(wl)\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isUnsafeContainer(container)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Cronjob: %v does not define any linux security hardening\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisUnsafePod(pod){\n not pod.spec.securityContext.seccompProfile\n not pod.spec.securityContext.seLinuxOptions\n\tannotations := [pod.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\nisUnsafeContainer(container){\n not container.securityContext.seccompProfile\n not container.securityContext.seLinuxOptions\n not container.securityContext.capabilities.drop\n}\n\nisUnsafeWorkload(wl) {\n not wl.spec.template.spec.securityContext.seccompProfile\n not wl.spec.template.spec.securityContext.seLinuxOptions\n\tannotations := [wl.spec.template.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\nisUnsafeCronJob(cronjob) {\n not cronjob.spec.jobTemplate.spec.template.spec.securityContext.seccompProfile\n not cronjob.spec.jobTemplate.spec.template.spec.securityContext.seLinuxOptions\n\tannotations := [cronjob.spec.jobTemplate.spec.template.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container does not defien any linux security hardening","remediation":"Make sure you define at least one linux security hardening property out of Seccomp, SELinux or Capabilities.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Ingress and Egress blocked","attributes":{"armoBuiltin":true},"id":"C-0030","controlID":"C-0030","creationTime":"","description":"Disable Ingress and Egress traffic on all pods wherever possible. It is recommended to define restrictive network policy on all new PODs, and then enable sources/destinations that this POD must communicate with.","remediation":"Define a network policy that restricts ingress and egress connections.","rules":[{"guid":"","name":"ingress-and-egress-blocked","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# For pods\ndeny[msga] {\n \t\tpods := [pod | pod= input[_]; pod.kind == \"Pod\"]\n\t\tnetworkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\t\tpod := pods[_]\n\t\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; podConnectedToNetworkPolicy(pod, networkpolicie)]\n\t\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\t\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not have ingress/egress defined\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n\n}\n\n# For pods\ndeny[msga] {\n \t\tpods := [pod | pod= input[_]; pod.kind == \"Pod\"]\n\t\tnetworkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\t\tpod := pods[_]\n\t\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; podConnectedToNetworkPolicy(pod, networkpolicie)]\n\t\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not have ingress/egress defined\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n\n}\n\n# For workloads\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; wlConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# For workloads\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; wlConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# For Cronjobs\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; cronjobConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# For Cronjobs\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; cronjobConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\npodConnectedToNetworkPolicy(pod, networkpolicie){\n\tnetworkpolicie.metadata.namespace == pod.metadata.namespace\n count(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == pod.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\npodConnectedToNetworkPolicy(pod, networkpolicie){\n\tnetworkpolicie.metadata.namespace == pod.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\nwlConnectedToNetworkPolicy(wl, networkpolicie){\n\twl.metadata.namespace == networkpolicie.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\n\nwlConnectedToNetworkPolicy(wl, networkpolicie){\n\twl.metadata.namespace == wl.metadata.namespace\n\tcount(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == wl.spec.template.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\n\ncronjobConnectedToNetworkPolicy(cj, networkpolicie){\n\tcj.metadata.namespace == networkpolicie.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\ncronjobConnectedToNetworkPolicy(cj, networkpolicie){\n\tcj.metadata.namespace == networkpolicie.metadata.namespace\n\tcount(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == cj.spec.jobTemplate.spec.template.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\nisIngerssEgressPolicy(networkpolicie) {\n list_contains(networkpolicie.spec.policyTypes, \"Ingress\")\n list_contains(networkpolicie.spec.policyTypes, \"Egress\")\n }\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob","NetworkPolicy"]}],"ruleDependencies":[],"description":"fails if there are no ingress and egress defined for pod","remediation":"Make sure you define ingress and egress policies for all your Pods","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Container hostPort","attributes":{"armoBuiltin":true},"id":"C-0044","controlID":"C-0044","creationTime":"","description":"Configuring hostPort limits you to a particular port, and if any two workloads that specify the same HostPort they cannot be deployed to the same node. Therefore, if the number of replica of such workload is higher than the number of nodes, the deployment will fail.","remediation":"Avoid usage of hostPort unless it is absolutely necessary. Use NodePort / ClusterIP instead.","rules":[{"guid":"","name":"container-hostPort","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container with hostPort\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n container := pod.spec.containers[_]\n\tisHostPort(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v has Host-port\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has container with hostPort\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isHostPort(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has container with hostPort\ndeny[msga] {\n \twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isHostPort(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\nisHostPort(container){\n\tports := container.ports[_]\n ports.hostPort\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has hostPort","remediation":"Make sure you do not configure hostPort for the container, if necessary use NodePort / ClusterIP","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Network policies","attributes":{"armoBuiltin":true},"id":"C-0011","controlID":"C-0011","creationTime":"","description":"If no network policy is defined, attackers who gain access to a single container may use it to probe the network. This control lists all namespaces in which no network policies are defined.","remediation":"Define network policies or use similar network protection mechanisms.","rules":[{"guid":"","name":"internal-networking","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Lateral Movement::Container internal networking, Discovery::Network mapping"},"creationTime":"","rule":"package armo_builtins\n\n# input: network policies\n# apiversion: networking.k8s.io/v1\n# fails if no network policies are defined in a certain namespace\n\ndeny[msga] {\n\tnamespaces := [namespace | namespace = input[_]; namespace.kind == \"Namespace\"]\n\tnamespace := namespaces[_]\n\tpolicy_names := [policy.metadata.namespace | policy = input[_]; policy.kind == \"NetworkPolicy\"]\n\tnot list_contains(policy_names, namespace.metadata.name)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"no policy is defined for namespace %v\", [namespace.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [namespace]\n\t\t}\n\t}\n}\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["networkpolicies","namespaces"]}],"ruleDependencies":[],"description":"lists namespaces in which no network policies are defined","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"CVE-2021-25741 - Using symlink for arbitrary host file system access.","attributes":{"armoBuiltin":true},"id":"C-0058","controlID":"C-0058","creationTime":"","description":"A user may be able to create a container with subPath or subPathExpr volume mounts to access files \u0026 directories anywhere on the host filesystem. Following Kubernetes versions are affected: v1.22.0 - v1.22.1, v1.21.0 - v1.21.4, v1.20.0 - v1.20.10, version v1.19.14 and lower. This control checks the vulnerable versions and the actual usage of the subPath feature in all Pods in the cluster.","remediation":"To mitigate this vulnerability without upgrading kubelet, you can disable the VolumeSubpath feature gate on kubelet and kube-apiserver, or remove any existing Pods using subPath or subPathExpr feature.","rules":[{"guid":"","name":"Symlink-Exchange-Can-Allow-Host-Filesystem-Access","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isSubPathContainer(container)\n\n\tmsga := {\n\t\t\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in pod : %v with subPath/subPathExpr\", [current_version, container.name, pod.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, pod]},\n\t\t}\n}\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isSubPathContainer(container)\n \n\tmsga := {\n\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in %v : %v with subPath/subPathExpr\", [current_version, container.name, wl.kind, wl.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, wl]},\n\t\t}\n}\n\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isSubPathContainer(container)\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in %v : %v with subPath/subPathExpr\", [current_version, container.name, wl.kind, wl.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, wl]},\n\t\t}\n}\n\n\n\nisSubPathContainer(container){\n container.volumeMounts[_].subPath\n}\n\nisSubPathContainer(container){\n container.volumeMounts[_].subPathExpr\n}\n\nisVulnerableVersion(version){\n version \u003c= \"v1.19.14\"\n}\n\nisVulnerableVersion(version){\n version \u003e= \"v1.22.0\"\n version \u003c= \"v1.22.1\"\n}\n\n\nisVulnerableVersion(version){\n version \u003e= \"v1.21.0\"\n version \u003c= \"v1.21.4\"\n}\n\n\nisVulnerableVersion(version){\n version \u003e= \"v1.20.0\"\n version \u003c= \"v1.20.9\"\n}\n\nisVulnerableVersion(version){\n\tversion == \"v1.20.10\"\n}\n\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob","Node"]}],"ruleDependencies":[],"description":"A user may be able to create a container with subPath volume mounts to access files \u0026 directories outside of the volume, including on the host filesystem. This was affected at the following versions: v1.22.0 - v1.22.1, v1.21.0 - v1.21.4, v1.20.0 - v1.20.10, version v1.19.14 and lower. ","remediation":"To mitigate this vulnerability without upgrading kubelet, you can disable the VolumeSubpath feature gate on kubelet and kube-apiserver, and remove any existing Pods making use of the feature.","ruleQuery":"armo_builtins"}]}]} \ No newline at end of file diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go index 9da07cac..1b395dba 100644 --- a/policyhandler/handlenotification.go +++ b/policyhandler/handlenotification.go @@ -10,6 +10,11 @@ import ( "github.com/armosec/k8s-interface/k8sinterface" ) +var supportedFrameworks = []reporthandling.PolicyIdentifier{ + {Kind: "Framework", Name: "nsa"}, + {Kind: "Framework", Name: "mitre"}, +} + // PolicyHandler - type PolicyHandler struct { k8s *k8sinterface.KubernetesApi @@ -59,7 +64,7 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *repo func (policyHandler *PolicyHandler) getPolicies(notification *reporthandling.PolicyNotification) ([]reporthandling.Framework, []armotypes.PostureExceptionPolicy, error) { - cautils.ProgressTextDisplay("Downloading/Loading framework definitions") + cautils.ProgressTextDisplay("Downloading/Loading policy definitions") frameworks, exceptions, err := policyHandler.GetPoliciesFromBackend(notification) if err != nil { @@ -70,7 +75,8 @@ func (policyHandler *PolicyHandler) getPolicies(notification *reporthandling.Pol err := fmt.Errorf("could not download any policies, please check previous logs") return frameworks, exceptions, err } - cautils.SuccessTextDisplay("Downloaded/Loaded framework") + //if notification.Rules + cautils.SuccessTextDisplay("Downloaded/Loaded policy") return frameworks, exceptions, nil } diff --git a/policyhandler/handlepullpolicies.go b/policyhandler/handlepullpolicies.go index 34f0f7ec..90ec3ddc 100644 --- a/policyhandler/handlepullpolicies.go +++ b/policyhandler/handlepullpolicies.go @@ -30,7 +30,23 @@ func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *reporth } return nil, nil, fmt.Errorf("kind: %v, name: %s, error: %s", rule.Kind, rule.Name, err.Error()) } - + case reporthandling.KindControl: + receivedControls, recExceptionPolicies, err := policyHandler.getControl(rule.Name) + if receivedControls != nil { + f := reporthandling.Framework{ + Controls: receivedControls, + } + frameworks = append(frameworks, f) + if recExceptionPolicies != nil { + exceptionPolicies = append(exceptionPolicies, recExceptionPolicies...) + } + } else if err != nil { + if strings.Contains(err.Error(), "unsupported protocol scheme") { + err = fmt.Errorf("failed to download from GitHub release, try running with `--use-default` flag") + } + return nil, nil, fmt.Errorf("error: %s", err.Error()) + } + // TODO: add case for control from file default: err := fmt.Errorf("missing rule kind, expected: %s", reporthandling.KindFramework) errs = fmt.Errorf("%s", err.Error()) @@ -52,3 +68,44 @@ func (policyHandler *PolicyHandler) getFrameworkPolicies(policyName string) (*re return receivedFramework, receivedException, nil } + +func (policyHandler *PolicyHandler) getControl(policyName string) ([]reporthandling.Control, []armotypes.PostureExceptionPolicy, error) { + + // get all frameworks + frameworks := []reporthandling.Framework{} + controls := []reporthandling.Control{} + + for i := range supportedFrameworks { + // TODO : implement getControl in policygetter + framework, err := policyHandler.getters.PolicyGetter.GetFramework(supportedFrameworks[i].Name) + if err != nil { + return nil, nil, err + } + if framework != nil { + frameworks = append(frameworks, *framework) + } + } + control := findControlInFrameworks(frameworks, policyName) + if control == nil { + return nil, nil, fmt.Errorf("control not found") + } + controls = append(controls, *control) + + exceptions, err := policyHandler.getters.ExceptionsGetter.GetExceptions(cautils.CustomerGUID, cautils.ClusterName) + if err != nil { + return controls, nil, err + } + + return controls, exceptions, nil +} + +func findControlInFrameworks(frameworks []reporthandling.Framework, controlName string) *reporthandling.Control { + for _, framework := range frameworks { + for _, control := range framework.Controls { + if strings.EqualFold(control.Name, controlName) || strings.EqualFold(control.ControlID, controlName) { + return &control + } + } + } + return nil +} diff --git a/resultshandling/printer/printresults.go b/resultshandling/printer/printresults.go index 8d8fc080..bc483b25 100644 --- a/resultshandling/printer/printresults.go +++ b/resultshandling/printer/printresults.go @@ -223,7 +223,8 @@ func (printer *Printer) PrintSummaryTable() { summaryTable.SetAutoWrapText(false) summaryTable.SetHeader(generateHeader()) summaryTable.SetHeaderLine(true) - summaryTable.SetAlignment(tablewriter.ALIGN_LEFT) + alignments := []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} + summaryTable.SetColumnAlignment(alignments) for i := 0; i < len(printer.sortedControlNames); i++ { controlSummary := printer.summary[printer.sortedControlNames[i]] diff --git a/resultshandling/results.go b/resultshandling/results.go index 64ace984..39258dc2 100644 --- a/resultshandling/results.go +++ b/resultshandling/results.go @@ -20,13 +20,16 @@ func NewResultsHandler(opaSessionObj *chan *cautils.OPASessionObj, reporterObj * } } -func (resultsHandler *ResultsHandler) HandleResults() float32 { +func (resultsHandler *ResultsHandler) HandleResults(scanInfo cautils.ScanInfo) float32 { opaSessionObj := <-*resultsHandler.opaSessionObj score := resultsHandler.printerObj.ActionPrint(opaSessionObj) - resultsHandler.reporterObj.ActionSendReportListenner(opaSessionObj) + // Don't send report for control scan + if scanInfo.FrameworkScan { + resultsHandler.reporterObj.ActionSendReportListenner(opaSessionObj) + } return score } From 009d8275c10f6bb1a06e0ec24e120ab899bf78a1 Mon Sep 17 00:00:00 2001 From: dwertent Date: Tue, 19 Oct 2021 14:22:09 +0300 Subject: [PATCH 23/37] Distinct exclude and failed resources --- README.md | 2 +- resultshandling/printer/printresults.go | 41 ++++++++++++++++--------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2b82689a..5afce369 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --form kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --format junit --output results.xml ``` -* Scan with exceptions, objects with exceptions will be presented as `warning` and not `fail` +* Scan with exceptions, objects with exceptions will be presented as `exclude` and not `fail` ``` kubescape scan framework nsa --exceptions examples/exceptions.json ``` diff --git a/resultshandling/printer/printresults.go b/resultshandling/printer/printresults.go index 8d8fc080..97602e05 100644 --- a/resultshandling/printer/printresults.go +++ b/resultshandling/printer/printresults.go @@ -101,16 +101,16 @@ func (printer *Printer) SummarySetup(postureReport *reporthandling.PostureReport continue } workloadsSummary := listResultSummary(cr.RuleReports) - mapResources := groupByNamespace(workloadsSummary) printer.summary[cr.Name] = ControlSummary{ - TotalResources: cr.GetNumberOfResources(), - TotalFailed: cr.GetNumberOfFailedResources(), - TotalWarnign: cr.GetNumberOfWarningResources(), - WorkloadSummary: mapResources, - Description: cr.Description, - Remediation: cr.Remediation, - ListInputKinds: cr.ListControlsInputKinds(), + TotalResources: cr.GetNumberOfResources(), + TotalFailed: cr.GetNumberOfFailedResources(), + TotalWarnign: cr.GetNumberOfWarningResources(), + FailedWorkloads: groupByNamespace(workloadsSummary, workloadSummaryFailed), + ExcludedWorkloads: groupByNamespace(workloadsSummary, workloadSummaryExclude), + Description: cr.Description, + Remediation: cr.Remediation, + ListInputKinds: cr.ListControlsInputKinds(), } } } @@ -120,8 +120,7 @@ func (printer *Printer) PrintResults() { for i := 0; i < len(printer.sortedControlNames); i++ { controlSummary := printer.summary[printer.sortedControlNames[i]] printer.printTitle(printer.sortedControlNames[i], &controlSummary) - printer.printResult(printer.sortedControlNames[i], &controlSummary) - + printer.printResources(&controlSummary) if printer.summary[printer.sortedControlNames[i]].TotalResources > 0 { printer.printSummary(printer.sortedControlNames[i], &controlSummary) } @@ -144,7 +143,7 @@ func (printer *Printer) printSummary(controlName string, controlSummary *Control func (printer *Printer) printTitle(controlName string, controlSummary *ControlSummary) { cautils.InfoDisplay(printer.writer, "[control: %s] ", controlName) - if controlSummary.TotalResources == 0 && len(controlSummary.ListInputKinds) > 0 { + if controlSummary.TotalResources == 0 { cautils.InfoDisplay(printer.writer, "resources not found %v\n", emoji.ConfusedFace) } else if controlSummary.TotalFailed != 0 { cautils.FailureDisplay(printer.writer, "failed %v\n", emoji.SadButRelievedFace) @@ -157,10 +156,24 @@ func (printer *Printer) printTitle(controlName string, controlSummary *ControlSu cautils.DescriptionDisplay(printer.writer, "Description: %s\n", controlSummary.Description) } -func (printer *Printer) printResult(controlName string, controlSummary *ControlSummary) { +func (printer *Printer) printResources(controlSummary *ControlSummary) { + + if len(controlSummary.FailedWorkloads) > 0 { + cautils.FailureDisplay(printer.writer, "Failed:\n") + printer.printGroupedResources(controlSummary.FailedWorkloads) + } + if len(controlSummary.ExcludedWorkloads) > 0 { + cautils.WarningDisplay(printer.writer, "Excluded:\n") + printer.printGroupedResources(controlSummary.ExcludedWorkloads) + } + +} + +func (printer *Printer) printGroupedResources(workloads map[string][]WorkloadSummary) { indent := INDENT - for ns, rsc := range controlSummary.WorkloadSummary { + + for ns, rsc := range workloads { preIndent := indent if ns != "" { cautils.SimpleDisplay(printer.writer, "%sNamespace %s\n", indent, ns) @@ -207,7 +220,7 @@ func percentage(big, small int) int { func generateFooter(numControlers, sumFailed, sumWarning, sumTotal int) []string { // Control name | # failed resources | all resources | % success row := []string{} - row = append(row, fmt.Sprintf("%d", numControlers)) + row = append(row, "Resource Summary") //fmt.Sprintf(""%d", numControlers")) row = append(row, fmt.Sprintf("%d", sumFailed)) row = append(row, fmt.Sprintf("%d", sumWarning)) row = append(row, fmt.Sprintf("%d", sumTotal)) From b371fbad0128a8bfaac8e562e7c398a8003fbe73 Mon Sep 17 00:00:00 2001 From: dwertent Date: Tue, 19 Oct 2021 15:08:00 +0300 Subject: [PATCH 24/37] adding summary --- docs/run-options.md | 2 +- resultshandling/printer/summary.go | 23 ++++++++++++++++------- resultshandling/printer/summeryhelpers.go | 14 ++++++++------ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/docs/run-options.md b/docs/run-options.md index 4a7a0a80..8a94afc0 100644 --- a/docs/run-options.md +++ b/docs/run-options.md @@ -51,7 +51,7 @@ kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --form kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --format junit --output results.xml ``` -* Scan with exceptions, objects with exceptions will be presented as `warning` and not `fail` +* Scan with exceptions, objects with exceptions will be presented as `warning` and not `fail` ``` kubescape scan framework nsa --exceptions examples/exceptions.json ``` diff --git a/resultshandling/printer/summary.go b/resultshandling/printer/summary.go index 1bc90911..9df245f6 100644 --- a/resultshandling/printer/summary.go +++ b/resultshandling/printer/summary.go @@ -13,13 +13,14 @@ func NewSummary() Summary { } type ControlSummary struct { - TotalResources int - TotalFailed int - TotalWarnign int - Description string - Remediation string - ListInputKinds []string - WorkloadSummary map[string][]WorkloadSummary // :[] + TotalResources int + TotalFailed int + TotalWarnign int + Description string + Remediation string + ListInputKinds []string + FailedWorkloads map[string][]WorkloadSummary // :[] + ExcludedWorkloads map[string][]WorkloadSummary // :[] } type WorkloadSummary struct { @@ -41,3 +42,11 @@ func (controlSummary *ControlSummary) ToSlice() []string { func (workloadSummary *WorkloadSummary) ToString() string { return fmt.Sprintf("/%s/%s/%s/%s", workloadSummary.Group, workloadSummary.Namespace, workloadSummary.Kind, workloadSummary.Name) } + +func workloadSummaryFailed(workloadSummary *WorkloadSummary) bool { + return workloadSummary.Exception == nil +} + +func workloadSummaryExclude(workloadSummary *WorkloadSummary) bool { + return workloadSummary.Exception != nil && workloadSummary.Exception.IsAlertOnly() +} diff --git a/resultshandling/printer/summeryhelpers.go b/resultshandling/printer/summeryhelpers.go index 3cd11edb..cf7a4e43 100644 --- a/resultshandling/printer/summeryhelpers.go +++ b/resultshandling/printer/summeryhelpers.go @@ -8,14 +8,16 @@ import ( ) // Group workloads by namespace - return {"namespace": <[]WorkloadSummary>} -func groupByNamespace(resources []WorkloadSummary) map[string][]WorkloadSummary { +func groupByNamespace(resources []WorkloadSummary, status func(workloadSummary *WorkloadSummary) bool) map[string][]WorkloadSummary { mapResources := make(map[string][]WorkloadSummary) for i := range resources { - if r, ok := mapResources[resources[i].Namespace]; ok { - r = append(r, resources[i]) - mapResources[resources[i].Namespace] = r - } else { - mapResources[resources[i].Namespace] = []WorkloadSummary{resources[i]} + if status(&resources[i]) { + if r, ok := mapResources[resources[i].Namespace]; ok { + r = append(r, resources[i]) + mapResources[resources[i].Namespace] = r + } else { + mapResources[resources[i].Namespace] = []WorkloadSummary{resources[i]} + } } } return mapResources From 87e79110a23c2c67aff4b68b17deda3639a1190a Mon Sep 17 00:00:00 2001 From: dwertent Date: Tue, 19 Oct 2021 16:25:54 +0300 Subject: [PATCH 25/37] fallback customer guid from configMap --- cautils/customerloader.go | 92 +++++++++++++++++++++++++++------------ cmd/framework.go | 4 +- 2 files changed, 65 insertions(+), 31 deletions(-) diff --git a/cautils/customerloader.go b/cautils/customerloader.go index c97acdb1..8e723b20 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -30,6 +30,7 @@ type ConfigObj struct { CustomerGUID string `json:"customerGUID"` Token string `json:"invitationParam"` CustomerAdminEMail string `json:"adminMail"` + ClusterName string `json:"clusterName"` } func (co *ConfigObj) Json() []byte { @@ -39,14 +40,30 @@ func (co *ConfigObj) Json() []byte { return []byte{} } +// Config - convert ConfigObj to config file +func (co *ConfigObj) Config() []byte { + clusterName := co.ClusterName + co.ClusterName = "" // remove cluster name before saving to file + b, err := json.Marshal(co) + co.ClusterName = clusterName + + if err == nil { + return b + } + + return []byte{} +} + // ====================================================================================== // =============================== interface ============================================ // ====================================================================================== type IClusterConfig interface { - // setters - SetCustomerGUID(customerGUID string) error + + // set + SetConfig(customerGUID string) error // getters + GetClusterName() string GetCustomerGUID() string GetConfigObj() *ConfigObj GetK8sAPI() *k8sinterface.KubernetesApi @@ -103,13 +120,14 @@ func ClusterConfigSetup(scanInfo *ScanInfo, k8s *k8sinterface.KubernetesApi, beA type EmptyConfig struct { } -func NewEmptyConfig() *EmptyConfig { return &EmptyConfig{} } -func (c *EmptyConfig) GetConfigObj() *ConfigObj { return &ConfigObj{} } -func (c *EmptyConfig) SetCustomerGUID(customerGUID string) error { return nil } -func (c *EmptyConfig) GetCustomerGUID() string { return "" } -func (c *EmptyConfig) GetK8sAPI() *k8sinterface.KubernetesApi { return nil } // TODO: return mock obj -func (c *EmptyConfig) GetDefaultNS() string { return k8sinterface.GetDefaultNamespace() } -func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj +func NewEmptyConfig() *EmptyConfig { return &EmptyConfig{} } +func (c *EmptyConfig) SetConfig(customerGUID string) error { return nil } +func (c *EmptyConfig) GetConfigObj() *ConfigObj { return &ConfigObj{} } +func (c *EmptyConfig) GetCustomerGUID() string { return "" } +func (c *EmptyConfig) GetK8sAPI() *k8sinterface.KubernetesApi { return nil } // TODO: return mock obj +func (c *EmptyConfig) GetDefaultNS() string { return k8sinterface.GetDefaultNamespace() } +func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj +func (c *EmptyConfig) GetClusterName() string { return "unknown" } func (c *EmptyConfig) GenerateURL() { message := fmt.Sprintf("You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s", getter.GetArmoAPIConnector().GetFrontendURL()) InfoTextDisplay(os.Stdout, message+"\n") @@ -169,10 +187,19 @@ func (c *ClusterConfig) GetCustomerGUID() string { return "" } -func (c *ClusterConfig) SetCustomerGUID(customerGUID string) error { +func (c *ClusterConfig) SetConfig(customerGUID string) error { + if c.configObj == nil { + c.configObj = &ConfigObj{} + } + // cluster name + if c.GetClusterName() == "" { + c.setClusterName(k8sinterface.GetClusterName()) + } + + // ARMO customer GUID if customerGUID != "" && c.GetCustomerGUID() != customerGUID { - c.configObj.CustomerGUID = customerGUID // override config customerGUID + c.setCustomerGUID(customerGUID) // override config customerGUID } customerGUID = c.GetCustomerGUID() @@ -181,10 +208,10 @@ func (c *ClusterConfig) SetCustomerGUID(customerGUID string) error { tenantResponse, err := c.backendAPI.GetCustomerGUID(customerGUID) if err == nil && tenantResponse != nil { if tenantResponse.AdminMail != "" { // this customer already belongs to some user - c.configObj.CustomerAdminEMail = tenantResponse.AdminMail + c.setCustomerAdminEMail(tenantResponse.AdminMail) } else { - c.configObj.Token = tenantResponse.Token - c.configObj.CustomerGUID = tenantResponse.TenantID + c.setToken(tenantResponse.Token) + c.setCustomerGUID(tenantResponse.TenantID) } } else { if err != nil && !strings.Contains(err.Error(), "already exists") { @@ -198,15 +225,28 @@ func (c *ClusterConfig) SetCustomerGUID(customerGUID string) error { } else { c.createConfigMap() } - if existsConfigFile() { - c.updateConfigFile() - } else { - c.createConfigFile() - } + c.updateConfigFile() return nil } +func (c *ClusterConfig) setToken(token string) { + c.configObj.Token = token +} + +func (c *ClusterConfig) setCustomerAdminEMail(customerAdminEMail string) { + c.configObj.CustomerAdminEMail = customerAdminEMail +} +func (c *ClusterConfig) setCustomerGUID(customerGUID string) { + c.configObj.CustomerGUID = customerGUID +} + +func (c *ClusterConfig) setClusterName(clusterName string) { + c.configObj.ClusterName = clusterName +} +func (c *ClusterConfig) GetClusterName() string { + return c.configObj.ClusterName +} func (c *ClusterConfig) LoadConfig() { // get from configMap if c.existsConfigMap() { @@ -220,8 +260,9 @@ func (c *ClusterConfig) LoadConfig() { func (c *ClusterConfig) ToMapString() map[string]interface{} { m := map[string]interface{}{} - bc, _ := json.Marshal(c.configObj) - json.Unmarshal(bc, &m) + if bc, err := json.Marshal(c.configObj); err == nil { + json.Unmarshal(bc, &m) + } return m } func (c *ClusterConfig) loadConfigFromConfigMap() (*ConfigObj, error) { @@ -360,14 +401,7 @@ func (c *ClusterConfig) updateConfigMap() error { } func (c *ClusterConfig) updateConfigFile() error { - if err := os.WriteFile(ConfigFileFullPath(), c.configObj.Json(), 0664); err != nil { - return err - } - return nil -} - -func (c *ClusterConfig) createConfigFile() error { - if err := os.WriteFile(ConfigFileFullPath(), c.configObj.Json(), 0664); err != nil { + if err := os.WriteFile(ConfigFileFullPath(), c.configObj.Config(), 0664); err != nil { return err } return nil diff --git a/cmd/framework.go b/cmd/framework.go index c24a4fdf..954ef634 100644 --- a/cmd/framework.go +++ b/cmd/framework.go @@ -120,12 +120,12 @@ func CliSetup() error { // policy handler setup policyHandler := policyhandler.NewPolicyHandler(&processNotification, k8s) - if err := clusterConfig.SetCustomerGUID(scanInfo.Account); err != nil { + if err := clusterConfig.SetConfig(scanInfo.Account); err != nil { fmt.Println(err) } + cautils.ClusterName = clusterConfig.GetClusterName() cautils.CustomerGUID = clusterConfig.GetCustomerGUID() - cautils.ClusterName = k8sinterface.GetClusterName() // cli handler setup go func() { From 8778d022cf35654b70cbd7b095da2a5c41ca905a Mon Sep 17 00:00:00 2001 From: Avner Tzur Date: Wed, 20 Oct 2021 10:59:30 +0300 Subject: [PATCH 26/37] add cronjob sample for kubescape --- examples/cronjob/ks-cronjob.yaml | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 examples/cronjob/ks-cronjob.yaml diff --git a/examples/cronjob/ks-cronjob.yaml b/examples/cronjob/ks-cronjob.yaml new file mode 100644 index 00000000..49f46efe --- /dev/null +++ b/examples/cronjob/ks-cronjob.yaml @@ -0,0 +1,126 @@ +--- +# ------------------- Kubescape Service Account ------------------- # +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: kubescape + name: kubescape-discovery + namespace: kubescape + +--- +# ------------------- Kubescape Role & Role Binding ------------------- # +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kubescape-discovery-role + namespace: kubescape +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["get", "list", "describe"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kubescape-discovery-binding + namespace: kubescape +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubescape-discovery-role +subjects: +- kind: ServiceAccount + name: kubescape-discovery + +--- +# ------------------- Kubescape Cluster Role & Cluster Role Binding ------------------- # +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kubescape-discovery-clusterroles + # "namespace" omitted since ClusterRoles are not namespaced +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["get", "list", "describe"] + +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kubescape-discovery-role-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubescape-discovery-clusterroles +subjects: +- kind: ServiceAccount + name: kubescape-discovery + namespace: kubescape + +--- +# ------------------- Kubescape User/Customer GUID ------------------- # +kind: ConfigMap +apiVersion: v1 +metadata: + name: kubescape-configmap + labels: + app: kubescape + namespace: kubescape +data: + config.json: | + { + "adminMail": "", + "customerGUID": "", + "clusterName": "", + "invitationParam": "" + } + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: kubescape + labels: + app: kubescape + namespace: kubescape +spec: + # ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ timezone (optional) + # | ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ minute (0 - 59) + # | │ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ hour (0 - 23) + # | │ │ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ day of the month (1 - 31) + # | │ │ │ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ month (1 - 12) + # | │ │ │ │ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ day of the week (0 - 6) (Sunday to Saturday; + # | │ │ │ │ │ 7 is also Sunday on some systems) + # | │ │ │ │ │ + # | │ │ │ │ │ + # CRON_TZ=UTC * * * * * + schedule: "0 0 1 * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: kubescape + image: quay.io/armosec/kubescape:latset + imagePullPolicy: IfNotPresent + command: ["/bin/sh","-c"] + args: + - kubescape scan framework nsa --exclude-namespaces kube-system,kube-public + #- kubescape scan framework nsa --use-default --exclude-namespaces kube-system,kube-public + volumeMounts: + - name: kubescape-config-volume + mountPath: /root/.kubescape/config.json + subPath: config.json + restartPolicy: OnFailure + serviceAccountName: kubescape-discovery + volumes: + - name: kubescape-config-volume + configMap: + name: kubescape-configmap + +--- + + From b036d1079e313348eec533de166214e6df9228e3 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 14:15:27 +0300 Subject: [PATCH 27/37] support control scan with new api --- cautils/customerloader.go | 8 ++- cautils/getter/downloadreleasedpolicy.go | 76 +++++------------------- cautils/getter/getpolicies.go | 1 + cautils/getter/loadpolicy.go | 4 +- clihandler/cmd/control.go | 2 +- clihandler/cmd/scan.go | 1 - go.mod | 2 +- go.sum | 10 +++- policyhandler/handlepullpolicies.go | 16 +---- 9 files changed, 38 insertions(+), 82 deletions(-) diff --git a/cautils/customerloader.go b/cautils/customerloader.go index 8e723b20..1a839b97 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -127,7 +127,13 @@ func (c *EmptyConfig) GetCustomerGUID() string { return "" } func (c *EmptyConfig) GetK8sAPI() *k8sinterface.KubernetesApi { return nil } // TODO: return mock obj func (c *EmptyConfig) GetDefaultNS() string { return k8sinterface.GetDefaultNamespace() } func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj -func (c *EmptyConfig) GetClusterName() string { return "unknown" } +func (c *EmptyConfig) GetClusterName() string { + clusterName := k8sinterface.GetClusterName() + if clusterName == "" { + return "unknown" + } + return k8sinterface.GetClusterName() +} func (c *EmptyConfig) GenerateURL() { message := fmt.Sprintf("You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s", getter.GetArmoAPIConnector().GetFrontendURL()) InfoTextDisplay(os.Stdout, message+"\n") diff --git a/cautils/getter/downloadreleasedpolicy.go b/cautils/getter/downloadreleasedpolicy.go index 713704e7..70484420 100644 --- a/cautils/getter/downloadreleasedpolicy.go +++ b/cautils/getter/downloadreleasedpolicy.go @@ -1,12 +1,7 @@ package getter import ( - "encoding/json" - "fmt" - "io" - "net/http" - "time" - + "github.com/armosec/opa-utils/gitregostore" "github.com/armosec/opa-utils/reporthandling" ) @@ -16,71 +11,30 @@ import ( // Download released version type DownloadReleasedPolicy struct { - hostURL string - httpClient *http.Client + gs *gitregostore.GitRegoStore } func NewDownloadReleasedPolicy() *DownloadReleasedPolicy { return &DownloadReleasedPolicy{ - hostURL: "", - httpClient: &http.Client{Timeout: 61 * time.Second}, + gs: gitregostore.InitDefaultGitRegoStore(), } } +func (drp *DownloadReleasedPolicy) GetControl(policyName string) (*reporthandling.Control, error) { + control, err := drp.gs.GetOPAControlByName(policyName) + if err != nil { + control, err = drp.gs.GetOPAControlByID(policyName) + if err != nil { + return nil, err + } + } + return control, nil +} + func (drp *DownloadReleasedPolicy) GetFramework(name string) (*reporthandling.Framework, error) { - if err := drp.setURL(name); err != nil { - return nil, err - } - respStr, err := HttpGetter(drp.httpClient, drp.hostURL) + framework, err := drp.gs.GetOPAFrameworkByName(name) if err != nil { return nil, err } - - framework := &reporthandling.Framework{} - if err = JSONDecoder(respStr).Decode(framework); err != nil { - return framework, err - } - - SaveFrameworkInFile(framework, GetDefaultPath(name+".json")) return framework, err } - -func (drp *DownloadReleasedPolicy) setURL(frameworkName string) error { - - latestReleases := "https://api.github.com/repos/armosec/regolibrary/releases/latest" - resp, err := http.Get(latestReleases) - if err != nil { - return fmt.Errorf("failed to get latest releases from '%s', reason: %s", latestReleases, err.Error()) - } - defer resp.Body.Close() - if resp.StatusCode < 200 || 301 < resp.StatusCode { - return fmt.Errorf("failed to download file, status code: %s", resp.Status) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed to read response body from '%s', reason: %s", latestReleases, err.Error()) - } - var data map[string]interface{} - err = json.Unmarshal(body, &data) - if err != nil { - return fmt.Errorf("failed to unmarshal response body from '%s', reason: %s", latestReleases, err.Error()) - } - - if assets, ok := data["assets"].([]interface{}); ok { - for i := range assets { - if asset, ok := assets[i].(map[string]interface{}); ok { - if name, ok := asset["name"].(string); ok { - if name == frameworkName { - if url, ok := asset["browser_download_url"].(string); ok { - drp.hostURL = url - return nil - } - } - } - } - } - } - return fmt.Errorf("failed to download '%s' - not found", frameworkName) - -} diff --git a/cautils/getter/getpolicies.go b/cautils/getter/getpolicies.go index 3345334c..6d496d78 100644 --- a/cautils/getter/getpolicies.go +++ b/cautils/getter/getpolicies.go @@ -7,6 +7,7 @@ import ( type IPolicyGetter interface { GetFramework(name string) (*reporthandling.Framework, error) + GetControl(policyName string) (*reporthandling.Control, error) } type IExceptionsGetter interface { diff --git a/cautils/getter/loadpolicy.go b/cautils/getter/loadpolicy.go index 3c7054f0..e8658ab2 100644 --- a/cautils/getter/loadpolicy.go +++ b/cautils/getter/loadpolicy.go @@ -26,10 +26,10 @@ func NewLoadPolicy(filePath string) *LoadPolicy { } } -func (lp *LoadPolicy) GetControl(controlName string, controlPath string) (*reporthandling.Control, error) { +func (lp *LoadPolicy) GetControl(controlName string) (*reporthandling.Control, error) { control := &reporthandling.Control{} - f, err := os.ReadFile(controlPath) + f, err := os.ReadFile(lp.filePath) if err != nil { return nil, err } diff --git a/clihandler/cmd/control.go b/clihandler/cmd/control.go index dd018a46..f98f75c6 100644 --- a/clihandler/cmd/control.go +++ b/clihandler/cmd/control.go @@ -12,7 +12,7 @@ import ( // controlCmd represents the control command var controlCmd = &cobra.Command{ - Use: fmt.Sprint("control "), + Use: "control /", Short: fmt.Sprintf("The control you wish to use for scan. It must be present in at least one of the folloiwng frameworks: %s", clihandler.ValidFrameworks), Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index dd4345e3..cb75dfb2 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -18,7 +18,6 @@ var scanCmd = &cobra.Command{ func init() { rootCmd.AddCommand(scanCmd) - scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system, kube-public") scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer"/"json"/"junit"`) scanCmd.PersistentFlags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout") diff --git a/go.mod b/go.mod index e1f577a3..55149e38 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,6 @@ require ( require ( github.com/armosec/armoapi-go v0.0.7 github.com/armosec/k8s-interface v0.0.5 - github.com/armosec/opa-utils v0.0.9 + github.com/armosec/opa-utils v0.0.11 github.com/armosec/utils-go v0.0.3 ) diff --git a/go.sum b/go.sum index 5f496219..088abb4a 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/armosec/armoapi-go v0.0.7 h1:SN13+iYrIkxgatU+MwuWnSlhxP1G7rZP7dC8us2I github.com/armosec/armoapi-go v0.0.7/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.5 h1:DWQXZNMSsYQeLQ6xpB21ueFMR9oFnz28iWQTNn31TAk= github.com/armosec/k8s-interface v0.0.5/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= -github.com/armosec/opa-utils v0.0.9 h1:t7BKv7k/YL+7bkklW641eM5o8FoFO2TrQZMQrgx3O4g= -github.com/armosec/opa-utils v0.0.9/go.mod h1:E0mFTVx+4BYAVvO2hxWnIniv/IZIogRCak8BkKd7KK4= +github.com/armosec/opa-utils v0.0.11 h1:MeV3JDKkeKQa37w1QIUFngbWPNEzXke3OphvmYNDOQU= +github.com/armosec/opa-utils v0.0.11/go.mod h1:E0mFTVx+4BYAVvO2hxWnIniv/IZIogRCak8BkKd7KK4= github.com/armosec/utils-go v0.0.2/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= github.com/armosec/utils-go v0.0.3 h1:uyQI676yRciQM0sSN9uPoqHkbspTxHO0kmzXhBeE/xU= github.com/armosec/utils-go v0.0.3/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= @@ -98,6 +98,7 @@ github.com/armosec/utils-k8s-go v0.0.1/go.mod h1:qrU4pmY2iZsOb39Eltpm0sTTNM3E4pm github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.41.1/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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= @@ -213,6 +214,7 @@ github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmn 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-gota/gota v0.12.0 h1:T5BDg1hTf5fZ/CO+T/N0E+DDqUhvoKBl+UVckgcAAQg= github.com/go-gota/gota v0.12.0/go.mod h1:UT+NsWpZC/FhaOyWb9Hui0jXg0Iq8e/YugZHTbyW/34= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -655,6 +657,7 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= @@ -693,6 +696,7 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 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 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -970,7 +974,9 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.1 h1:HCWmqqNoELL0RAQeKBXWtkp04mGk8koafcB4He6+uhc= gonum.org/v1/gonum v0.9.1/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= diff --git a/policyhandler/handlepullpolicies.go b/policyhandler/handlepullpolicies.go index 90ec3ddc..1410e879 100644 --- a/policyhandler/handlepullpolicies.go +++ b/policyhandler/handlepullpolicies.go @@ -13,7 +13,6 @@ func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *reporth var errs error frameworks := []reporthandling.Framework{} exceptionPolicies := []armotypes.PostureExceptionPolicy{} - // Get - cacli opa get for _, rule := range notification.Rules { switch rule.Kind { @@ -71,21 +70,12 @@ func (policyHandler *PolicyHandler) getFrameworkPolicies(policyName string) (*re func (policyHandler *PolicyHandler) getControl(policyName string) ([]reporthandling.Control, []armotypes.PostureExceptionPolicy, error) { - // get all frameworks - frameworks := []reporthandling.Framework{} controls := []reporthandling.Control{} - for i := range supportedFrameworks { - // TODO : implement getControl in policygetter - framework, err := policyHandler.getters.PolicyGetter.GetFramework(supportedFrameworks[i].Name) - if err != nil { - return nil, nil, err - } - if framework != nil { - frameworks = append(frameworks, *framework) - } + control, err := policyHandler.getters.PolicyGetter.GetControl(policyName) + if err != nil { + return nil, nil, err } - control := findControlInFrameworks(frameworks, policyName) if control == nil { return nil, nil, fmt.Errorf("control not found") } From 836211ae2be529235d164d11ba90bab7098e909e Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 14:39:33 +0300 Subject: [PATCH 28/37] update go mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 55149e38..f81202ed 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,6 @@ require ( require ( github.com/armosec/armoapi-go v0.0.7 github.com/armosec/k8s-interface v0.0.5 - github.com/armosec/opa-utils v0.0.11 + github.com/armosec/opa-utils v0.0.12 github.com/armosec/utils-go v0.0.3 ) diff --git a/go.sum b/go.sum index 088abb4a..77cb2553 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/armosec/armoapi-go v0.0.7 h1:SN13+iYrIkxgatU+MwuWnSlhxP1G7rZP7dC8us2I github.com/armosec/armoapi-go v0.0.7/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.5 h1:DWQXZNMSsYQeLQ6xpB21ueFMR9oFnz28iWQTNn31TAk= github.com/armosec/k8s-interface v0.0.5/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= -github.com/armosec/opa-utils v0.0.11 h1:MeV3JDKkeKQa37w1QIUFngbWPNEzXke3OphvmYNDOQU= -github.com/armosec/opa-utils v0.0.11/go.mod h1:E0mFTVx+4BYAVvO2hxWnIniv/IZIogRCak8BkKd7KK4= +github.com/armosec/opa-utils v0.0.12 h1:X8D1yGzJMVZQyz/oiGyA9sSI4aGqw5uad1SjrTRZfR0= +github.com/armosec/opa-utils v0.0.12/go.mod h1:E0mFTVx+4BYAVvO2hxWnIniv/IZIogRCak8BkKd7KK4= github.com/armosec/utils-go v0.0.2/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= github.com/armosec/utils-go v0.0.3 h1:uyQI676yRciQM0sSN9uPoqHkbspTxHO0kmzXhBeE/xU= github.com/armosec/utils-go v0.0.3/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= From 11d4926c8551109d0808df1147b3f5a4704f6183 Mon Sep 17 00:00:00 2001 From: dwertent Date: Wed, 20 Oct 2021 14:49:27 +0300 Subject: [PATCH 29/37] updte junit results --- cautils/customerloader.go | 6 +++--- resultshandling/printer/junit.go | 21 +++++++++++++++++---- resultshandling/printer/printresults.go | 6 +++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/cautils/customerloader.go b/cautils/customerloader.go index 8e723b20..c0f5ea5d 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -129,8 +129,8 @@ func (c *EmptyConfig) GetDefaultNS() string { return k8sinterf func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj func (c *EmptyConfig) GetClusterName() string { return "unknown" } func (c *EmptyConfig) GenerateURL() { - message := fmt.Sprintf("You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s", getter.GetArmoAPIConnector().GetFrontendURL()) - InfoTextDisplay(os.Stdout, message+"\n") + message := fmt.Sprintf("\nCheckout for more cool features: https://%s\n", getter.GetArmoAPIConnector().GetFrontendURL()) + InfoTextDisplay(os.Stdout, fmt.Sprintf("\n%s\n", message)) } // ====================================================================================== @@ -165,7 +165,7 @@ func (c *ClusterConfig) GenerateURL() { if c.configObj == nil { return } - message := fmt.Sprintf("You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: %s", u.String()) + message := fmt.Sprintf("\nCheckout for more cool features: https://%s\n", getter.GetArmoAPIConnector().GetFrontendURL()) if c.configObj.CustomerAdminEMail != "" { InfoTextDisplay(os.Stdout, message+"\n") return diff --git a/resultshandling/printer/junit.go b/resultshandling/printer/junit.go index d3b15c38..370a5d0a 100644 --- a/resultshandling/printer/junit.go +++ b/resultshandling/printer/junit.go @@ -17,9 +17,11 @@ type JUnitTestSuites struct { type JUnitTestSuite struct { XMLName xml.Name `xml:"testsuite"` Tests int `xml:"tests,attr"` - Failures int `xml:"failures,attr"` Time string `xml:"time,attr"` Name string `xml:"name,attr"` + Resources int `xml:"resources,attr"` + Excluded int `xml:"excluded,attr"` + Failed int `xml:"filed,attr"` Properties []JUnitProperty `xml:"properties>property,omitempty"` TestCases []JUnitTestCase `xml:"testcase"` } @@ -30,6 +32,9 @@ type JUnitTestCase struct { Classname string `xml:"classname,attr"` Name string `xml:"name,attr"` Time string `xml:"time,attr"` + Resources int `xml:"resources,attr"` + Excluded int `xml:"excluded,attr"` + Failed int `xml:"filed,attr"` SkipMessage *JUnitSkipMessage `xml:"skipped,omitempty"` Failure *JUnitFailure `xml:"failure,omitempty"` } @@ -55,7 +60,12 @@ type JUnitFailure struct { func convertPostureReportToJunitResult(postureResult *reporthandling.PostureReport) (*JUnitTestSuites, error) { juResult := JUnitTestSuites{XMLName: xml.Name{Local: "Kubescape scan results"}} for _, framework := range postureResult.FrameworkReports { - suite := JUnitTestSuite{Name: framework.Name} + suite := JUnitTestSuite{ + Name: framework.Name, + Resources: framework.GetNumberOfResources(), + Excluded: framework.GetNumberOfWarningResources(), + Failed: framework.GetNumberOfFailedResources(), + } for _, controlReports := range framework.ControlReports { suite.Tests = suite.Tests + 1 testCase := JUnitTestCase{} @@ -63,9 +73,12 @@ func convertPostureReportToJunitResult(postureResult *reporthandling.PostureRepo testCase.Classname = "Kubescape" testCase.Time = "0" if 0 < len(controlReports.RuleReports[0].RuleResponses) { - suite.Failures = suite.Failures + 1 + + testCase.Resources = framework.GetNumberOfResources() + testCase.Excluded = framework.GetNumberOfWarningResources() + testCase.Failed = framework.GetNumberOfFailedResources() failure := JUnitFailure{} - failure.Message = fmt.Sprintf("%d resources failed", len(controlReports.RuleReports[0].RuleResponses)) + failure.Message = fmt.Sprintf("%d resources failed", testCase.Failed) for _, ruleResponses := range controlReports.RuleReports[0].RuleResponses { failure.Contents = fmt.Sprintf("%s\n%s", failure.Contents, ruleResponses.AlertMessage) } diff --git a/resultshandling/printer/printresults.go b/resultshandling/printer/printresults.go index 97602e05..2a718e4c 100644 --- a/resultshandling/printer/printresults.go +++ b/resultshandling/printer/printresults.go @@ -54,7 +54,7 @@ func calculatePostureScore(postureReport *reporthandling.PostureReport) float32 } func (printer *Printer) ActionPrint(opaSessionObj *cautils.OPASessionObj) float32 { - var score float32 + score := calculatePostureScore(opaSessionObj.PostureReport) if printer.printerType == PrettyPrinter { printer.SummarySetup(opaSessionObj.PostureReport) @@ -67,6 +67,7 @@ func (printer *Printer) ActionPrint(opaSessionObj *cautils.OPASessionObj) float3 os.Exit(1) } printer.writer.Write(postureReportStr) + fmt.Printf("\nFinal score: %d\n", int(score*100)) } else if printer.printerType == JunitResultPrinter { junitResult, err := convertPostureReportToJunitResult(opaSessionObj.PostureReport) if err != nil { @@ -79,13 +80,12 @@ func (printer *Printer) ActionPrint(opaSessionObj *cautils.OPASessionObj) float3 os.Exit(1) } printer.writer.Write(postureReportStr) + fmt.Printf("\nFinal score: %d\n", int(score*100)) } else if !cautils.IsSilent() { fmt.Println("unknown output printer") os.Exit(1) } - score = calculatePostureScore(opaSessionObj.PostureReport) - return score } From 9cb937798f1b2696e57f90edc1b4a6c19d4a887c Mon Sep 17 00:00:00 2001 From: dwertent Date: Wed, 20 Oct 2021 14:53:19 +0300 Subject: [PATCH 30/37] update readme --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5afce369..ff012afc 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,9 @@ curl -s https://raw.githubusercontent.com/armosec/kubescape/master/install.sh | ## Run: ``` -kubescape scan framework nsa --exclude-namespaces kube-system,kube-public +kubescape scan framework nsa ``` -If you wish to scan all namespaces in your cluster, remove the `--exclude-namespaces` flag. - ### Click [šŸ‘](https://github.com/armosec/kubescape/stargazers) if you want us to continue to develop and improve Kubescape šŸ˜€ @@ -86,15 +84,15 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser ### Examples -* Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/News-Features/Feature-Stories/Article-View/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework and submit results to [Armo portal](https://portal.armo.cloud/) +* Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/News-Features/Feature-Stories/Article-View/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework and submit results to [ARMO portal](https://portal.armo.cloud/) ``` -kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --submit +kubescape scan framework nsa --submit ``` -* Scan a running Kubernetes cluster with [`mitre`](https://www.microsoft.com/security/blog/2020/04/02/attack-matrix-kubernetes/) framework and submit results to [Armo portal](https://portal.armo.cloud/) +* Scan a running Kubernetes cluster with [`MITRE ATT&CKĀ®`](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) framework and submit results to [ARMO portal](https://portal.armo.cloud/) ``` -kubescape scan framework mitre --exclude-namespaces kube-system,kube-public --submit +kubescape scan framework mitre --submit ``` * Scan local `yaml`/`json` files before deploying. [Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI) @@ -187,7 +185,7 @@ go build -o kubescape . 3. Run ``` -./kubescape scan framework nsa --exclude-namespaces kube-system,kube-public +./kubescape scan framework nsa ``` 4. Enjoy :zany_face: From 093ee8916e130d4f60cdb1f4ab8ce8f38f090843 Mon Sep 17 00:00:00 2001 From: Bezalel Brandwine Date: Wed, 20 Oct 2021 16:04:10 +0300 Subject: [PATCH 31/37] Add API version to report structure --- go.mod | 2 +- go.sum | 42 +++++++++++++++++++++++++++++ policyhandler/handlenotification.go | 4 ++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 9bce8496..807831cc 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( require ( github.com/armosec/armoapi-go v0.0.7 github.com/armosec/k8s-interface v0.0.5 - github.com/armosec/opa-utils v0.0.7 + github.com/armosec/opa-utils v0.0.13 github.com/armosec/utils-go v0.0.3 ) diff --git a/go.sum b/go.sum index 07805434..8783e82d 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -70,6 +71,7 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -88,6 +90,8 @@ github.com/armosec/k8s-interface v0.0.5 h1:DWQXZNMSsYQeLQ6xpB21ueFMR9oFnz28iWQTN github.com/armosec/k8s-interface v0.0.5/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= github.com/armosec/opa-utils v0.0.7 h1:cafKzdQcCVqaOz6zNdne+wxNqajZFd6Ad2KJpHM3gF8= github.com/armosec/opa-utils v0.0.7/go.mod h1:fxPGsKEKOf0FDQVciKiCTZv4iibRkbld5lK1hyUyVcA= +github.com/armosec/opa-utils v0.0.13 h1:QkmmYX0lzC7ZNGetyD8ysRKQHgJhjMfvRUW2cp+hz2o= +github.com/armosec/opa-utils v0.0.13/go.mod h1:E0mFTVx+4BYAVvO2hxWnIniv/IZIogRCak8BkKd7KK4= github.com/armosec/utils-go v0.0.2/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= github.com/armosec/utils-go v0.0.3 h1:uyQI676yRciQM0sSN9uPoqHkbspTxHO0kmzXhBeE/xU= github.com/armosec/utils-go v0.0.3/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= @@ -104,6 +108,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/briandowns/spinner v1.16.0 h1:DFmp6hEaIx2QXXuqSJmtfSBSAjRmpGiKG6ip2Wm/yOs= github.com/briandowns/spinner v1.16.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= @@ -185,6 +190,8 @@ github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -201,12 +208,18 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= 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-gota/gota v0.12.0/go.mod h1:UT+NsWpZC/FhaOyWb9Hui0jXg0Iq8e/YugZHTbyW/34= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= 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= @@ -234,6 +247,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -375,6 +389,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X 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/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -472,6 +488,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= 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= @@ -514,6 +532,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -663,18 +682,29 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= 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-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= 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/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 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= @@ -745,6 +775,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -836,6 +867,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/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= @@ -870,11 +902,13 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190206041539-40960b6deb8e/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= @@ -889,6 +923,7 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190927191325-030b2cf1153e/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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -935,6 +970,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.1/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -1121,6 +1162,7 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2R k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 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/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go index 9da07cac..d0963f9b 100644 --- a/policyhandler/handlenotification.go +++ b/policyhandler/handlenotification.go @@ -51,7 +51,9 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *repo return fmt.Errorf("empty list of resources") } opaSessionObj.K8SResources = k8sResources - + if opaSessionObj.PostureReport.ClusterAPIServerInfo, err = policyHandler.k8s.KubernetesClient.Discovery().ServerVersion(); err != nil { + cautils.ErrorDisplay(fmt.Sprintf("Failed to discover API server inforamtion: %v", err)) + } // update channel *policyHandler.processPolicy <- opaSessionObj return nil From cc57a34a32c7ef205f972e27d7269dd9f2ae63be Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 16:18:53 +0300 Subject: [PATCH 32/37] run control scan form file --- cautils/customerloader.go | 8 +---- cautils/downloadinfo.go | 1 + cautils/getter/downloadreleasedpolicy.go | 15 +++++--- cautils/getter/getpoliciesutils.go | 24 +++++++++++++ cautils/getter/loadpolicy.go | 2 +- cautils/scaninfo.go | 1 - clihandler/cmd/control.go | 12 ++++--- clihandler/cmd/download.go | 46 ++++++++++++++++-------- clihandler/cmd/scan.go | 2 +- install.sh | 2 +- nsa.json | 1 - resultshandling/results.go | 2 +- 12 files changed, 79 insertions(+), 37 deletions(-) delete mode 100644 nsa.json diff --git a/cautils/customerloader.go b/cautils/customerloader.go index 1a839b97..1ff94840 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -127,13 +127,7 @@ func (c *EmptyConfig) GetCustomerGUID() string { return "" } func (c *EmptyConfig) GetK8sAPI() *k8sinterface.KubernetesApi { return nil } // TODO: return mock obj func (c *EmptyConfig) GetDefaultNS() string { return k8sinterface.GetDefaultNamespace() } func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj -func (c *EmptyConfig) GetClusterName() string { - clusterName := k8sinterface.GetClusterName() - if clusterName == "" { - return "unknown" - } - return k8sinterface.GetClusterName() -} +func (c *EmptyConfig) GetClusterName() string { return k8sinterface.GetClusterName() } func (c *EmptyConfig) GenerateURL() { message := fmt.Sprintf("You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s", getter.GetArmoAPIConnector().GetFrontendURL()) InfoTextDisplay(os.Stdout, message+"\n") diff --git a/cautils/downloadinfo.go b/cautils/downloadinfo.go index 7136be43..c54601eb 100644 --- a/cautils/downloadinfo.go +++ b/cautils/downloadinfo.go @@ -3,4 +3,5 @@ package cautils type DownloadInfo struct { Path string FrameworkName string + ControlName string } diff --git a/cautils/getter/downloadreleasedpolicy.go b/cautils/getter/downloadreleasedpolicy.go index 70484420..028597ff 100644 --- a/cautils/getter/downloadreleasedpolicy.go +++ b/cautils/getter/downloadreleasedpolicy.go @@ -1,6 +1,8 @@ package getter import ( + "strings" + "github.com/armosec/opa-utils/gitregostore" "github.com/armosec/opa-utils/reporthandling" ) @@ -21,12 +23,15 @@ func NewDownloadReleasedPolicy() *DownloadReleasedPolicy { } func (drp *DownloadReleasedPolicy) GetControl(policyName string) (*reporthandling.Control, error) { - control, err := drp.gs.GetOPAControlByName(policyName) - if err != nil { + var control *reporthandling.Control + var err error + if strings.HasPrefix(policyName, "C-") || strings.HasPrefix(policyName, "c-") { control, err = drp.gs.GetOPAControlByID(policyName) - if err != nil { - return nil, err - } + } else { + control, err = drp.gs.GetOPAControlByName(policyName) + } + if err != nil { + return nil, err } return control, nil } diff --git a/cautils/getter/getpoliciesutils.go b/cautils/getter/getpoliciesutils.go index af367a3d..55a4bc2d 100644 --- a/cautils/getter/getpoliciesutils.go +++ b/cautils/getter/getpoliciesutils.go @@ -21,6 +21,30 @@ func GetDefaultPath(name string) string { return defaultfilePath } +func SaveControlInFile(control *reporthandling.Control, pathStr string) error { + encodedData, err := json.Marshal(control) + if err != nil { + return err + } + err = os.WriteFile(pathStr, []byte(fmt.Sprintf("%v", string(encodedData))), 0644) + if err != nil { + if os.IsNotExist(err) { + pathDir := path.Dir(pathStr) + if err := os.Mkdir(pathDir, 0744); err != nil { + return err + } + } else { + return err + + } + err = os.WriteFile(pathStr, []byte(fmt.Sprintf("%v", string(encodedData))), 0644) + if err != nil { + return err + } + } + return nil +} + func SaveFrameworkInFile(framework *reporthandling.Framework, pathStr string) error { encodedData, err := json.Marshal(framework) if err != nil { diff --git a/cautils/getter/loadpolicy.go b/cautils/getter/loadpolicy.go index e8658ab2..f0553f45 100644 --- a/cautils/getter/loadpolicy.go +++ b/cautils/getter/loadpolicy.go @@ -35,7 +35,7 @@ func (lp *LoadPolicy) GetControl(controlName string) (*reporthandling.Control, e } err = json.Unmarshal(f, control) - if controlName != "" && !strings.EqualFold(controlName, control.Name) { + if controlName != "" && !strings.EqualFold(controlName, control.Name) && !strings.EqualFold(controlName, control.ControlID) { return nil, fmt.Errorf("control from file not matching") } return control, err diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index a0e58b62..8ca73ca6 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -55,7 +55,6 @@ func (scanInfo *ScanInfo) setUseFrom() { if scanInfo.UseDefault { scanInfo.UseFrom = getter.GetDefaultPath(scanInfo.PolicyIdentifier.Name + ".json") } - } func (scanInfo *ScanInfo) setGetter() { if scanInfo.UseFrom != "" { diff --git a/clihandler/cmd/control.go b/clihandler/cmd/control.go index f98f75c6..0618e0c4 100644 --- a/clihandler/cmd/control.go +++ b/clihandler/cmd/control.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "os" + "strings" "github.com/armosec/kubescape/cautils" "github.com/armosec/kubescape/clihandler" @@ -15,18 +16,19 @@ var controlCmd = &cobra.Command{ Use: "control /", Short: fmt.Sprintf("The control you wish to use for scan. It must be present in at least one of the folloiwng frameworks: %s", clihandler.ValidFrameworks), Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return fmt.Errorf("requires one argument") + if len(args) < 1 && !(cmd.Flags().Lookup("use-from").Changed) { + return fmt.Errorf("requires at least one argument") } - return nil }, RunE: func(cmd *cobra.Command, args []string) error { flagValidationControl() - scanInfo.FrameworkScan = false scanInfo.PolicyIdentifier = reporthandling.PolicyIdentifier{} + if !(cmd.Flags().Lookup("use-from").Changed) { + scanInfo.PolicyIdentifier.Name = strings.ToLower(args[0]) + } + scanInfo.FrameworkScan = false scanInfo.PolicyIdentifier.Kind = reporthandling.KindControl - scanInfo.PolicyIdentifier.Name = args[0] scanInfo.Init() cautils.SetSilentMode(scanInfo.Silent) err := clihandler.CliSetup(scanInfo) diff --git a/clihandler/cmd/download.go b/clihandler/cmd/download.go index 24c01669..ced71411 100644 --- a/clihandler/cmd/download.go +++ b/clihandler/cmd/download.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "strings" "github.com/armosec/kubescape/cautils" "github.com/armosec/kubescape/cautils/getter" @@ -12,8 +13,8 @@ import ( var downloadInfo cautils.DownloadInfo var downloadCmd = &cobra.Command{ - Use: fmt.Sprintf("download framework [flags]\nSupported frameworks: %s", clihandler.ValidFrameworks), - Short: "Download framework controls", + Use: fmt.Sprintf("download framework/control / [flags]\nSupported frameworks: %s", clihandler.ValidFrameworks), + Short: "Download framework/control", Long: ``, Args: func(cmd *cobra.Command, args []string) error { if len(args) != 2 { @@ -22,19 +23,36 @@ var downloadCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { - downloadInfo.FrameworkName = args[1] - g := getter.NewDownloadReleasedPolicy() - if downloadInfo.Path == "" { - downloadInfo.Path = getter.GetDefaultPath(downloadInfo.FrameworkName + ".json") - } - frameworks, err := g.GetFramework(downloadInfo.FrameworkName) - if err != nil { - return err - } - err = getter.SaveFrameworkInFile(frameworks, downloadInfo.Path) - if err != nil { - return err + if strings.EqualFold(args[0], "framework") { + downloadInfo.FrameworkName = args[1] + g := getter.NewDownloadReleasedPolicy() + if downloadInfo.Path == "" { + downloadInfo.Path = getter.GetDefaultPath(downloadInfo.FrameworkName + ".json") + } + frameworks, err := g.GetFramework(downloadInfo.FrameworkName) + if err != nil { + return err + } + err = getter.SaveFrameworkInFile(frameworks, downloadInfo.Path) + if err != nil { + return err + } + } else if strings.EqualFold(args[0], "control") { + downloadInfo.ControlName = args[1] + g := getter.NewDownloadReleasedPolicy() + if downloadInfo.Path == "" { + downloadInfo.Path = getter.GetDefaultPath(downloadInfo.ControlName + ".json") + } + controls, err := g.GetControl(downloadInfo.ControlName) + if err != nil { + return err + } + err = getter.SaveControlInFile(controls, downloadInfo.Path) + if err != nil { + return err + } } + return nil }, } diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index cb75dfb2..13d2da22 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -9,7 +9,7 @@ var scanInfo cautils.ScanInfo // scanCmd represents the scan command var scanCmd = &cobra.Command{ - Use: "scan", + Use: "scan ", Short: "Scan the current running cluster or yaml files", Long: `The action you want to perform`, Run: func(cmd *cobra.Command, args []string) { diff --git a/install.sh b/install.sh index c9cc5ceb..2d0173bd 100755 --- a/install.sh +++ b/install.sh @@ -53,6 +53,6 @@ echo -e "\033[0m" $KUBESCAPE_EXEC version echo -echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan framework nsa --exclude-namespaces kube-system,kube-public" +echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan framework nsa" echo -e "\033[0m" diff --git a/nsa.json b/nsa.json deleted file mode 100644 index b8e70c21..00000000 --- a/nsa.json +++ /dev/null @@ -1 +0,0 @@ -{"guid":"","name":"NSA","attributes":{"armoBuiltin":true},"creationTime":"","description":"Implement NSA security advices for K8s ","controls":[{"guid":"","name":"Control plane hardening","attributes":{"armoBuiltin":true},"id":"C-0005","controlID":"C-0005","creationTime":"","description":"Kubernetes control plane API is running with non-secure port enabled which allows attackers to gain unprotected access to the cluster.","remediation":"Set the insecure-port flag of the API server to zero.","rules":[{"guid":"","name":"insecure-port-flag","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\nimport data.cautils as cautils\n\n# Fails if pod has insecure-port flag enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n container := pod.spec.containers[_]\n\tisInsecurePortFlag(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The API server container: %v has insecure-port flag enabled\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has insecure-port flag enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isInsecurePortFlag(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The API server container: %v has insecure-port flag enabled\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\t\nisInsecurePortFlag(container){\n cautils.list_contains(container.command, \"--insecure-port=1\")\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if the api server has insecure-port enabled","remediation":"Make sure that the insecure-port flag of the api server is set to 0","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Host PID/IPC privileges","attributes":{"armoBuiltin":true},"id":"C-0038","controlID":"C-0038","creationTime":"","description":"Containers should be as isolated as possible from the host machine. The hostPID and hostIPC fields in Kubernetes may excessively expose the host to potentially malicious actions.","remediation":"Remove hostPID and hostIPC privileges unless they are absolutely necessary.","rules":[{"guid":"","name":"host-pid-ipc-privileges","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has hostPID enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tisHostPID(pod.spec)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has hostPID enabled\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if pod has hostIPC enabled\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tisHostIPC(pod.spec)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has hostIPC enabled\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has hostPID enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostPID(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod with hostPID enabled\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has hostIPC enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostIPC(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod with hostIPC enabled\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has hostPID enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostPID(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod with hostPID enabled\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has hostIPC enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostIPC(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod with hostIPC enabled\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Check that hostPID and hostIPC are set to false. Default is false. Only in pod spec\n\n\nisHostPID(podspec){\n podspec.hostPID == true\n}\n\nisHostIPC(podspec){\n podspec.hostIPC == true\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"Containers should be as isolated as possible from the host machine. The hostPID and hostIPC fields in Kubernetes may excessively expose the host to potentially malicious actions.","remediation":"Make sure that the fields hostIPC and hostPID in the pod spec are not set to true (set to false or not present)","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Immutable container filesystem","attributes":{"armoBuiltin":true},"id":"C-0017","controlID":"C-0017","creationTime":"","description":"Mutable container filesystem can be abused to inject malicious code or data into containers. Use immutable (read-only) filesystem to limit potential attacks.","remediation":"Set the filesystem of the container to read-only when possible (POD securityContext, readOnlyRootFilesystem: true). If containers application needs to write into the filesystem, it is recommended to mount secondary filesystems for specific directories where application require write access.","rules":[{"guid":"","name":"immutable-container-filesystem","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pods has container with mutable filesystem\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v has mutable filesystem\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has container with mutable filesystem \ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v has mutable filesystem\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has container with mutable filesystem \ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tisMutableFilesystem(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v has mutable filesystem\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Default of readOnlyRootFilesystem is false. This field is only in container spec and not pod spec\nisMutableFilesystem(container){\n not container.securityContext.readOnlyRootFilesystem\n }","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has mutable filesystem","remediation":"Make sure that the securityContext.readOnlyRootFilesystem field in the container/pod spec is set to true","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Non-root containers","attributes":{"armoBuiltin":true},"id":"C-0013","controlID":"C-0013","creationTime":"","description":"Potential attackers may gain access to a container and leverage its existing privileges to conduct an attack. Therefore, it is not recommended to deploy containers with root privileges unless it is absolutely necessary. This contol identifies all the Pods running as root or can escalate to root.","remediation":"If your application does not need root privileges, make sure to define the runAsUser or runAsGroup under the PodSecurityContext and use user ID 1000 or higher. Do not turn on allowPrivlegeEscalation bit and make sure runAsNonRoot is true.","rules":[{"guid":"","name":"non-root-containers","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container configured to run as root\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isRootContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v may run as root\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if pod has container configured to run as root\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isRootPod(pod, container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v may run as root\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isRootContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isRootPod(wl.spec.template, container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has a container configured to run as root\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\t isRootContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\n# Fails if workload has container configured to run as root\ndeny[msga] {\n \twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isRootPod(wl.spec.jobTemplate.spec.template, container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v may run as root\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\nisRootPod(pod, container) {\n not container.securityContext.runAsUser\n pod.spec.securityContext.runAsUser == 0\n}\n\nisRootPod(pod, container) {\n not container.securityContext.runAsUser\n\tnot container.securityContext.runAsGroup\n\tnot container.securityContext.runAsNonRoot\n not pod.spec.securityContext.runAsUser\n\tnot pod.spec.securityContext.runAsGroup\n pod.spec.securityContext.runAsNonRoot == false\n}\n\nisRootPod(pod, container) {\n not container.securityContext.runAsGroup\n pod.spec.securityContext.runAsGroup == 0\n}\n\nisRootPod(pod, container) {\n\tnot pod.spec.securityContext.runAsGroup\n\tnot pod.spec.securityContext.runAsUser\n \tcontainer.securityContext.runAsNonRoot == false\n}\n\nisRootContainer(container) {\n container.securityContext.runAsUser == 0\n}\n\nisRootContainer(container) {\n container.securityContext.runAsGroup == 0\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container can run as root","remediation":"Make sure that the user/group in the securityContext of pod/container is set to an id less than 1000, or the runAsNonRoot flag is set to true. Also make sure that the allowPrivilegeEscalation field is set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Privileged container","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Privilege escalation"]},"id":"C-0057","controlID":"C-0057","creationTime":"","description":"Potential attackers may gain access to privileged containers and inherit access to the host resources. Therefore, it is not recommended to deploy privileged containers unless it is absolutely necessary. This control identifies all the privileged Pods.","remediation":"Remove privileged capabilities by setting the securityContext.privileged to false. If you must deploy a Pod as privileged, add other restriction to it, such as network policy, Seccomp etc and still remove all unnecessary capabilities. Use the exception mechanism to remove unnecessary notifocations.","rules":[{"guid":"","name":"rule-privilege-escalation","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::privileged container","mitre":"Privilege Escalation","mitreCode":"TA0004"},"creationTime":"","rule":"package armo_builtins\n# Deny mutating action unless user is in group owning the resource\n\n\n#privileged pods\ndeny[msga] {\n\n\tpod := input[_]\n\tpod.kind == \"Pod\"\n\tcontainers := pod.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following pods are defined as privileged: %v\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n }\n}\n\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainers := wl.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v is defined as privileged:\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n#handles cronjob\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainers := wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following cronjobs are defined as privileged: %v\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 3,\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"determines if pods/deployments defined as privileged true","remediation":"avoid defining pods as privilleged","ruleQuery":""}]},{"guid":"","name":"Allowed hostPath","attributes":{"armoBuiltin":true},"id":"C-0006","controlID":"C-0006","creationTime":"","description":"Mounting host directory to the container can be abused to get access to sensitive data and gain persistence on the host machine.","remediation":"Refrain from using host path mount.","rules":[{"guid":"","name":"alert-rw-hostpath","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Persistance::Writable hostPath mount, Lateral Movement::Writable volume mounts on the host"},"creationTime":"","rule":"package armo_builtins\n\n# input: pod\n# apiversion: v1\n# does: returns hostPath volumes\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n volumes := pod.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := pod.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n podname := pod.metadata.name\n\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod: %v has: %v as hostPath volume\", [podname, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n volumes := wl.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := wl.spec.template.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t\n\t}\n}\n\n#handles CronJobs\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n volumes := wl.spec.jobTemplate.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tvolumeMount := container.volumeMounts[_]\n\tvolumeMount.name == volume.name\n\tisRWMount(volumeMount)\n\n \n\tmsga := {\n\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\"packagename\": \"armo_builtins\",\n\t\"alertScore\": 7,\n\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisRWMount(mount) {\n not mount.readOnly\n}\nisRWMount(mount) {\n mount.readOnly == false\n} ","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod"]}],"ruleDependencies":[{"packageName":"cautils"},{"packageName":"kubernetes.api.client"}],"description":"determines if any workload contains a hostPath volume with rw permissions","remediation":"Set the readOnly field of the mount to true","ruleQuery":""}]},{"guid":"","name":"Automatic mapping of service account","attributes":{"armoBuiltin":true},"id":"C-0034","controlID":"C-0034","creationTime":"","description":"Potential attacker may gain access to a POD and steal its service account token. Therefore, it is recommended to disable automatic mapping of the service account tokens in service account configuration and enable it only for PODs that need to use them.","remediation":"Disable automatic mounting of service account tokens to PODs either at the service account level or at the individual POD level, by specifying the automountServiceAccountToken: false. Note that POD level takes precedence.","rules":[{"guid":"","name":"automount-service-account","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n# Fails if user account mount tokens in pod by default.\ndeny [msga]{\n serviceaccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == \"ServiceAccount\"]\n serviceaccount := serviceaccounts[_]\n isAutoMount(serviceaccount)\n\n msga := {\n\t \"alertMessage\": sprintf(\"the following service account: %v in the following namespace: %v mounts service account tokens in pods by default\", [serviceaccount.metadata.name, serviceaccount.metadata.namespace]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [serviceaccount]\n\t\t}\n\t}\n} \n\nisAutoMount(serviceaccount) {\n\tnot serviceaccount.automountServiceAccountToken == false\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Serviceaccount"]}],"ruleDependencies":[],"description":"fails if service account automountServiceAccountToken enabled","remediation":"Make sure that the automountServiceAccountToken field on the service account spec if set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"hostNetwork access","attributes":{"armoBuiltin":true},"id":"C-0041","controlID":"C-0041","creationTime":"","description":"Potential attackers may gain access to a POD and inherit access to the entire host network. For example, in AWS case, they will have access to the entire VPC. This control identifies all the PODs with host network access enabled.","remediation":"Only connect PODs to host network when it is necessary. If not, set the hostNetwork field of the pod spec to false, or completely remove it (false is the default). Whitelist only those PODs that must have access to host network by design.","rules":[{"guid":"","name":"host-network-access","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n# Fails if pod has hostNetwork enabled\ndeny[msga] {\n pods := [ pod | pod = input[_] ; pod.kind == \"Pod\"]\n pod := pods[_]\n\n isHostNetwork(pod.spec)\n\n \tmsga := {\n\t\"alertMessage\": sprintf(\"Pod: %v is connected to the host network\", [pod.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has hostNetwork enabled\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tisHostNetwork(wl.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"%v: %v has a pod connected to the host network\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has hostNetwork enabled\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tisHostNetwork(wl.spec.jobTemplate.spec.template.spec)\n msga := {\n\t\"alertMessage\": sprintf(\"CronJob: %v has a pod connected to the host network\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisHostNetwork(podspec) {\n podspec.hostNetwork == true\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if pod has hostNetwork enabled","remediation":"Make sure that the hostNetwork field of the pod spec is not set to true (set to false or not present)","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Resource policies","attributes":{"armoBuiltin":true},"id":"C-0009","controlID":"C-0009","creationTime":"","description":"CPU and memory resources should have a limit set for every container to prevent resource exhaustion. This control identifies all the Pods without resource limit definition.","remediation":"Define LimitRange and ResourceQuota policies to limit resource usage for namespaces or nodes.","rules":[{"guid":"","name":"resource-policies","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Check if container has limits\ndeny[msga] {\n \tpods := [pod | pod = input[_]; pod.kind == \"Pod\"]\n pod := pods[_]\n\tcontainer := pod.spec.containers[_]\n\tnot container.resources.limits\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Check if container has limits - for workloads\n# If there is no limits specified in the workload, we check the namespace, since if limits are only specified for namespace\n# and not in workload, it won't be on the yaml\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n\tnot container.resources.limits\n\tisNamespaceWithLimits(wl.metadata.namespace)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n\t\n}\n\n# Check if container has limits - for cronjobs\n# If there is no limits specified in the cronjob, we check the namespace, since if limits are only specified for namespace\n# and not in cronjob, it won't be on the yaml\ndeny [msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tnot container.resources.limits\n\tisNamespaceWithLimits(wl.metadata.namespace)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"there are no resource limits defined for container : %v\", [container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if LimitRange exists but it does not define maximum usage of resources\ndeny[msga] {\n\n limitRanges := [limitRange | limitRange = input[_]; limitRange.kind == \"LimitRange\"]\n limitRange := limitRanges[_]\n\n\tlimits := limitRange.spec.limits[_]\n not limits.max\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following LimitRange: %v does not define a maximum field for resources\", [limitRange.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [limitRange]\n\t\t}\n\t}\n}\n\n# Fails if ResourQuota exists but it does not define maximum usage of resources\ndeny[msga] {\n resourceQuotas := [resourceQuota | resourceQuota = input[_]; resourceQuota.kind == \"ResourceQuota\"]\n resourceQuota := resourceQuotas[_]\n\n not resourceQuota.spec.hard\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following ResourQuota: %v does not define a hard field\", [resourceQuota.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [resourceQuota]\n\t\t}\n\t}\n}\n\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}\n\n\n# Check only LimitRange. For ResourceQuota limits need to be specified. \nisNamespaceWithLimits(namespace) {\n limitRanges := [policy.metadata.namespace | policy = input[_]; policy.kind == \"LimitRange\"]\n not list_contains(limitRanges, namespace)\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod","LimitRange","ResourceQuota"]}],"ruleDependencies":[],"description":"fails if namespace has no resource policies defined","remediation":"Make sure that you definy resource policies (LimitRange or ResourceQuota) which limit the usage of resources for all the namespaces","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Exposed dashboard","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Initial Access"]},"id":"C-0047","controlID":"C-0047","creationTime":"","description":"Kubernetes dashboard versions before v2.0.1 do not support user authentication. If exposed externally, it will allow unauthenticated remote management of the cluster. This control checks presence of the kubernetes-dashboard deployment and its version number.","remediation":"Update dashboard version to v2.0.1 and above.","rules":[{"guid":"","name":"rule-exposed-dashboard","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Initial Access::Exposed Dashboard"},"creationTime":"","rule":"package armo_builtins\n\n# input: pods\n# apiversion: v1\n# fails if dashboard exists and is exposed\n\ndeny[msga] {\n\tdeployment := input[_]\n startswith(deployment.metadata.name, \"kubernetes-dashboard\")\n container := deployment.spec.template.spec.containers[_]\n version := trim_prefix(container.image, \"kubernetesui/dashboard:v\")\n to_number(replace(version, \".\", \"\")) \u003c 201\n \n\tservice := input[_]\n\tservice.kind == \"Service\"\n\tisNodePortLbService(service)\n count({x | service.spec.selector[x]; deployment.metadata.labels[x]}) == count(service.spec.selector)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"dashboard exists and is exposed %s\", [container.image]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [deployment]\n\t\t}\n }\n}\n\n\n\nisNodePortLbService(service) {\n\tservice.spec.type == \"NodePort\"\n}\n\nisNodePortLbService(service) {\n\tservice.spec.type == \"LoadBalancer\"\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","Service"]}],"ruleDependencies":[],"description":"fails if dashboard exists and is exposed","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Allow privilege escalation","attributes":{"armoBuiltin":true},"id":"C-0016","controlID":"C-0016","creationTime":"","description":"Attackers may gain access to a container and uplift its privilege to enable excessive capabilities.","remediation":"If your application does not need it, make sure the allowPrivilegeEscalation field of the securityContext is set to false.","rules":[{"guid":"","name":"rule-allow-privilege-escalation","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container that allow privilege escalation\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isAllowPrivilegeEscalationContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v allow privilege escalation\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n\n# Fails if workload has a container that allow privilege escalation\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isAllowPrivilegeEscalationContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v allow privilege escalation\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if cronjob has a container that allow privilege escalation\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tisAllowPrivilegeEscalationContainer(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"container :%v in %v: %v allow privilege escalation\", [container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\nisAllowPrivilegeEscalationContainer(container) {\n container.securityContext.allowPrivilegeEscalation == true\n}\n\nisAllowPrivilegeEscalationContainer(container) {\n sysAdminCap := \"SYS_ADMIN\"\n contains(container.securityContext.capabilities.add[_], sysAdminCap)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container allows privilege escalation","remediation":"Make sure that the allowPrivilegeEscalation field in the securityContext of pod/container is set to false","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Applications credentials in configuration files","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Credential access","Lateral Movement"]},"id":"C-0012","controlID":"C-0012","creationTime":"","description":"Attackers who have access to configuration files can steal the stored secrets and use them. This control checks if ConfigMaps or pod specifications have sensitive information in their configuration.","remediation":"Use Kubernetes secrets or Key Management Systems to store credentials.","rules":[{"guid":"","name":"rule-credentials-in-env-var","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Credential access::Applications credentials in configuration files, Lateral Movement::Applications credentials in configuration files"},"creationTime":"","rule":"package armo_builtins\n# import data.cautils as cautils\n# import data.kubernetes.api.client as client\n\ndeny[msga] {\n\tpod := input[_]\n pod.kind == \"Pod\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n container := pod.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v has sensitive information in environment variables\", [pod.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n }\n}\n\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n container := wl.spec.template.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has sensitive information in environment variables\", [wl.kind, wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"passwd\",\"password\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n env := container.env[_]\n contains(lower(env.name), key_name)\n\tisNotReference(env)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Cronjob: %v has sensitive information in environment variables\", [wl.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n }\n}\n\n\n\nisNotReference(env)\n{\n\tnot env.valueFrom.secretKeyRef\n\tnot env.valueFrom.configMapKeyRef\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if Pods have sensitive information in configuration","remediation":"","ruleQuery":"armo_builtins"},{"guid":"","name":"rule-credentials-configmap","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Credential access::Applications credentials in configuration files, Lateral Movement::Applications credentials in configuration files"},"creationTime":"","rule":"package armo_builtins\n# import data.cautils as cautils\n# import data.kubernetes.api.client as client\n\n# fails if config map has keys with suspicious name\ndeny[msga] {\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n sensitive_key_names := {\"aws_access_key_id\", \"aws_secret_access_key\", \"azure_batchai_storage_account\", \"azure_batchai_storage_key\",\n \"azure_batch_account\", \"azure_batch_key\", \"pass\", \"username\", \"pwd\", \"cred\", \"token\", \"key\", \"cert\"}\n key_name := sensitive_key_names[_]\n map_secret := configmap.data[map_key]\n contains(lower(map_key), key_name)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}\n\n# fails if config map has values with suspicious content - not base 64\ndeny[msga] {\n sensitive_values := {\"BEGIN\", \"PRIVATE KEY\", \"eyJhbGciO\"}\n value := sensitive_values[_]\n\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n map_secret := configmap.data[map_key]\n contains(map_secret, value)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}\n\n# fails if config map has values with suspicious content - base 64\ndeny[msga] {\n sensitive_values := {\"BEGIN\", \"PRIVATE KEY\", \"eyJhbGciO\"}\n value := sensitive_values[_]\n\n\tconfigmap := input[_]\n configmap.kind == \"ConfigMap\"\n map_secret := configmap.data[map_key]\n decoded_secret := base64.decode(map_secret)\n contains(decoded_secret, value)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"this configmap has sensitive information: %v\", [configmap.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [configmap]\n\t\t}\n }\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["ConfigMap"]}],"ruleDependencies":[],"description":"fails if ConfigMaps have sensitive information in configuration","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Cluster-admin binding","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Privilege escalation"]},"id":"C-0035","controlID":"C-0035","creationTime":"","description":"Attackers who have cluster admin permissions (can perform any action on any resource), can take advantage of their privileges for malicious activities. This control determines which subjects have cluster admin permissions.","remediation":"You should apply least privilege principle. Make sure cluster admin permissions are granted only when it is absolutely necessary. Don't use subjects with such high permissions for daily operations.","rules":[{"guid":"","name":"rule-list-all-cluster-admins","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::Cluster-admin binding"},"creationTime":"","rule":"package armo_builtins\nimport data.cautils as cautils\n\n# input: roles\n# apiversion: v1\n# does: returns roles+ related subjects in rolebinding\n\ndeny[msga] {\n\troles := [role | role= input[_]; role.kind == \"Role\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"Role\"\n\trolebinding.roleRef.name == role.metadata.name\n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n }\n}\n\n# input: ClusterRole\n# apiversion: v1\n# does: returns clusterroles+ related subjects in rolebinding\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n \n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n }\n}\n\n# input: ClusterRole\n# apiversion: v1\n# does:\treturns clusterroles+ related subjects in clusterrolebinding\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"ClusterRoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanCreate(rule)\n\tcanCreateResources(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"The following %v: %v have high privileges, such as cluster-admin\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role,rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n\ncanCreate(rule) {\n\tcautils.list_contains(rule.verbs,\"*\")\n}\ncanCreateResources(rule){\n\tcautils.list_contains(rule.resources,\"*\")\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Role","ClusterRole","ClusterRoleBinding","RoleBinding"]}],"ruleDependencies":[{"packageName":"cautils"}],"description":"determines which users have cluster admin permissions","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Exec into container","attributes":{"armoBuiltin":true,"microsoftMitreColumns":["Execution"]},"id":"C-0002","controlID":"C-0002","creationTime":"","description":"Attackers with relevant permissions can run malicious commands in the context of legitimate containers in the cluster using ā€œkubectl execā€ command. This control determines which subjects have permissions to use this command.","remediation":"It is recommended to prohibit ā€œkubectl execā€ command in production environments. It is also recommended not to use subjects with this permission for daily cluster operations.","rules":[{"guid":"","name":"exec-into-container","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Privilege Escalation::Exec into container"},"creationTime":"","rule":"\npackage armo_builtins\nimport data.cautils as cautils\n\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n\t roles := [role | role= input[_]; role.kind == \"Role\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"Role\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"RoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\n# input: clusterrolebindings + rolebindings\n# apiversion: rbac.authorization.k8s.io/v1 \n# returns subjects that can exec into container\n\ndeny[msga] {\n roles := [role | role= input[_]; role.kind == \"ClusterRole\"]\n rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == \"ClusterRoleBinding\"]\n role:= roles[_]\n rolebinding := rolebindings[_]\n\n rule:= role.rules[_]\n\tcanExecToPodResource(rule)\n\tcanExecToPodVerb(rule)\n\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n subjects := rolebinding.subjects[_]\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following %v: %v, can exec into containers\", [subjects.kind, subjects.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n \t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [role, rolebinding],\n\t\t\t\"externalObjects\": {\n\t\t\t\t\"subject\" : [subjects]\n\t\t\t}\n\t\t}\n\t}\n}\n\ncanExecToPodVerb(rule) {\n\tcautils.list_contains(rule.verbs, \"create\")\n}\ncanExecToPodVerb(rule) {\n\tcautils.list_contains(rule.verbs, \"*\")\n}\n\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"pods/exec\")\n}\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"pods/*\")\n}\ncanExecToPodResource(rule) {\n\tcautils.list_contains(rule.resources,\"*\")\n}\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Role","ClusterRole","ClusterRoleBinding","RoleBinding"]}],"ruleDependencies":[{"packageName":"cautils"}],"description":"determines which users have permissions to exec into pods","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Dangerous capabilities","attributes":{"armoBuiltin":true},"id":"C-0028","controlID":"C-0028","creationTime":"","description":"Giving dangerous and unnecessary LINUX capabilities to a container can increase the impact of the container compromise. This control identifies all the PODs with dangerous capabilities such as SYS_ADMIN and others.","remediation":"Check and remove all unnecessary capabilities from the POD security context of the containers and use the exception mechanism to remove warnings where these capabilities are necessary.","rules":[{"guid":"","name":"dangerous-capabilities","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v have dangerous capabilities\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in workload: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in cronjob: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisDangerousCapabilities(container){\n dangerousCapabilities := [\"ALL\", \"SYS_ADMIN\", \"NET_ADMIN\", \"SYS_PTRACE\"]\n dangerousCapabilitie := dangerousCapabilities[_]\n contains(container.securityContext.capabilities.add[_], dangerousCapabilitie)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has dangrous capabilities","remediation":"Remove all dangerous capabilities which aren’t necessary for the container.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Insecure capabilities","attributes":{"armoBuiltin":true},"id":"C-0046","controlID":"C-0046","creationTime":"","description":"Giving insecure or excsessive capabilities to a container can increase the impact of the container compromise. This control identifies all the PODs with dangerous capabilities (see documentation pages for details).","remediation":"Remove all insecure capabilities which aren’t necessary for the container.","rules":[{"guid":"","name":"insecure-capabilities","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in pod: %v have dangerous capabilities\", [container.name, pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainer := wl.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in workload: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer := wl.spec.jobTemplate.spec.template.spec.containers[_]\n isDangerousCapabilities(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"container: %v in cronjob: %v have dangerous capabilities\", [container.name, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisDangerousCapabilities(container){\n insecureCapabilities := [\"CHOWN\", \"DAC_OVERRIDE\", \"FSETID\", \"FOWNER\", \"MKNOD\", \"NET_RAW\", \"SETGID\", \"SETUID\", \"SETFCAP\", \"NET_BIND_SERVICE\",\"SYS_CHROOT\",\"KILL\",\"AUDIT_WRITE\"]\n insecureCapabilitie := insecureCapabilities[_]\n contains(container.securityContext.capabilities.add[_], insecureCapabilitie)\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has insecure capabilities","remediation":"Remove all insecure capabilities which aren’t necessary for the container.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Linux hardening","attributes":{"armoBuiltin":true},"id":"C-0055","controlID":"C-0055","creationTime":"","description":"Containers may be given more privileges than they actually need. This can increase the potential impact of a container compromise.","remediation":"You can use AppArmor, Seccomp, SELinux and Linux Capabilities mechanisms to restrict containers abilities to utilize unwanted privileges.","rules":[{"guid":"","name":"linux-hardening","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod does not define linux security hardening \ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n isUnsafePod(pod)\n container := pod.spec.containers[_]\n isUnsafeContainer(container)\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not define any linux security hardening\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload does not define linux security hardening \ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n isUnsafeWorkload(wl)\n container := wl.spec.template.spec.containers[_]\n isUnsafeContainer(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Workload: %v does not define any linux security hardening\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# Fails if pod does not define linux security hardening \ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n isUnsafeCronJob(wl)\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isUnsafeContainer(container)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Cronjob: %v does not define any linux security hardening\", [wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisUnsafePod(pod){\n not pod.spec.securityContext.seccompProfile\n not pod.spec.securityContext.seLinuxOptions\n\tannotations := [pod.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\nisUnsafeContainer(container){\n not container.securityContext.seccompProfile\n not container.securityContext.seLinuxOptions\n not container.securityContext.capabilities.drop\n}\n\nisUnsafeWorkload(wl) {\n not wl.spec.template.spec.securityContext.seccompProfile\n not wl.spec.template.spec.securityContext.seLinuxOptions\n\tannotations := [wl.spec.template.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\nisUnsafeCronJob(cronjob) {\n not cronjob.spec.jobTemplate.spec.template.spec.securityContext.seccompProfile\n not cronjob.spec.jobTemplate.spec.template.spec.securityContext.seLinuxOptions\n\tannotations := [cronjob.spec.jobTemplate.spec.template.metadata.annotations[i] | annotaion = i; startswith(i, \"container.apparmor.security.beta.kubernetes.io\")]\n\tnot count(annotations) \u003e 0\n}\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container does not defien any linux security hardening","remediation":"Make sure you define at least one linux security hardening property out of Seccomp, SELinux or Capabilities.","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Ingress and Egress blocked","attributes":{"armoBuiltin":true},"id":"C-0030","controlID":"C-0030","creationTime":"","description":"Disable Ingress and Egress traffic on all pods wherever possible. It is recommended to define restrictive network policy on all new PODs, and then enable sources/destinations that this POD must communicate with.","remediation":"Define a network policy that restricts ingress and egress connections.","rules":[{"guid":"","name":"ingress-and-egress-blocked","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# For pods\ndeny[msga] {\n \t\tpods := [pod | pod= input[_]; pod.kind == \"Pod\"]\n\t\tnetworkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\t\tpod := pods[_]\n\t\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; podConnectedToNetworkPolicy(pod, networkpolicie)]\n\t\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\t\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not have ingress/egress defined\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n\n}\n\n# For pods\ndeny[msga] {\n \t\tpods := [pod | pod= input[_]; pod.kind == \"Pod\"]\n\t\tnetworkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\t\tpod := pods[_]\n\t\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; podConnectedToNetworkPolicy(pod, networkpolicie)]\n\t\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"Pod: %v does not have ingress/egress defined\", [pod.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n\n}\n\n# For workloads\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; wlConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# For workloads\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; wlConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# For Cronjobs\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; cronjobConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003e 0\n goodPolicies := [goodpolicie | goodpolicie= networkpoliciesConnectedToPod[_]; isIngerssEgressPolicy(goodpolicie)]\n\tcount(goodPolicies) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n# For Cronjobs\ndeny[msga] {\n wl := input[_]\n\twl.kind == \"CronJob\"\n networkpolicies := [networkpolicie | networkpolicie= input[_]; networkpolicie.kind == \"NetworkPolicy\"]\n\tnetworkpoliciesConnectedToPod := [networkpolicie | networkpolicie= networkpolicies[_]; cronjobConnectedToNetworkPolicy(wl, networkpolicie)]\n\tcount(networkpoliciesConnectedToPod) \u003c 1\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has Pods which don't have ingress/egress defined\", [wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\npodConnectedToNetworkPolicy(pod, networkpolicie){\n\tnetworkpolicie.metadata.namespace == pod.metadata.namespace\n count(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == pod.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\npodConnectedToNetworkPolicy(pod, networkpolicie){\n\tnetworkpolicie.metadata.namespace == pod.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\nwlConnectedToNetworkPolicy(wl, networkpolicie){\n\twl.metadata.namespace == networkpolicie.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\n\nwlConnectedToNetworkPolicy(wl, networkpolicie){\n\twl.metadata.namespace == wl.metadata.namespace\n\tcount(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == wl.spec.template.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\n\ncronjobConnectedToNetworkPolicy(cj, networkpolicie){\n\tcj.metadata.namespace == networkpolicie.metadata.namespace\n count(networkpolicie.spec.podSelector) == 0\n}\n\ncronjobConnectedToNetworkPolicy(cj, networkpolicie){\n\tcj.metadata.namespace == networkpolicie.metadata.namespace\n\tcount(networkpolicie.spec.podSelector) \u003e 0\n count({x | networkpolicie.spec.podSelector.matchLabels[x] == cj.spec.jobTemplate.spec.template.metadata.labels[x]}) == count(networkpolicie.spec.podSelector.matchLabels)\n}\n\nisIngerssEgressPolicy(networkpolicie) {\n list_contains(networkpolicie.spec.policyTypes, \"Ingress\")\n list_contains(networkpolicie.spec.policyTypes, \"Egress\")\n }\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob","NetworkPolicy"]}],"ruleDependencies":[],"description":"fails if there are no ingress and egress defined for pod","remediation":"Make sure you define ingress and egress policies for all your Pods","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Container hostPort","attributes":{"armoBuiltin":true},"id":"C-0044","controlID":"C-0044","creationTime":"","description":"Configuring hostPort limits you to a particular port, and if any two workloads that specify the same HostPort they cannot be deployed to the same node. Therefore, if the number of replica of such workload is higher than the number of nodes, the deployment will fail.","remediation":"Avoid usage of hostPort unless it is absolutely necessary. Use NodePort / ClusterIP instead.","rules":[{"guid":"","name":"container-hostPort","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container with hostPort\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n container := pod.spec.containers[_]\n\tisHostPort(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v has Host-port\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has container with hostPort\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isHostPort(container)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has container with hostPort\ndeny[msga] {\n \twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isHostPort(container)\n msga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\nisHostPort(container){\n\tports := container.ports[_]\n ports.hostPort\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"description":"fails if container has hostPort","remediation":"Make sure you do not configure hostPort for the container, if necessary use NodePort / ClusterIP","ruleQuery":"armo_builtins"}]},{"guid":"","name":"Network policies","attributes":{"armoBuiltin":true},"id":"C-0011","controlID":"C-0011","creationTime":"","description":"If no network policy is defined, attackers who gain access to a single container may use it to probe the network. This control lists all namespaces in which no network policies are defined.","remediation":"Define network policies or use similar network protection mechanisms.","rules":[{"guid":"","name":"internal-networking","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Lateral Movement::Container internal networking, Discovery::Network mapping"},"creationTime":"","rule":"package armo_builtins\n\n# input: network policies\n# apiversion: networking.k8s.io/v1\n# fails if no network policies are defined in a certain namespace\n\ndeny[msga] {\n\tnamespaces := [namespace | namespace = input[_]; namespace.kind == \"Namespace\"]\n\tnamespace := namespaces[_]\n\tpolicy_names := [policy.metadata.namespace | policy = input[_]; policy.kind == \"NetworkPolicy\"]\n\tnot list_contains(policy_names, namespace.metadata.name)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"no policy is defined for namespace %v\", [namespace.metadata.name]),\n\t\t\"alertScore\": 9,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [namespace]\n\t\t}\n\t}\n}\n\nlist_contains(list, element) {\n some i\n list[i] == element\n}","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["networkpolicies","namespaces"]}],"ruleDependencies":[],"description":"lists namespaces in which no network policies are defined","remediation":"","ruleQuery":"armo_builtins"}]},{"guid":"","name":"CVE-2021-25741 - Using symlink for arbitrary host file system access.","attributes":{"armoBuiltin":true},"id":"C-0058","controlID":"C-0058","creationTime":"","description":"A user may be able to create a container with subPath or subPathExpr volume mounts to access files \u0026 directories anywhere on the host filesystem. Following Kubernetes versions are affected: v1.22.0 - v1.22.1, v1.21.0 - v1.21.4, v1.20.0 - v1.20.10, version v1.19.14 and lower. This control checks the vulnerable versions and the actual usage of the subPath feature in all Pods in the cluster.","remediation":"To mitigate this vulnerability without upgrading kubelet, you can disable the VolumeSubpath feature gate on kubelet and kube-apiserver, or remove any existing Pods using subPath or subPathExpr feature.","rules":[{"guid":"","name":"Symlink-Exchange-Can-Allow-Host-Filesystem-Access","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n pod := input[_]\n pod.kind == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n isSubPathContainer(container)\n\n\tmsga := {\n\t\t\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in pod : %v with subPath/subPathExpr\", [current_version, container.name, pod.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, pod]},\n\t\t}\n}\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[_]\n isSubPathContainer(container)\n \n\tmsga := {\n\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in %v : %v with subPath/subPathExpr\", [current_version, container.name, wl.kind, wl.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, wl]},\n\t\t}\n}\n\n\n\ndeny[msga] {\n\tnodes := input[_]\n\tcurrent_version := nodes.status.nodeInfo.kubeletVersion\n isVulnerableVersion(current_version)\n wl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[_]\n isSubPathContainer(container)\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"You may be vulnerable to CVE-2021-25741. You have a Node with version: %v and the following container : %v in %v : %v with subPath/subPathExpr\", [current_version, container.name, wl.kind, wl.metadata.name]),\n\t\t\t\"alertObject\": {\"k8SApiObjects\": [nodes, wl]},\n\t\t}\n}\n\n\n\nisSubPathContainer(container){\n container.volumeMounts[_].subPath\n}\n\nisSubPathContainer(container){\n container.volumeMounts[_].subPathExpr\n}\n\nisVulnerableVersion(version){\n version \u003c= \"v1.19.14\"\n}\n\nisVulnerableVersion(version){\n version \u003e= \"v1.22.0\"\n version \u003c= \"v1.22.1\"\n}\n\n\nisVulnerableVersion(version){\n version \u003e= \"v1.21.0\"\n version \u003c= \"v1.21.4\"\n}\n\n\nisVulnerableVersion(version){\n version \u003e= \"v1.20.0\"\n version \u003c= \"v1.20.9\"\n}\n\nisVulnerableVersion(version){\n\tversion == \"v1.20.10\"\n}\n\n\n","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob","Node"]}],"ruleDependencies":[],"description":"A user may be able to create a container with subPath volume mounts to access files \u0026 directories outside of the volume, including on the host filesystem. This was affected at the following versions: v1.22.0 - v1.22.1, v1.21.0 - v1.21.4, v1.20.0 - v1.20.10, version v1.19.14 and lower. ","remediation":"To mitigate this vulnerability without upgrading kubelet, you can disable the VolumeSubpath feature gate on kubelet and kube-apiserver, and remove any existing Pods making use of the feature.","ruleQuery":"armo_builtins"}]}]} \ No newline at end of file diff --git a/resultshandling/results.go b/resultshandling/results.go index 39258dc2..2db5e8f0 100644 --- a/resultshandling/results.go +++ b/resultshandling/results.go @@ -27,7 +27,7 @@ func (resultsHandler *ResultsHandler) HandleResults(scanInfo cautils.ScanInfo) f score := resultsHandler.printerObj.ActionPrint(opaSessionObj) // Don't send report for control scan - if scanInfo.FrameworkScan { + if scanInfo.FrameworkScan { // TODO - use interface for ActionSendReportListenner resultsHandler.reporterObj.ActionSendReportListenner(opaSessionObj) } From f6c03ed7a2af6d2d18716fd3d2c5f9679ef9c927 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 16:50:59 +0300 Subject: [PATCH 33/37] fix offline support --- policyhandler/handlenotification.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go index 54bccf13..76ecbb6e 100644 --- a/policyhandler/handlenotification.go +++ b/policyhandler/handlenotification.go @@ -56,9 +56,7 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *repo return fmt.Errorf("empty list of resources") } opaSessionObj.K8SResources = k8sResources - if opaSessionObj.PostureReport.ClusterAPIServerInfo, err = policyHandler.k8s.KubernetesClient.Discovery().ServerVersion(); err != nil { - cautils.ErrorDisplay(fmt.Sprintf("Failed to discover API server inforamtion: %v", err)) - } + // update channel *policyHandler.processPolicy <- opaSessionObj return nil @@ -86,7 +84,10 @@ func (policyHandler *PolicyHandler) getPolicies(notification *reporthandling.Pol func (policyHandler *PolicyHandler) getResources(notification *reporthandling.PolicyNotification, opaSessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) (*cautils.K8SResources, error) { var k8sResources *cautils.K8SResources var err error - if k8sinterface.ConnectedToCluster { + if k8sinterface.ConnectedToCluster { // TODO - use interface + if opaSessionObj.PostureReport.ClusterAPIServerInfo, err = policyHandler.k8s.KubernetesClient.Discovery().ServerVersion(); err != nil { + cautils.ErrorDisplay(fmt.Sprintf("Failed to discover API server inforamtion: %v", err)) + } k8sResources, err = policyHandler.getK8sResources(opaSessionObj.Frameworks, ¬ification.Designators, scanInfo.ExcludedNamespaces) } else { k8sResources, err = policyHandler.loadResources(opaSessionObj.Frameworks, scanInfo) From 2725923b9bd5259996bf14f1acf1073de3fa7a26 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 16:58:09 +0300 Subject: [PATCH 34/37] case insensitive --- clihandler/cmd/download.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clihandler/cmd/download.go b/clihandler/cmd/download.go index ced71411..c0c3b6c9 100644 --- a/clihandler/cmd/download.go +++ b/clihandler/cmd/download.go @@ -24,7 +24,7 @@ var downloadCmd = &cobra.Command{ }, RunE: func(cmd *cobra.Command, args []string) error { if strings.EqualFold(args[0], "framework") { - downloadInfo.FrameworkName = args[1] + downloadInfo.FrameworkName = strings.ToLower(args[1]) g := getter.NewDownloadReleasedPolicy() if downloadInfo.Path == "" { downloadInfo.Path = getter.GetDefaultPath(downloadInfo.FrameworkName + ".json") @@ -38,7 +38,7 @@ var downloadCmd = &cobra.Command{ return err } } else if strings.EqualFold(args[0], "control") { - downloadInfo.ControlName = args[1] + downloadInfo.ControlName = strings.ToLower(args[1]) g := getter.NewDownloadReleasedPolicy() if downloadInfo.Path == "" { downloadInfo.Path = getter.GetDefaultPath(downloadInfo.ControlName + ".json") From 47183c405fb41d2c86a7d87597ba838d68e1c074 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 17:29:25 +0300 Subject: [PATCH 35/37] add some comments --- cautils/getter/downloadreleasedpolicy.go | 1 + go.sum | 286 ----------------------- policyhandler/handlepullpolicies.go | 12 +- 3 files changed, 2 insertions(+), 297 deletions(-) diff --git a/cautils/getter/downloadreleasedpolicy.go b/cautils/getter/downloadreleasedpolicy.go index 028597ff..944c1bd1 100644 --- a/cautils/getter/downloadreleasedpolicy.go +++ b/cautils/getter/downloadreleasedpolicy.go @@ -22,6 +22,7 @@ func NewDownloadReleasedPolicy() *DownloadReleasedPolicy { } } +// Return control per name/id using ARMO api func (drp *DownloadReleasedPolicy) GetControl(policyName string) (*reporthandling.Control, error) { var control *reporthandling.Control var err error diff --git a/go.sum b/go.sum index 70c49bd5..3de6d8cf 100644 --- a/go.sum +++ b/go.sum @@ -26,40 +26,27 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF 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 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= 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 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= 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 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= 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 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3 h1:hJiie5Bf3QucGRa4ymsAUOxyhYwGEz1xrsVk0P8erlw= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0 h1:SPOUaucgtVls75mg+X7CXigS71EnsfVUK/2CgVrwqgw= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412 h1:GvWw74lx5noHocd+f6HBMXK6DuggBB1dhVkuGZbv7qM= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c h1:ivON6cwHK1OH26MZyWDCnbTRZZf0IhNsENoNAKFS1g4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6 h1:K72hopUosKG3ntOPNG4OzzbuhxGuVf06fa2la1/H/Ho= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:OR8VhtwhcAI3U48/rzBsVOuHi0zDPzYI1xASVcdSgR8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -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/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -75,40 +62,26 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af h1:wVe6/Ea46ZMeNkQjjBW6xcqyQA/j5e0D6GytH95g0gQ= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= 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 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armosec/armoapi-go v0.0.2/go.mod h1:vIK17yoKbJRQyZXWWLe3AqfqCRITxW8qmSkApyq5xFs= github.com/armosec/armoapi-go v0.0.7 h1:SN13+iYrIkxgatU+MwuWnSlhxP1G7rZP7dC8us2I7v0= @@ -122,88 +95,59 @@ github.com/armosec/utils-go v0.0.3 h1:uyQI676yRciQM0sSN9uPoqHkbspTxHO0kmzXhBeE/x github.com/armosec/utils-go v0.0.3/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= github.com/armosec/utils-k8s-go v0.0.1 h1:Ay3y7fW+4+FjVc0+obOWm8YsnEvM31vPAVoKTyTAFRk= github.com/armosec/utils-k8s-go v0.0.1/go.mod h1:qrU4pmY2iZsOb39Eltpm0sTTNM3E4pmeyWx4dgDUC2U= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.41.1 h1:TR9j7i73tzV8ELPMc0LkImSRLljRJ+gQeArKBC7IfVE= github.com/aws/aws-sdk-go v1.41.1/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625 h1:ckJgFhFWywOx+YLEMIJsTb+NV6NexWICk5+AMSuz3ss= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/briandowns/spinner v1.16.0 h1:DFmp6hEaIx2QXXuqSJmtfSBSAjRmpGiKG6ip2Wm/yOs= github.com/briandowns/spinner v1.16.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bytecodealliance/wasmtime-go v0.30.0 h1:WfYpr4WdqInt8m5/HvYinf+HrSEAIhItKIcth+qb1h4= github.com/bytecodealliance/wasmtime-go v0.30.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= 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 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= 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/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -212,12 +156,9 @@ github.com/dgraph-io/badger/v3 v3.2103.1 h1:zaX53IRg7ycxVlkd5pYdCeFp1FynD6qBGQoQ github.com/dgraph-io/badger/v3 v3.2103.1/go.mod h1:dULbq6ehJ5K0cGW/1TQ9iSfUk0gbSiToDWmWmTsJ53E= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -225,14 +166,11 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= @@ -241,9 +179,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m 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 h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= 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 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= @@ -251,12 +187,9 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= @@ -269,39 +202,26 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1 h1:wBrPaMkrXFBW3qXpXAjiKljdVUMxn9bX2ia3XjPHoik= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0 h1:UlZlgrvvmT/58o573ot7NFw0vZasZ5I6bcIft/oMdgg= github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= 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 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gota/gota v0.12.0 h1:T5BDg1hTf5fZ/CO+T/N0E+DDqUhvoKBl+UVckgcAAQg= github.com/go-gota/gota v0.12.0/go.mod h1:UT+NsWpZC/FhaOyWb9Hui0jXg0Iq8e/YugZHTbyW/34= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07 h1:OTlfMvwR1rLyf9goVmXfuS5AJn80+Vmj4rTf4n46SOs= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -310,21 +230,15 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 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/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -333,7 +247,6 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= @@ -344,7 +257,6 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er 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/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 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= @@ -353,7 +265,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt 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 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= 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= @@ -378,7 +289,6 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= @@ -395,17 +305,13 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= 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 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= 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= @@ -417,152 +323,99 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf 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 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -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.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/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-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= 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 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= 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 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1 h1:ujPKutqRlJtcfWk6toYVYagwra7HQHbXOaS171b4Tg8= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -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/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 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/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3 h1:/Um6a/ZmD5tF7peoOJ5oN5KMQ0DrGVQSXLNwyckutPk= github.com/kr/pty v1.1.3/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/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -576,30 +429,19 @@ github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= 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 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -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/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= 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= @@ -608,23 +450,17 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -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/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/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/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 h1:D6paGObi5Wud7xg83MaEFyjxQB1W5bz5d0IFppr+ymk= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -645,32 +481,22 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= 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 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= 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/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d h1:zapSxdmZYY6vJWXFKLQ+MkI+agc+HQyfrCGowDSHiKs= github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/phpdave11/gofpdf v1.4.2 h1:KPKiIbfwbvC/wOncwhrpRdXVj2CZTCFlw4wnoyjtHfQ= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12 h1:RZb9NG62cw/RW0rHAduVRo+98R8o/G1krcg2ns7DakQ= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= 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 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc= 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 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= @@ -680,12 +506,10 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP 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.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= 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.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -693,116 +517,73 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 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.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4 h1:Fth6mevc5rX7glNLpbAMJnqKlfIkcTjZCSHEeqvKbcI= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48 h1:vabduItPAIz9px5iryD5peyx7O3Ya8TBThapgXim98o= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470 h1:qb9IthCFBmROJ6YBS31BEMeSYjOscSiG+EO+JVNTz64= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d h1:Yoy/IzG4lULT6qZg62sVC+qyBL8DQkmD2zv6i7OImrc= github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c h1:UOk+nlt1BJtTcH15CT7iNO7YVWTfTv/DNwEAQHLIaDQ= github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b h1:vYEG87HxbU6dXj5npkeulCS96Dtz5xg3jcfCgpcvbIw= github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20 h1:7pDq9pAMCQgRohFmd25X8hIH8VxmT3TaDm+r9LHxgBk= github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9 h1:MPblCbqA5+z6XARjScMfz1TqtJC7TuTRj0U9VqIBs6k= github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50 h1:crYRwvwjdVh1biHzzciFHe8DrZcYrVcZFlJtykhRctg= github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc h1:eHRtZoIi6n9Wo1uR+RU44C247msLWwyA89hVKwRLkMk= github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9 h1:fxoFD0in0/CBzXoyNhMTjvBZYW6ilSnTw7N7y/8vkmM= github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191 h1:T4wuULTrzCKMFlg3HmKHgXAF8oStFb/+lOIupLV2v+o= github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241 h1:Y+TeIabU8sJD10Qwd/zMty2/LEaT9GNDaA6nyZf+jgo= github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122 h1:TQVQrsyNaimGwF7bIhzoVC9QkKm4KsWd8cECGzFx8gI= github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2 h1:bu666BQci+y4S0tVRVjsHUeRon6vUXmsGBwdowgMrg4= github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82 h1:LneqU9PHDsg/AkPDU3AkqMxnMYL+imaqkpflHu73us8= github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537 h1:YGaxtkYjb8mnTvtufv2LKLwCQu2/C7qFB7UtrOlTWOY= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133 h1:JtcyT0rk/9PKOdnKQzuDR+FSjh7SGtJwpgVpfZBRKlQ= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 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/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= 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 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -810,12 +591,9 @@ 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.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -824,26 +602,18 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/viant/assertly v0.4.8 h1:5x1GzBaRteIwTr5RAGFVG14uNeRFxVNbXPWrK2qAgpc= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0 h1:6TteTDQ68CjgcCe8wH3D3ZhUQQOJXMTbj/D9rkk2a1k= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= 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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY= github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co= @@ -851,24 +621,15 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= 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 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -879,34 +640,21 @@ 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 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0= go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= @@ -919,9 +667,7 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d h1:E2M5QgjZ/Jg+ObCQAudsXxuTsLj7Nl5RV/lZcQZmKSo= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= 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= @@ -960,7 +706,6 @@ golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030 h1:lP9pYkih3DUSC641giIXa2XqfTIbbbRr0w2EOTA7wHA= golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -974,10 +719,8 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= 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 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= 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= @@ -987,7 +730,6 @@ 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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= @@ -1059,7 +801,6 @@ golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852 h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 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= @@ -1071,7 +812,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ 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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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= @@ -1225,14 +965,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f 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.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -1241,7 +979,6 @@ gonum.org/v1/gonum v0.9.1/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0 h1:3sEo36Uopv1/SA/dMFFaxXoL5XyikJ9Sf2Vll/k6+2E= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= @@ -1267,7 +1004,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= 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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1325,7 +1061,6 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D 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 h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1350,7 +1085,6 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG 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.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 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= @@ -1366,25 +1100,19 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 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.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= @@ -1408,7 +1136,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/x4yG7qPBrtNfLY= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1417,24 +1144,18 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh 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 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nKuewd4= k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apiserver v0.22.2 h1:TdIfZJc6YNhu2WxeAOWq1TvukHF0Sfx0+ln4XK9qnL4= k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/code-generator v0.22.2 h1:+bUv9lpTnAWABtPkvO4x0kfz7j/kDEchVt0P/wXU3jQ= k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= -k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M= k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= @@ -1444,15 +1165,10 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 h1:fmRfl9WJ4ApJn7LxNuED4m0t18qivVQOxP6aAYG9J6c= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.10.2 h1:jW8qiY+yMnnPx6O9hu63tgcwaKzd1yLYui+mpvClOOc= sigs.k8s.io/controller-runtime v0.10.2/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= @@ -1461,7 +1177,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3 sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/go-diff v0.5.0 h1:eTiIR0CoWjGzJcnQ3OkhIl/b9GJovq4lSAVRt0ZFEG8= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/policyhandler/handlepullpolicies.go b/policyhandler/handlepullpolicies.go index 1410e879..0762a05e 100644 --- a/policyhandler/handlepullpolicies.go +++ b/policyhandler/handlepullpolicies.go @@ -68,6 +68,7 @@ func (policyHandler *PolicyHandler) getFrameworkPolicies(policyName string) (*re return receivedFramework, receivedException, nil } +// Get control by name func (policyHandler *PolicyHandler) getControl(policyName string) ([]reporthandling.Control, []armotypes.PostureExceptionPolicy, error) { controls := []reporthandling.Control{} @@ -88,14 +89,3 @@ func (policyHandler *PolicyHandler) getControl(policyName string) ([]reporthandl return controls, exceptions, nil } - -func findControlInFrameworks(frameworks []reporthandling.Framework, controlName string) *reporthandling.Control { - for _, framework := range frameworks { - for _, control := range framework.Controls { - if strings.EqualFold(control.Name, controlName) || strings.EqualFold(control.ControlID, controlName) { - return &control - } - } - } - return nil -} From eb9fe85c753b2816e5b6cd97905bfd18ecb9a818 Mon Sep 17 00:00:00 2001 From: Daniel-GrunbergerCA Date: Wed, 20 Oct 2021 17:45:11 +0300 Subject: [PATCH 36/37] add error handling --- cautils/getter/getpoliciesutils.go | 1 + cautils/getter/loadpolicy.go | 1 + clihandler/cmd/download.go | 5 ++++- clihandler/cmd/scan.go | 12 ++++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/cautils/getter/getpoliciesutils.go b/cautils/getter/getpoliciesutils.go index 55a4bc2d..7949eb70 100644 --- a/cautils/getter/getpoliciesutils.go +++ b/cautils/getter/getpoliciesutils.go @@ -21,6 +21,7 @@ func GetDefaultPath(name string) string { return defaultfilePath } +// Save control as json in file func SaveControlInFile(control *reporthandling.Control, pathStr string) error { encodedData, err := json.Marshal(control) if err != nil { diff --git a/cautils/getter/loadpolicy.go b/cautils/getter/loadpolicy.go index f0553f45..c976a478 100644 --- a/cautils/getter/loadpolicy.go +++ b/cautils/getter/loadpolicy.go @@ -26,6 +26,7 @@ func NewLoadPolicy(filePath string) *LoadPolicy { } } +// Return control from file func (lp *LoadPolicy) GetControl(controlName string) (*reporthandling.Control, error) { control := &reporthandling.Control{} diff --git a/clihandler/cmd/download.go b/clihandler/cmd/download.go index c0c3b6c9..6ed2dadf 100644 --- a/clihandler/cmd/download.go +++ b/clihandler/cmd/download.go @@ -18,7 +18,10 @@ var downloadCmd = &cobra.Command{ Long: ``, Args: func(cmd *cobra.Command, args []string) error { if len(args) != 2 { - return fmt.Errorf("requires two arguments : framework ") + return fmt.Errorf("requires two arguments : framework/control /") + } + if !strings.EqualFold(args[0], "framework") && !strings.EqualFold(args[0], "control") { + return fmt.Errorf("invalid parameter '%s'. Supported parameters: framework, control", args[0]) } return nil }, diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index 13d2da22..e86e5a02 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -1,6 +1,9 @@ package cmd import ( + "fmt" + "strings" + "github.com/armosec/kubescape/cautils" "github.com/spf13/cobra" ) @@ -12,6 +15,15 @@ var scanCmd = &cobra.Command{ Use: "scan ", Short: "Scan the current running cluster or yaml files", Long: `The action you want to perform`, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return fmt.Errorf("requires one argument: framework/control") + } + if !strings.EqualFold(args[0], "framework") && !strings.EqualFold(args[0], "control") { + return fmt.Errorf("invalid parameter '%s'. Supported parameters: framework, control", args[0]) + } + return nil + }, Run: func(cmd *cobra.Command, args []string) { }, } From a90177e7c0e11a8fcf2d822aefb4afb53c195cf7 Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 21 Oct 2021 09:56:05 +0300 Subject: [PATCH 37/37] update go mod file --- .gitignore | 1 + go.mod | 76 +++++++++++++++++++++++++++++++++++++++++++++++++----- go.sum | 18 +++++++------ 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 24f45ac4..bf33394d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.vs* *kubescape* *debug* +*vender* .idea \ No newline at end of file diff --git a/go.mod b/go.mod index a60200c2..0e3cbc03 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,16 @@ module github.com/armosec/kubescape go 1.17 require ( + github.com/armosec/armoapi-go v0.0.8 + github.com/armosec/k8s-interface v0.0.5 + github.com/armosec/opa-utils v0.0.13 + github.com/armosec/utils-go v0.0.3 github.com/briandowns/spinner v1.16.0 github.com/enescakir/emoji v1.0.0 - github.com/fatih/color v1.12.0 - github.com/gofrs/uuid v4.0.0+incompatible + github.com/fatih/color v1.13.0 + github.com/gofrs/uuid v4.1.0+incompatible github.com/golang/glog v1.0.0 - github.com/mattn/go-isatty v0.0.13 + github.com/mattn/go-isatty v0.0.14 github.com/olekukonko/tablewriter v0.0.5 github.com/open-policy-agent/opa v0.33.1 github.com/satori/go.uuid v1.2.0 @@ -20,8 +24,66 @@ require ( ) require ( - github.com/armosec/armoapi-go v0.0.7 - github.com/armosec/k8s-interface v0.0.5 - github.com/armosec/opa-utils v0.0.13 - github.com/armosec/utils-go v0.0.3 + cloud.google.com/go v0.81.0 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.18 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/armosec/utils-k8s-go v0.0.1 // indirect + github.com/coreos/go-oidc v2.2.1+incompatible // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/docker/docker v20.10.9+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect + github.com/francoispqt/gojay v1.2.13 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-gota/gota v0.12.0 // indirect + github.com/go-logr/logr v0.4.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.5 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/json-iterator/go v1.1.11 // indirect + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pquerna/cachecontrol v0.1.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.19.1 // indirect + golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect + golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect + golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 // indirect + golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/text v0.3.6 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect + gonum.org/v1/gonum v0.9.1 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + k8s.io/klog/v2 v2.9.0 // indirect + k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect + sigs.k8s.io/controller-runtime v0.10.2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 3de6d8cf..842bf3e4 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,9 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 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/armosec/armoapi-go v0.0.2/go.mod h1:vIK17yoKbJRQyZXWWLe3AqfqCRITxW8qmSkApyq5xFs= -github.com/armosec/armoapi-go v0.0.7 h1:SN13+iYrIkxgatU+MwuWnSlhxP1G7rZP7dC8us2I7v0= github.com/armosec/armoapi-go v0.0.7/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= +github.com/armosec/armoapi-go v0.0.8 h1:JPa9rZynuE2RucamDh6dsy/sjCScmWDsyt1zagJFCDo= +github.com/armosec/armoapi-go v0.0.8/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.5 h1:DWQXZNMSsYQeLQ6xpB21ueFMR9oFnz28iWQTNn31TAk= github.com/armosec/k8s-interface v0.0.5/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= github.com/armosec/opa-utils v0.0.13 h1:QkmmYX0lzC7ZNGetyD8ysRKQHgJhjMfvRUW2cp+hz2o= @@ -185,8 +186,8 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +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.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -240,8 +241,9 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= +github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 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.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -419,13 +421,13 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=